繁星淼淼
根据C语言标准(n1256):7.19.6.2 fscanf函数...4 fscanf函数依次执行格式的每个指令。如果指令失败,如下所述,函数将返回。失败描述为输入失败(由于发生编码错误或输入字符不可用)或匹配失败(由于不适当的输入)。...7作为转换规范的指令定义了一组匹配的输入序列,如下文针对每个说明符所述。转换说明将按照以下步骤执行:8除非输入规范中包含[,c或n说明符,否则将跳过输入的空白字符(由isspace函数指定)。250)9从流中读取一个输入项,除非规范包括n个说明符。输入项定义为最长的输入字符序列,该序列不超过任何指定的字段宽度,并且是匹配输入序列的前缀,或者是匹配输入序列的前缀。251)输入项之后的第一个字符(如果有)保持未读状态。如果输入项的长度为零,则该指令的执行失败;否则,该指令的执行失败。除非文件末尾,编码错误或读取错误阻止了来自流的输入,否则此条件是匹配失败,在这种情况下,这是输入失败。10除非是%说明符,否则输入项(或者,如果是%n指令,即输入字符数)转换为适合转换说明符的类型。如果输入项不是匹配序列,则指令的执行失败:此条件是匹配失败。除非用*表示禁止分配,否则转换结果将放置在尚未收到转换结果的format参数后面的第一个参数指向的对象中。如果该对象没有适当的类型,或者无法在对象中表示转换结果,则该行为是不确定的。在第10段中添加了重点。%d转换说明符希望输入文本的格式设置为十进制整数。如果不是,则转换失败,并且导致转换失败的字符保留在输入流中。scanf()使用%d转换说明符进一步调用将会阻塞相同的字符。scanf()返回成功分配的数量;您需要检查此结果以查看转换是否成功,如下所示:int x = 0;while (x != 4){ int result = scanf("%d", &x); if (result != 1) { printf("Last call to scanf() failed; exiting\n"); break; }}不幸的是,您仍然将错误的输入卡在输入流中。有许多策略可以解决这个问题。您可以使用删除令人反感的字符,getchar然后重试:while (x != 4){ int tmp; if (scanf("%d", &tmp) == 0) getchar(); else x = tmp;}或者,您可以尝试读取下一个换行符,假设所有剩余的输入都为b0rked:while (x != 4){ int tmp; if (scanf("%d", &tmp) == 0) while (getchar() != '\n') ; else x = tmp;}或者,您可以尝试将输入读取为文本,然后使用strtol()(我的首选技术)将其转换为整数:char input[SOME_SIZE];int x = 0;...while (x != 4){ if (fgets(input, sizeof input, stdin)) { char *check; int tmp = (int) strtol(input, &check, 10); if (!isspace(*check) && *check != 0) { printf("%s is not a valid integer: try again\n", input); } else { x = tmp; } } else { printf("Read error on standard input\n"); break; }}这需要做更多的工作,但可以让您在将错误的输入分配给之前捕获错误的输入x。