1

我对 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<tab><newline>

我希望这会打印“换行符”,因为 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");
}
4

3 回答 3

3

模式 ( \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.
于 2013-02-27T20:43:58.557 回答
1

您遇到了一个更臭名昭著的为什么*scanf不应该使用的原因:令人困惑的空白处理。您的'\t'不只是匹配单个选项卡,它匹配任意数量的任何类型的空格,包括换行符!

做这种事情的最好方法,假设你有getline,看起来像这样:

#include <stdio.h>
#include <stdlib.h>

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如果你希望你的程序在面对超长的输入行时保持健壮,这只会带来不便。)

于 2013-02-27T20:48:33.493 回答
0

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

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

于 2013-02-27T20:45:21.673 回答