3

我的目标是将分隔符更改scanf为“ \n”。我尝试使用scanf("%[^\n]s",sen);单个输入并且工作正常。但是当我将同一行放在for多个句子的循环中时,它给了我垃圾值。

有谁知道为什么?


这是我的代码:

char sen[20];
for (i=0;i<2;i++)
{
    scanf("%[^\n]s",sen);
    printf("%s\n",sen);
}
4

5 回答 5

14

考虑这个(C99)代码:

#include <stdio.h>

int main(void)
{
    char buffer[256];

    while (scanf("%255[^\n]", buffer) == 1)
        printf("Found <<%s>>\n", buffer);
    int c;
    if ((c = getchar()) != EOF)
        printf("Failed on character %d (%c)\n", c, c);
    return(0);
}

当我运行它并输入一个字符串“绝对是任何带有空格TABTAB标签的东西!”时,它给了我:

Found <<absolutely anything with   spaces       tabs galore!>>
Failed on character 10 (
)

当然, ASCII (UTF-8) 10 10是换行符。

这能帮助你理解你的问题吗?


它在这种情况下有效(对于单行),但如果我想将多行输入放入数组数组中,那么它会失败。而且我不明白如何scanf在您的代码中返回值?

scanf()许多(大多数?)有经验的 C 程序员避免和fscanf()喜欢瘟疫是有原因的;他们很难正常工作。我会推荐这种替代方案, using sscanf(),它不会得到与执行相同的scanf()执行fscanf()

#include <stdio.h>

int main(void)
{
    char line[256];
    char sen[256];

    while (fgets(line, sizeof(line), stdin) != 0)
    {
        if (sscanf(line, "%255[^\n]", sen) != 1)
            break;
        printf("Found <<%s>>\n", sen);
    }
    int c;
    if ((c = getchar()) != EOF)
        printf("Failed on character %d (%c)\n", c, c);
    return(0);
}

这将读取输入行(使用fgets()它确保没有缓冲区溢出(假设该gets()功能,如果您听说过它,将您的计算机熔化成金属和硅池),然后用于sscanf()处理该行。这处理换行符,这是原始代码的失败。

char sen[20];
for (i=0;i<2;i++)
{
    scanf("%[^\n]s",sen);
    printf("%s\n",sen);
}

问题:

  1. 你不检查是否scanf()成功。
  2. 在第一次迭代时将换行符留在缓冲区中;第二次迭代生成返回值 0,因为要读取的第一个字符是换行符,它是扫描集排除的字符。
  3. 您看到的胡言乱语可能是第一行输入,重复。事实上,如果不是有界循环,它不会等你再输入任何东西;它会一遍又一遍地吐出第一行。

返回值来自scanf()

scanf()(来自 ISO/IEC 9899:1999)的定义是:

§7.19.6.4 scanf 函数

概要

 #include <stdio.h>
 int scanf(const char * restrict format, ...);

描述

2 该scanf函数等效于fscanf在 的参数stdin之前插入参数scanf

退货

3scanf如果在任何转换之前发生输入失败,该函数将返回宏 EOF 的值。否则,该scanf函数返回分配的输入项的数量,如果发生早期匹配失败,该数量可能少于提供的数量,甚至为零。

请注意,当我的第一个程序中的循环退出时,这是因为scanf()返回 0,而不是 EOF。

于 2012-10-14T19:41:45.117 回答
3

%[^\n]将换行符留在缓冲区中。%[^\n]%*c吃掉换行符。在任何情况下,%[^\n]都可以读取任意数量的字符并导致缓冲区溢出或更糟。我使用格式字符串%*[^\n]%*c从文件中吞噬一行输入的其余部分。例如,可以读取一个数字并通过 丢弃该行的其余部分%d%*[^\n]%*c。如果数字后面有注释或标签,或者其他不需要的数据,这很有用。

于 2014-12-07T18:29:14.303 回答
1
char sen[20];
for (i=0;i<2;i++)
{
  scanf("%[^\n]s",sen);
  printf("%s\n",sen);
  getchar();
}

希望这会有所帮助...实际上“\ n”保留在流输入缓冲区中... Ee需要在再次调用scanf之前将其刷新

于 2014-04-28T21:56:26.927 回答
0

我知道我迟到了,但是经过很长时间测试 C 后我遇到了同样的问题。
这里的问题是新行被视为下一次迭代的输入。

所以,这是我的解决方案,用于getchar()丢弃输入流的换行符:

char s[10][25];
int i;

for(i = 0; i < 10; i++){
    printf("Enter string: ");
    scanf("%s", s[i]);
    getchar();
}

希望能帮助到你 :)

于 2021-02-06T15:37:59.567 回答
0

在循环中使用scanf("%[^\n]", sen)时,出现的问题是\n停留在输入缓冲区内并且没有被刷新。结果下一次,当使用相同的输入语法时,它会读取\n并认为它是一个空输入。解决此问题的一个简单但有效的解决方案是使用:

char sen[20];
for (i=0;i<2;i++)
{
    scanf("%[^\n]%*c",sen);
    printf("%s\n",sen);
}

%*c摆脱\n输入缓冲区中的字符。

于 2021-05-25T07:25:09.653 回答