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

时间:2013-02-27 20:40:32

标签: c

我对处理空格时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");
}

3 个答案:

答案 0 :(得分: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.

答案 1 :(得分:1)

你遇到了*scanf should never be used:臭名昭着的空白处理的一个更臭名昭着的原因。您的'\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只是在您希望程序在面对超长输入线。)

答案 2 :(得分:0)

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

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