0

NOTE: Please notice this is not a duplicate of Why is scanf() causing infinite loop in this code? , I've already seen that question but the issue there is that he checks for ==0 instead of !=EOF. Also, his problem is different, the "infinite loop" there still waits for user input, it just does not exit.

I have the following while loop:

while ((read = scanf(" (%d,%d)\n", &src, &dst)) != EOF) {
                if(read != 2 ||
                         src >= N || src < 0 ||
                         dst >= N || dst < 0) {
                        printf("invalid input, should be (N,N)");
                } else
                        matrix[src][dst] = 1;
        }

The intention of which is to read input in the format (int,int), to stop reading when EOF is read, and to try again if an invalid input is received.

The probelm is, that scanf works only for the first iteration, after that there is an infinite loop. The program does not wait for user input, it just keeps assuming that the last input is the same.

read, src, and dst are of type int.

I have looked at similar questions, but they seem to fail for checking if scanf returns 0 instead of checking for EOF, and the answers tells them to switch to EOF.

Community
  • 1
  • 1
Tom Klino
  • 2,358
  • 5
  • 35
  • 60
  • 3
    remove `\n` from the `scanf` – Spikatrix Apr 25 '15 at 09:06
  • @user3121023 , that's no good, it will stop recieving input after an invalid input. – Tom Klino Apr 25 '15 at 09:08
  • @CoolGuy I actually started without `\n`, had the same problem. I added it because I seen a recomondation to it from another question. And to your second question, any input - valid or invalid - replicates the issue. – Tom Klino Apr 25 '15 at 09:09
  • @BLUEPIXY , see my previous comment (my response to CoolGuy) – Tom Klino Apr 25 '15 at 09:11
  • 2
    @Tom , Try `int c;while((c=getchar())!='\n' && c!=EOF);` in the body of the `if` – Spikatrix Apr 25 '15 at 09:12
  • possible duplicate of [Why is scanf() causing infinite loop in this code?](http://stackoverflow.com/questions/1716013/why-is-scanf-causing-infinite-loop-in-this-code) – sashoalm Apr 25 '15 at 09:15
  • @sashoalm , not a duplicate. I've already seen that question. his issue was that he checked `== 0` instead of `!=EOF` – Tom Klino Apr 25 '15 at 09:17
  • @CoolGuy , in your suggestion, where should I read the input to `src` and `dst` ? – Tom Klino Apr 25 '15 at 09:18
  • 2
    @Tom , Just add `int c;while((c=getchar())!='\n' && c!=EOF);` just after `printf("invalid input, should be (N,N)");` – Spikatrix Apr 25 '15 at 09:19
  • Does "(%d,%d)\n" without a leading space work? – user3125367 Apr 25 '15 at 09:31
  • @CoolGuy , this does change something, but causes a weird bahaviour. it gets the valid input, but does not execute anything in the loop until it gets some kind of invalid input. – Tom Klino Apr 25 '15 at 09:34
  • @CoolGuy , this is what I have now: http://pastebin.com/D6h01tzm . But it produces that odd behaviour I was talking about – Tom Klino Apr 25 '15 at 09:40
  • @CoolGuy - your solution was spot on! I only needed to remove the `\n` from my `scanf` after that. If you phrase that as an answer I will accept it. (it might also help future generations). thanks – Tom Klino Apr 25 '15 at 09:55
  • @Tom, EOF normally is defined as -1, scanf, when unable to parse any input field, returns 0. It will never get to -1 on end of file. – Luis Colorado Apr 27 '15 at 05:12

2 Answers2

2

You need to use

int c;
while((c=getchar()) != '\n' && c != EOF);

at the end of the while loop in order to clear/flush the standard input stream(stdin). Why? The answer can be seen below:

The scanf with the format string(" (%d,%d)\n") you have requires the user to type

  1. An opening bracket(()
  2. A number(For the first %d)
  3. A comma(,)
  4. A number(For the last %d)

The space(First character of the format string of your scanf) and the newline character(\n which is the last character of the format string of your scanf) are considered to be whitespace characters. Lets see what the C11 standard has to say about whitespace characters in the format string of fscanf(Yes. I said fscanf because it is equivalent to scanf when the first argument is stdin):

7.21.6.2 The fscanf function

[...]

  1. A directive composed of white-space character(s) is executed by reading input up to the first non-white-space character (which remains unread), or until no more characters can be read. The directive never fails

So, all whitespace characters skips/discards all whitespace characters, if any, until the first non-whitespace character as seen in the quote above. This means that the space at the start of the format string of your scanf cleans all leading whitespace until the first non-whitespace character and the \n character does the same.

When you enter the right data as per the format string in the scanf, the execution of the scanf does not end. This is because the \n hadn't found a non-whitespace character in the stdin and will stop scanning only when it finds one. So, you have to remove it.

The next problem lies when the user types something else which is not as per the format string of the scanf. When this happens, scanf fails and returns. The rest of the data which caused the scanf to fail prevails in the stdin. This character is seen by the scanf when it is called the next time. This can also make the scanf fail. This causes an infinite loop.

To fix it, you have to clean/clear/flush the stdin in each iteration of the while loop using the method shown above.

Community
  • 1
  • 1
Spikatrix
  • 20,225
  • 7
  • 37
  • 83
-1

scanf prompts the user for some input. Assuming the user does what's expected of them, they will type some digits, and they will hit the enter key.

The digits will be stored in the input buffer, but so will a newline character, which was added by the fact that they hit the enter key.

scanf will parse the digits to produce an integer, which it stores in the src variable. It stops at the newline character, which remains in the input buffer.

Later, second scanf which looks for a newline character in the input buffer. It finds one immediately, so it doesn't need to prompt the user for any more input.

Vinay Shukla
  • 1,818
  • 13
  • 41
  • This doesn't really solve my issue. Do you have a suggestion of what might fix it? – Tom Klino Apr 25 '15 at 09:16
  • Can you share the entire code plz, adding a space after `(%d ,%d )` may help but need to verify – Vinay Shukla Apr 25 '15 at 09:19
  • @yanivx , `%d` does **not** read `\n`. It skips it. and "*Assuming the user does what's expected of them, they will type some digits, and they will hit the enter key.*" is wrong. The `scanf` in the OP's question has brackets and a comma. These need to be typed too – Spikatrix Apr 25 '15 at 09:20
  • @CoolGuy agreed but 2 consecutive `scanf` or `getline` leads to this issue where in the newline character fulfils the requirement of second `scanf` I will try the code and will get back – Vinay Shukla Apr 25 '15 at 09:22
  • @Tom here is the answer to your ? you can use `%s` to fix the problem which i have referred in my answer. A sample fix is here http://stackoverflow.com/a/5453684/2959769 – Vinay Shukla Apr 25 '15 at 09:35