1

So I'm learning how to use the while and for loops in C but this code won't seem to work. the scanf statement seems to be getting ignored and the loop just repeats itself without requiring me to input 'Y' for it to repeat. Here's the code:

void showCommission();

void main() {
    char keepGoing='y';
    while(keepGoing=='y') {
        showCommission();
        printf("Do you want to calculate another?\n");
        scanf("%c",&keepGoing);
   }
}

void showCommission() {
    float sales,commission;
    const float COM_RATE=0.10;
    printf("Enter the amount of sales\n");
    scanf("%f",&sales);
    commission=sales*COM_RATE;
    printf("The commission is $%f.\n",commission);
}

Here's what running the code gives me:

Enter the amount of sales                                                                         
5000                                                                                              
The commission is $500.000000.                                                                    
Do you want to calclulate another?    

...Program finished with exit code 10                                                             
Press ENTER to exit console.  

it never prompts me to enter y and the code just exits for some reason.

H.S.
  • 11,654
  • 2
  • 15
  • 32
Helay98
  • 25
  • 5
  • 1
    [Try this question](https://stackoverflow.com/questions/7898215/how-to-clear-input-buffer-in-c) to see if it helps explain why you're seeing this issue. – Joel Trauger Jan 17 '20 at 15:34
  • 1
    OT: `void` return type of `main()` is not as per standards. The return type of `main()` should be `int`. – H.S. Jan 17 '20 at 15:39

3 Answers3

11

The problem you're encountering is that the call to scanf to read in a value using the %c format will accept a newline character as valid input!

This, combined with the fact that the scanf("%f",&sales); call reads in a float value but does not 'consume' the following newline, will leave that newline character in the input buffer, for the subsequent call to read a value for keepGoing. Thus, you will have a value for keepGoing that is not y and the program will terminate.

There are several ways around this. The simplest, perhaps, is to add a space character before the %c field, which will instruct the scanf function to skip all 'whitespace' characters (which includes the newline) when 'scanning' for the input character:

scanf(" %c", &keepGoing); // Added space before %c will skip any 'leftover' newline!
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
4

You've got a few problems. First, you need to check your scanf return values; if stdin is closed without providing y, scanf will constantly return -1 without rewriting keepGoing (making the loop infinite).

The other problem is early exit; %c suppresses the normal scanf whitespace skipping behavior, so your scanf's in main are always trying to read whatever followed the float you just parsed to populate sales (usually whitespace or a newline of some sort), so when you enter:

1.12
y

the %c reads the newline after the 2, not the y, and the loop exits immediately.

A simple fix would be to change:

scanf("%c",&keepGoing);

to:

if (scanf(" %c", &keepGoing) != 1) break;

The leading space will reenable whitespace skipping so it consumes all whitespace before it tries to read the next character, and whenever it fails to read a character at all, it will end the loop, rather than running forever. A similar check should probably be added for your other scanf.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • He could also read two characters. Declare `char discardNL;` and then `scanf("%c%c", &keepGoing, %discardNL);` – Joel Trauger Jan 17 '20 at 15:38
  • 1
    @JoelTrauger: That assumes the user didn't accidentally enter a little trailing whitespace on the previous line, or double-tap `Enter` or whatever. Skipping all the whitespace, however much there is, is usually better (of course, even better would be validating input properly, discarding lines when the float parse doesn't work, forcing the input on continue to be only `y` or `n` and reprompting when it's not and `stdin` hasn't reached EOF, etc.). – ShadowRanger Jan 17 '20 at 15:40
-1

This is due to the newline (enter keystroke) leftover from non-chars input. scanf("%f",&sales);

For example, if i enter 500 for the amount of sales, the program will read 500\n, where the \n is your enter keystroke. However, scanf("%f",&sales) will only read float value. Therefore the \n is leftover in your input buffer. Then, when the program try to run scanf("%c",&keepGoing), it consume the leftover \n and it will treat as you pressed enter keystroke and skipped the input.

The issue can be fixed by consuming the leftover \n.

void showCommission() {
float sales,commission;
char consumeNewLine;
const float COM_RATE=0.10;
printf("Enter the amount of sales\n");
scanf("%f",&sales);
scanf("%c",&consumeNewLine);
commission=sales*COM_RATE;
printf("The commission is $%f.\n",commission);
}
Tian
  • 62
  • 1
  • 4