当第一个跟踪失败时,为什么我不能再对同一个变量使用scanf

请参阅以下代码:

#include  int main(int argc, char const *argv[]) { int n; int i = scanf("%d", &n); printf("%d\n", i); int j = scanf("%d", &n); printf("%d\n", j); return 0; } 

假设我第一次为n输入一个字符串, scanf将返回0 ; 但是,为什么它不允许我第二次输入n的值而j是自动0 ? 即使我第一次键入错误的值,我该怎么做才能让我再次输入n值?

您几乎肯定会输入一个非数字值,这将导致第一个scanf失败,返回零并且(这是重要的位) 将流指针保留在scanf调用之前的确切位置。

这意味着下次调用它时,它只会尝试读取相同的数据。

零返回值是一个死的赠品 – scanf返回成功扫描的项目数,因此零表示您没有给它一个数字。

如果您输入数字,它可以正常工作,如下面的代码:

 #include  int main(int argc, char const *argv[]) { int n; int i = scanf("%d", &n); printf(">> %d %d\n", i, n); int j = scanf("%d", &n); printf(">> %d %d\n", j, n); return 0; } 

当您运行它并输入4132 ,您会看到:

 41 >> 1 41 32 >> 1 32 

在他们职业生涯的某个阶段,每个C程序员都会遇到用户输入该语言的不足之处。 基于行的输入最好的选择是简单地找到一个能很好地运行的函数,然后在结果字符串上使用sscanf

确保行是基本单元,并且可以处理缓冲区溢出并确保过多的数据不会“破坏”未来的输入。

这是我之前准备的。

您输入的非数字字符串不会被scanf

相反,您可以像这样使用fgetssscanf

 #include  int main(void) { int n; char str[100]; fgets(str, sizeof(str), stdin); int i = sscanf(str, "%d", &n); printf("%d\n", i); fgets(str, sizeof(str), stdin); int j = sscanf(str, "%d", &n); printf("%d\n", j); return 0; } 

在重新输入输入并读取它们之前,您可以忽略其余部分。 你可以使用以下方法忽略其余部分:

 scanf("%[^\n]*\n"); 

如果输入数字,您的代码将正常工作。 但是,在输入字符串时,必须先从输入流中删除该字符串,然后再使用它。


例如:

 #include  int main(int argc, char const *argv[]) { int n; char c; int i = scanf("%d", &n); printf("%d\n", i); //Remove the previous string from the input stream while ( (c = getchar()) != '\n' && c != EOF ); int j = scanf("%d", &n); printf("%d\n", j); return 0; } 

输入为整数时输出

 100 1 200 1 

输入为字符串时输出

 abcd 0 efghi 0 

进一步参考: 为什么每个人都说不使用scanf? 我该怎么用?