使用制表符和换行符进行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; }
如果你没有getline
, fgets
通常就足够了。 (警告:不要将fgets
与gets
混淆。 gets
是危险的,永远不应该使用,但是如果你希望你的程序在超长输入行的情况下变得健壮,那么fgets
是不方便的。)
“处理空格时,我对scanf的行为感到困惑。” 是普遍的主张!
如果格式字符串中有任何空格,它将占用所有空格,因此“\ t”匹配任何空格字符串。