Scanf not working in while loop when nonmatching string is entered

不打扰是莪最后的温柔 提交于 2021-01-27 06:24:06

问题


I'm using a function called checkType to check whether the user has entered a valid input of integer type. For example, if the user enters 15 it will print valid and 15c will print not valid. However, if the user enters a string input only like ccccc, it results in an infinite loop and the program crashes. I have added some screenshots below to show the outputs.

int checkType(int input, char *c) {
  if (input == 2 and *c == '\n') {
    return 1;
  } else {
    return 0;
  };
}

int main(void) {
  int faces = 0;
  char c;
  int valid = 0;
  int input;

  while (valid == 0) {
    printf("Enter number of faces: ");
    input = scanf("%d%c", &faces, &c);
    valid = checkType(input, &c);
    printf(valid == 0 ? "not valid\n" : "valid\n");
  }
}

Infinite Loop:


回答1:


The scanf() family of functions is not really made for input of questionable syntax.

The usual approach to solve your problem is to read in all the input in a way which is sure to succeed, e.g. by reading a complete line (instead of a number, word-like string, or anything else with expected format) with fgets(). Then you can try to parse that line-representing string as by expected format. (You can use sscanf() for the parsing attempt.) If that fails you ignore it and read the next line, or try parsing according to an alternative allowed format for the same input.

The relevant difference is that reading a whole line will succeed and remove it from the input stream. In contrast to that, your code, in case of syntax failure, leaves in the input stream whatever did not match the expected syntax. As such it will, of course, fail the next iteration of the reading loop again. That is what causes your endless loop.

In detail:

  • read a whole line into a buffer,
    using fgets() and the option to restrict the number of characters to the size of the buffer
  • at this point all of the line is removed from the input (aka stdin, aka input stream),
    which means that the next read will get new input even if the read line does not match any allowed format,
    this is the relevant difference to trying to read input directly with scanf()
  • from the line buffer, attempt to read separate values according to an allowed format,
    using sscanf() and with a check of the return value
  • if successful great, you have your expected variables filled (e.g. an integer);
    you could try scanning for additional, not format-covered trailing input (and continue like for incorrect input, even if the beginning of the line matched an allowed format)
  • if not successful try a different allowed format,
    using sscanf() again,
    from the same line buffer, which is not changed, not even if a format partially matched
  • if no allowed format matches the input it is time to consider it incorrect
  • incorrect input can be ignored or can cause a fatal parsing error in your program, your choice



回答2:


However, if the user enters a string input only like ccccc,
it results in an infinite loop and the program crashes

Reason : scanf returns the number of valid read values from stdin. If we give cccc as input, scanf cannot read the value, because the input and variable faces are of different data type. This makes input = 0. So the function checkType returns 0, which in turn makes valid = 0. This makes while(valid == 0) always true and hence the endless loop.




回答3:


Scanf will read form stdin, and not clean the stdin buffer if not match. So it will read wrong data again in your case, you can just add a clean function with stdin after scanf, like: __fpurge(stdin)

You can refer to the following two links:

https://man7.org/linux/man-pages/man3/scanf.3.html

http://c-faq.com/stdio/stdinflush2.html




回答4:


With input like "ccccc" and scanf("%d%c" ..., there is no conversion to an int. scanf() returns 0 and stdin remains unchanged. Calling the function again has the same result.

Code neds to consume errant input - somehow.

Research fgets() to read a line of user input.



来源:https://stackoverflow.com/questions/64870792/scanf-not-working-in-while-loop-when-nonmatching-string-is-entered

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!