0

I have a do-while loop, shown below

do
{
    dimensions = NULL;

    printf("=======================================\nDo you want to multiply in 2 dimensions, or 3?\n\n");

    scanf("%c", &dimensions);

    ... //do stuff

    printf("\nEnter r to repeat, return to terminate\n");
    scanf("%c", &key);
    scanf("%c", &key);
}
while(key == 'r');

On the first run, it executes fine. The problem however is when it runs through the code again after the user enters 'r' and hits return. It'll take you to the first printf("==== etc., but won't allow the user to do anything, it'll go straight back to the second printf("\nEnter...

I stepped through the code to see what was going on, and on a second run through the program just skips the scanf( and all following code for absolutely no reason. Initially I thought it was because 'dimensions' wasn't being set to a value that doesn't run the following methods - but I have, and even if that were the case, the program would run the methods instead of skipping them without user input.

Am I missing something? Is scanf( not enough to stop the program once it's already been used?

Boggy B
  • 171
  • 1
  • 8
  • 2
    Inclined to change the tag to C, since the code is only using C features and C programmers might be more familiar with that interface. --Obvious question: why two `scanf` at the end of the loop? also, what is the type of `dimensions` and why are you setting it to `NULL`? – David Rodríguez - dribeas Dec 10 '13 at 20:36
  • I think, that two scanf are maybe because return can be represented as two symbols - \n and \r ? – Martin Perry Dec 10 '13 at 20:44
  • Well this is the weird thing - For some reason the app ignores the scanf( part if only one of them is present. I really don't understand that. I had my suspicions that this is the problem but I've not a clue as to how to solve it. I'll change it to a C tag now. – Boggy B Dec 10 '13 at 20:45
  • @MartinPerry: Not in this case. When reading from files and std/cin the "Line Termination Sequence" (which is unique to platform) is converted into a '\n' (assuming files are opened in text mode). – Martin York Dec 10 '13 at 20:46
  • @BoggyB: Note scanf blockes until the input is flushed. Usually the input is flushed when you hit (or you type a heck of a lot). Also remember code is never skipped. If you think that then usually you are misunderstanig what is happening. Print out the value of `key` after each `scanf()` (and the return value of scanf) to see what is in the variable. – Martin York Dec 10 '13 at 20:47
  • scanf() is one of those functions that can have weird behavior. I recommend using gets() instead and then parsing the user input especially for this simple interaction. Here is a [description of scanf](http://www.cplusplus.com/reference/cstdio/scanf/) – Richard Chambers Dec 10 '13 at 20:49

3 Answers3

1

Your problem is that when your program gets input from the console with scanf, it reads the data from the keyboard into the input buffer, then values are taken out of the buffer and placed into the locations you provide to scanf. The issue is that when scanf reads a character, it also reads the \n into the buffer, then upon being called again, it reads the second character that was placed into the buffer (without asking you for more input - because why would it? It already HAS things in the buffer).

So there are two solutions: one - use fflush on stdin like so: fflush(stdin). Second - write a while loop that clears out characters one by one from the input buffer: while (getchar() != '\n' );

EDIT: For more reading, see How to clear input buffer in C?

Community
  • 1
  • 1
0

Think it through: "the user enters 'r' and hits return", then the program reads the 'r' and repeats. What's left in the input buffer? There were two keys pressed, and the code only read the first one.

That's also the reason that the code needs two calls to scanf. The first clears the extra character out of the input buffer and the second reads the new character.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
0

What is happening now

To make the buffer flush you need to enter

r<enter>

Hitting <enter> flushes the buffer. So the input buffer now contains two characters.

r\n

So the first scanf will read r
The second scanf will read \n

So by the time you reach the while key has a value of \n. The test fails and the loop is not repeated. So you should remove the second scanf() reading into key.

So you remove the second scanf. Now what happens?

User types

r<enter>

This leaves the input buffer with:

r\n

The scanf() read r into key. The loop repeats correctly. But when we get back to the scanf(). The input buffer still has \n character in the buffer. So the scanf() immediately reads this value and the loop exists as it should have.

how you should fix it.

Ask for Y/N answer and validate that the input is correct.

std::string line;
std::getline(std::cin, line);
while (line != "Y" && line != "N")
{
    std::cout << "Hey cluts enter a correct value. Y/N\n";
    std::getline(std::cin, line);
} 
Community
  • 1
  • 1
Martin York
  • 257,169
  • 86
  • 333
  • 562