I do not know if this has ever been asked in C before but

I have a floating point variable like this:

while (fCost <= 0.0)
 	    {
            printf("\n\tKudler Fine Foods 'Sales Tax Calculator'\t\n");
            printf("\nPlease enter your sub-total:\n"); //allows customer to enter sub-total
            scanf("\n%f", &fCost);
            }

note the variable was named as a floating point earlier

When I type in c or m or any other letter and not a number I go into an infinite loop

now the question

How to I get the loop to repeat and not accept a character so I can prevent the infinite loop?

>How to I get the loop to repeat and not accept a character so I can prevent the infinite loop?
By ditching the use of scanf() to read input form user.
Here's the start of alternatives on how to read a floating point from user.

Comments
Great link! :icon_razz:

I do not know if this has ever been asked in C before but

only about a million times :P

other than that, the link Aia gives is pretty solid. anything i might add would just be pedantry.

on the one hand, i like the compactness of Sinkula's code (i sometimes code like that), but on the other hand, it doesnt lend itself very well to readability for people not used to the style

int mygetd(double *result)
{
   char buff [ 32 ]; /* modify as needed */
   return fgets(buff, sizeof buff, stdin) && sscanf(buff, "%lf", result) == 1;
}

It might help you if we break out the "return" statement a little bit for readability.

So here is an example of his code broken out to an extreme degree. I normally wouldn't write such tedious code for a simple function, but this might make it more clear as to what the operations grouped in his "return" statement are actually doing.

int mygetd(double *result)
{
   char buff [ 32 ]; /* modify as needed */
   numBytesRead = 0;
   isValidValue = 0;

   numBytesRead = fgets(buff, sizeof buff, stdin) 
   if (numBytesRead>0)  // format value, pass back as "result"
      isValidValue = sscanf(buff, "%lf", result);

   if (isValidValue == 1) 
      return 1;  // value entered is good
   else
      return 0; // no valid value found
}

To understand how his combined return statement works, you can follow it by the C operators' order of precedence...

first the "fgets()" function is performed, if it evaluates as TRUE, then the "scanf(...) ==1" function is subsequently evaluated (note, the == 1 is redundant). if it also evaluates as TRUE, the entire function returns TRUE (1), and the variable "result" is passed back with correct value.

But if the "fgets()" function evaluates as false, the entire routine immediately returns with FALSE (0) and the "scanf()" function is not even performed, so the variable "result" is left unmodified.

Or if "scanf()==1" evaluates as false, the entire routine likewise returns FALSE and "result" is either unmodified or undefined (i forget which).


.

It might help you if we break out the "return" statement a little bit for readability.

So here is an example of his code broken out to an extreme degree. I normally wouldn't write such tedious code for a simple function, but this might make it more clear as to what the operations grouped in his "return" statement are actually doing.

int mygetd(double *result)
{
   char buff [ 32 ]; /* modify as needed */
   numBytesRead = 0;
   isValidValue = 0;

   numBytesRead = fgets(buff, sizeof buff, stdin) 
   if (numBytesRead>0)  // format value, pass back as "result"
      isValidValue = sscanf(buff, "%lf", result);

   if (isValidValue == 1) 
      return 1;  // value entered is good
   else
      return 0; // no valid value found
}

To understand how his combined return statement works, you can follow it by the C operators' order of precedence...

first the "fgets()" function is performed, if it evaluates as TRUE, then the "scanf(...) ==1" function is subsequently evaluated (note, the == 1 is redundant). if it also evaluates as TRUE, the entire function returns TRUE (1), and the variable "result" is passed back with correct value.

But if the "fgets()" function evaluates as false, the entire routine immediately returns with FALSE (0) and the "scanf()" function is not even performed, so the variable "result" is left unmodified.

Or if "scanf()==1" evaluates as false, the entire routine likewise returns FALSE and "result" is either unmodified or undefined (i forget which).


.

The fgets function returns a pointer (not a count of characters), and if it fails it will be a null pointer. The first implicit check is whether or not fgets returned a non-null pointer, indicating success.

The sscanf function returns the number of input items assigned. This could be EOF, 0, or 1 for this case; a return value of 1 will indicated success, other results would indicate failure, so it is a check for success. The check for equality with 1 is not redundant, because EOF would be a nonzero value.

So it reads something like, "If you successfully obtained input text and you successfully converted that input text into a number, then return true. If anything fails, return false."

Yesterday as I was going over the section on fgets I was researching it up and ran across someone that used the following code and said it worked

//User Requirements
            printf("\nWelcome to Kudler Fine Foods,\n\nWe hope you enjoyed your shopping experience.\n");
            printf("\n\n\n\tPlease Enter your Subtotal: $");
            iResponse = scanf("%f", &fCost);
            
            //validity check
            while (fCost < fCheck || iResponse != 1){
	    fflush(stdin);
	    printf("\n\tPlease Re-enter your Subtotal: $");
	    iResponse = scanf("%f", &fCost);
	    }//end while loop

Note:I hope this code wraps up in the codebox, sorryif it does not

Someone came behind them and said fflush does not always work and did not explain why
Is there a big difference between fflush and fgets?

(1) fflush and fgets are two totally separate things, and completely independent of each other.

(2) fflush is only meaningful for "stdout", as im sure Dave's link explains.

(3) the code you have that someone "said it worked" will not work any better than your original code. if you enter an invalid input, it will still blow up on you.

.

This article has been dead for over six months. Start a new discussion instead.