使用制表符和换行符进行scanf缓冲

处理空格时我对scanf的行为感到困惑。

这是我正在使用的代码:

int main() { int val; int c; scanf("%d\t", &val); c = getchar(); if(c == EOF) printf("eof"); else if(c == '\t') printf("tab"); else if(c == '\n') printf("newline"); } 

这是我传递的输入:

 1234 

我希望这会打印“换行符”,因为scanf只查找制表符,并且假设scanf默认在缓冲区中留下空格。 相反,它打印“eof”。 %d\t似乎吞下了换行符。

我错过了一些关于scanf的工作原理吗?

请注意,如果我将其更改为以下内容,则会正确打印“换行符”:

 int main() { int val; int c; scanf("%d", &val); getchar(); /* note this extra getchar */ c = getchar(); if(c == EOF) printf("eof"); else if(c == '\t') printf("tab"); else if(c == '\n') printf("newline"); } 

模式中的任何数量的空格( \t )都匹配输入中的任何数量的空格( \t\n )。

从手册页:

 White space (such as blanks, tabs, or newlines) in the format string match any amount of white space, including none, in the input. 

你遇到了一个更为臭名昭着的原因,就是为什么永远不要使用*scanf :令人困惑的空白处理。 你的'\t'不仅匹配单个标签,它匹配任何类型的空白 ,包括换行符!

假设你有getline ,做这种事情的最好方法是这样的:

 #include  #include  int main(void) { char *line = 0; char *p; long val; (void) getline(&line, 0, stdin); val = strtol(line, &p, 10); if (*p == '\0') puts("eof (no tab)"); else { if (*p != '\t') printf("no tab, %c instead\n", *p); p++; if (*p == '\0') puts("eof"); else if (*p == '\t') puts("tab"); else if (*p == '\n') puts("newline"); } free(line); return 0; } 

如果你没有getlinefgets通常就足够了。 (警告:不要将fgetsgets混淆。 gets是危险的,永远不应该使用,但是如果你希望你的程序在超长输入行的情况下变得健壮,那么fgets是不方便的。)

“处理空格时,我对scanf的行为感到困惑。” 是普遍的主张!

如果格式字符串中有任何空格,它将占用所有空格,因此“\ t”匹配任何空格字符串。