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?

Recommended Answers

All 10 Replies

>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.

commented: Great link! :icon_razz: +14

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.

Thank you both, I now just need to understand it

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."

good points -- i stand corrected.

one day i'll learn about relying on "memory"

.

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?

The issue is fflush(stdin) .

http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1052863818&id=1043284351


[edit]The earlier snippet ended up being a part of User Input: Strings and Numbers [C]. There I'd gone into various details a little deeper. At one time that tutorial ended with a discussion of the fflush(stdin) issue which always seems to follow along with these questions. For whatever reason, the powers that be elided that portion.

(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.

.

Thank you both

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.