I am working on a problem that requires me to input a float with exactly 2 digits of precision.
I know how to print a float with two digits of precision but how can I input a float under this condition? I think this is the problem with my program because there is no compilation error as such but it just says wrong answer. I am working with C language.
I tried to read an int and a float with two digits of precision as required the following way:
int x;
float balance,y;
scanf("%d %.2f",&x,&y);
For complete references, here are the question and my solution
There is a problem in proposed solution. According to cplusplus.com, the format f only accepts a width and no precision.
If you had controlled the return from the scanf (what you should definitively always do - and now you know why !) you would have seen immediately the problem :
int x, cr;
float balance,y;
cr = scanf("%d %.2f",&x,&y);
if (cr != 2) {
fprintf(stderr, "Read error : cr = %d\n", cr);
}
Given any input, you will get :
Read error : cr = 1
Possible implementation with very little change :
cr = scanf("%d %f",&x,&y);
if (cr != 2) {
fprintf(stderr, "Read error : cr = %d\n", cr);
}
// should round to only two digits - within floating point accuracy
y = (((double)((int)(y * 100 + 0.5))) / 100.);
If you have a system where math.h contains round (not MSVC :-( ), last line is better written as (thanks to chux for proposing it) :
y = round(y * 100)/100
because above formula will fail for negative y and for y > INT_MAX / 100
If you really needed exact precision with two decimal digit, the correct way would be to do all computation as integer on long, taking the numbers multiplied by 100. I leave that as an exercise for the reader :-)
This answer inputs a float then checks it was in the correct format. But If you are working with money you should be using int cents; unless you have megabucks and don't care about cents, or are working to fractions of a penny (in which case you could work in 10th of a penny).
#include <stdio.h>
#include <string.h>
#define BUFLEN 20
int main()
{
float money;
char buff[BUFLEN+1], bank[BUFLEN+1], *eptr;
printf ("Input the money: ");
if (fgets(buff, BUFLEN, stdin) == NULL) {
printf("Failed input\n");
return 1;
}
if ((eptr = strchr (buff, '\n')) != NULL) // newline?
*eptr = 0; // terminate
if (sscanf(buff, "%f", &money) != 1) { // get the money
printf("Failed input\n");
return 1;
}
sprintf(bank, "%0.2f", money); // check format of entry
if (strcmp(bank, buff)) {
printf("2 digit precision please: Euros.cents\n");
return 1;
}
printf("You paid %s\n", bank);
return 0;
}
Related
Want to elicit average of entered real value,until negative value is entered.
My problem is
My calculation don't quit when negative value is entered
It keep asks printf sentence for 3 time.
What did I do wrong?
#include <stdio.h>
int main(void)
{
double total = 0.0;
double input=0.0;
int num = 0;
for (; input >= 0.0;)
{
total += input;
printf("real number(minus to quit):");
scanf_s("%1f", &input);
num++;
}
printf("average:%f \n", total / (num - 1));
return 0;
}
you have many problems with your code :
it's not %1f in the line scanf_s("%1f", &total); as %1f will give you undefined behavior , it's %lfas you are scanning a double , there is a big difference between number one and lower case L
the function called scanf returns an integer indicating how many elements could be assigned to the input that the user entered , so , you should do if(scanf_s("%lf", &input) == 1) to check if the assignment done successfully, that will help you in detecting if - is entered instead of the number
if the user entered a lonely - then sacnf will fail to convert and you have to take another approach
when you are printing the average in this line : printf("average:%f \n", total / (num - 1)); , you actually prints a double , so it's %lf instead of %f
the condition of the for loop is incorrect , you are saying for (; input >= 0.0;) but this will prevent you from entering any negative values as when entering a negative value , the for loop will break , so you could use while(1) instead of the for loop and only break when a - is entered alone
so here is my edited version of yours , I introduced a dummy string to read the buffer and check whether the input was a lonely - or not , and if not then I try to convert it to double and here is my edited solution :
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char dummy[30];
double total = 0.0;
int num = 0;
double DecimalConverted = 0;
while(1)
{
printf("real number(minus to quit):");
fgets(dummy, 30, stdin); // gets the input into the buffer
if(dummy[0] == '-' && dummy[1] == '\n') // break from the loop on condition that '-' only entered
break;
// convert the string to decimal
DecimalConverted = strtod(dummy ,NULL);
if(DecimalConverted == 0)
printf("not a number\n");
else{
total += DecimalConverted;
num++;
}
}
printf("average:%lf \n", total / (num - 1));
return 0;
}
and here is the output :
real number(minus to quit):12
real number(minus to quit):-51
real number(minus to quit):-
average:-39.000000
The task goes like this:
Write a program that calculates the power of a number (as a pow function from the "math.h" library), except the limitation here is that the exponent can only be an integer. The base and exponent are entered from the keyboard, where the base can be of the real type, while the exponent is a positive or negative integer. Attention should be paid to checking data entry; special treatment should be given to cases where the number is not entered and when the number entered is not an integer when entering the exponent!
Example input/output:
Enter a base number: abc
You didn't enter a number!
Enter a base number: 3.3
Enter exponent: something
You didn't enter a number!
Enter a base number: 3.3
Enter exponent: 5
3.3^5 = 391.354
Enter a base number: 12
Enter exponent: 2.5
Entered number is not an integer!
This is my code so far:
#include <stdio.h>
int main() {
double base, result = 1;
int exp, i;
printf("Enter a base number: ");
scanf("%lf", &base);
printf("Enter exponent: ");
scanf("%d", &exp);
for (i=1; i<=exp; i++) {
result *= base;
}
printf("%.2lf^%d = %.2lf", base,exp,result);
return 0;
}
It calculates the power of n successfully. But how do I add the "You didn't enter a number!" text when the input is wrong. Also, some results should be printed with 3 decimals, some with 6, etc.(depends on the result).
... how do I add the "You didn't enter a number!" text when the input is wrong.
To validate that a line of input is a double:
Do not use scanf() anywhere until you know why it is bad.
Instead, read the line of user input with fgets() which forms a string.
char buf[1024]; // Ample size buffer for very large and tiny precise values.
if (fgets(buf, sizeof buf, stdin)) {
double x;
int error_code = validate_double(buf, &x);
if (error_code == 0) printf("%.17g\n", x);
else printf("Error %d, invalid double <%s>\n", error_code, buf);
}
Validate with strdod()
int validate_double(const char *buf, double *x) {
errno = 0;
char *endptr;
*x = strtod(buf, &endptr);
if (buf == endptr) return 1; // Non numeric input
// First skip over trailing white-space
while (isspace(((const unsigned char *)endptr)[0])) {
endptr++;
}
if (*endptr) return 2; // Junk after numeric input
if (errno == ERANGE && (*x > 1.0 || *x < -1.0)) { // overflow
return 0; // or maybe 3 if you want to flag this
}
if (errno == ERANGE && (*x <= 1.0 && *x >= -1.0)) { // underflow
return 0; // or maybe 4 if you want to flag this
}
return 0;
}
To validate input is an integer, could use strtol() or the above and simply add.
double expo;
int error_code = validate_double(buf, &expo);
if (error_code == 0) {
if (!(expo >= 0.0 && expo <= INT_MAX && (int)expo == expo)) {
error_code = 5; // Out of +int range or non-integer.
}
}
... some results should be printed with 3 decimals, some with 6, etc.(depends on the result).
Try printing with %g with ample precision. This format does not print trailing precision '0' digits.
printf("%.17g\n", result);
Your exponentiation algorithm is [very] inefficient:
for (i = 1; i <= exp; i++) {
result *= base;
}
It is the equivalent of doing multiplication by repetitive addition.
To do it efficiently, do "exponentiation by squaring". See: https://en.wikipedia.org/wiki/Exponentiation_by_squaring
Change your loop to:
for (i = exp; i != 0; i /= 2) {
if (i % 2)
result *= base;
base *= base;
}
Also, look at the xpow function in the second code block of my recent answer: What's the problem in the code which was supposed to print Armstrong numbers up to 999
I am trying to make a program that calculate the width or how many numbers a float contains. I need this to make good looking outputs in console. For example, the width of the following numbers are:
4 (1)
23 (2)
0.3 (3 because the . has the width of one)
0.45 (4)
12.34 (5)
0 (1)
I have tried to check if the number == 0 then the width is 1 and done, and else multiply the number with 10 until there is no decimals float == (int)float and then calculating how many times it is needed to divide by 10 to get a number float < 0. I have tried everything I have found at the internet without any real luck...
Just use snprintf for counting length of what you want to print, like this:
int main()
{
float num;
int len;
if (1 == scanf("%f", &num)) {
len = snprintf(NULL, 0, "%g", num);
printf("%g (%d)\n", num, len);
}
return 0;
}
You could try to convert float to the string.
You may use snprintf or something similar for your needs.
The precision of the conversion of the snprintf may not be best.
You may want to limit number of characters after the '.'.
#include <stdio.h>
#include <string.h>
int main(void)
{
float num = -12345.678;
char str[32];
size_t counter = 0;
// freestyle solution
int len;
printf("Please input the number:\n");
if (1 == scanf("%f", &num)) {
len = snprintf(NULL, 0, "%g", num);
printf("\%g (%d)\n", num, len);
}
//sg7: improved one - '.' and '-' counted.
len = snprintf(str, 32, "%f", num);
printf("\n%s Number of characters: %zu",str, len);
return 0;
}
Test:
Please input the number:
-12.345678
-12.3457 (8)
-12.345678 Number of characters: 10
Assuming your float is stored in the variable f, you can do this:
int width; char buffer[50];
width = sprintf(buffer,"%f",f);
Please keep in mind that floats are usually stored with a precision of six digits after the decimal point, so a number like 14.2 is stored as 14.200000 thus having a width of 9 instead of 4. It might be stored as 13.999999 as well so keep that in mind.
I am trying to write a code in C (gcc) to accept only floating numbers with decimals and reject integers, special characters, alphanumeric entry.
Valid entries are:
1.23, 3.45, 6.77
Invalid entries:
abc, e34, 834ww, 6, 9,
and some blah things that is not a float.
This is what I have tried:
#include <stdio.h>
int main()
{
double floatnum;
double decpart=0.000000;
printf("Enter a floating number num: ");
while (decpart == 0.0000000)
{
scanf("%lf", &floatnum);
int intpart = (int)floatnum;
double decpart = floatnum - intpart;
if (decpart == 0.000000){
printf("Invalid floating point number, enter again: ");
}
else
{
printf("Number entered = %.2f\n", floatnum);
break;
}
}
return 0;
}
I don't want exact code, but I need some pointers/clues on what would be the best way to achieve that.
I reworked your code dropping the scanf part and replacing it by a combination of fgets and strtod.
Checks done:
valid number entered (by checking if the endptr returned by strtod points on the linefeed char, meaning that the whole entered string has been parsed properly): avoids invalid numbers AND forms like 42.4xxxx accepted by atof for instance
if trailing space is added after single number it is replaced by linefeed, and thus accepted by the program
your decimal checking code, unchanged
the program lets numbers like 12.455e+1 pass (124.55), well maybe it's a feature rather than a bug since it's valid as a float.
fixed code:
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
int main()
{
double decpart;
printf("Enter a floating number num: ");
char buf[100];
int len;
char *endptr;
while (fgets(buf,sizeof(buf),stdin) != NULL)
{
len = strlen(buf)-1;
// right strip spaces (replace by linefeed like fgets ends the input)
while (len>0)
{
len--;
if (buf[len]==' ')
{
buf[len]='\n';
}
else
{
break;
}
}
double floatnum = strtod(buf,&endptr);
if ((endptr==buf)||(endptr[0]!='\n'))
{
printf("Invalid floating point number, enter again: ");
}
else
{
int intpart = (int)floatnum;
double decpart = floatnum - intpart;
if (decpart == 0.000000){
printf("Invalid floating point number, enter again: ");
}
else
{
printf("Number entered = %.2f\n", floatnum);
break;
}
}
}
return 0;
}
tests:
Enter a floating number num: no
Invalid floating point number, enter again: 45
Invalid floating point number, enter again: 45.6xxx
Invalid floating point number, enter again: 45.6
Number entered = 45.60
As you commented above that you are taking input one char at a time then you could count the number of decimals and characters while taking input and then check if count_alpha>0 and count_dots>1 then its not valid else its valid.
I don't want exact code, but I need some pointers/clues on what would be the best way to achieve that (Read only floating point number with decimal and reject integer and special characters).
Read as string (fgets())
Insure string contains a '.', 'E' or 'e', reject otherwise.
Test if converts as FP correctly with no trailing junk. (strtod() or sscanf("%lf %n",...) and is finite (isfinite())
The specification is ambiguous: do you intend to accept 0.00 as a floating point value with decimals, although it happens to have an integral value?
Your implementation would reject it, but it would accept 1e-1 which does not match the criteria.
Here is an alternative that accepts positive numbers with digits before and after a decimal point:
#include <stdio.h>
#include <string.h>
int main() {
char buf[80];
double floatnum;
printf("Enter floating point numbers: ");
while (scanf("%79s", buf) == 1) {
int len = strlen(buf);
int pos = -1;
sscanf(buf, "%*[0-9].%*[0-9]%n", &pos);
if (pos == len && sscanf(buf, "%lf", &floatnum) == 1) {
printf("Number entered = %.2f\n", floatnum);
} else {
printf("Invalid floating point number: %s, enter again: ", buf);
}
}
return 0;
}
If you wish to also accept negative numbers and numbers with a redundant positive sign, you can extend the validator to skip an initial sign.
Program to limit the user's input to one decimal point in C.
For example:
Enter grade: 5 //Acceptable
Enter grade: 8.5 //Acceptable
Enter grade: 6.467 //Not acceptable, Re-enter grade
#include <stdio.h>
#include <math.h>
main()
{
double grade[8];
int i;
for (i = 0; i < 8; i++) {
printf("Insert grade: ");
scanf("%f", &grade[i]);
}
}
You will have to input the data as string, then check it only has one decimal place.
It is not possible to input a floating-point value and then check for decimal places; since the floating point values are stored internally with binary places and hold an approximation of the value that was input, in most cases.
The input code could look like:
char temp[20];
if ( 1 != scanf("%19s", temp) )
return EXIT_FAILURE;
// code to check for decimal place goes here - I'm purposefully not
// showing it as this looks like homework!
// once we have checked that the input is correct, then convert to double
grade[i] = strtod(temp, NULL);
#include <stdio.h> // printf(), scanf()
#include <math.h> // floor()
main()
{
double grade[8];
int i;
for (i = 0; i < 8; i++)
{
do
{
printf("Insert grade: ");
scanf("%lf", &grade[i]);
grade[i] *= 10;
if (grade[i] != floor(grade[i])) // Prints error message, if user types more than one decimal point
{
printf("Grade must have one decimal point.\nPlease re-enter grade.\n");
}
}while (grade[i] != floor(grade[i])); // Checks decimal point
}
}
Use fgets() to read the line into a buffer and then test that buffer.
char buf[99];
fgets(buf, sizeof buf, stdin);
// parse the line as a float - look for problems
char *endptr;
float f = strtof(buf, &endptr);
if (buf == endptr || *endptr != '\n') Fail_NonFloatInput();
// look for .
char *dot = strchr(buf, '.');
if (dot && isdigit(dot[1]) && isdigit(dot[2])) Fail_TooMuchPrecisison();
}
Alternatively code could try:
long long i;
int f;
if (2 != scanf("%lld.%1d", &i, &f)) Bad_Input();
float fl = i + f/10.0;
But that fails float input like 123456789012345678901234567890.0.
As #Matt McNabb says, read as text first.
You can use printf format specifiers to specificy the number of positions you are interested.
A format specifier follows this prototype: [see compatibility note below]
%[flags][width][.precision][length]specifier
Example from the cplusplus.com
#include <stdio.h>
int main()
{
printf ("floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416);
return 0
}
Output
floats: 3.14 +3e+000 3.141600E+000
More examples here http://www.cplusplus.com/reference/cstdio/printf/