【问题标题】:What does scanf REMOVES from input after scanning?scanf 扫描后从输入中删除什么?
【发布时间】:2014-06-19 06:00:12
【问题描述】:

我已经阅读了许多问题、博客和书籍,但我想我只是无法正确地关联事物。 scanf 扫描后做什么?它读取除空格、制表符和换行符之外的所有内容,但它对换行符有什么作用? 扫描输入后,我无法以任何方式删除换行符。 例如,将其视为输入:-

5
Abcdefgh

现在,我已将 5 扫描为整数,

 scanf("%d", &i); 

但是如何删除 '\n' 以便一次读取一个字符前面的所有内容?我想使用:-

 while((c=getchar())!='\n'){//Do something} 

'\n' 应该是字符串之后的那个,但是 getchar() 得到 5 之后的那个,并且循环甚至在运行一次之前就终止了。我想我只是错过了一个小技巧。

scanf("%d", &i);
while((c=getchar())!='\n'){
    //Do something with the character
}

输入文件:-
5
ABCDEF
期望 while 循环运行,而它不运行。因为它在 5 之后捕获 '\n'。我尝试在 scanf() 和 while() 之间添加 getchar(),但随后程序卡住并且什么也不做。

【问题讨论】:

    标签: c scanf getchar


    【解决方案1】:

    您可以在scanf() 调用之后立即使用getchar() 来使用\n,这样它就不会干扰您的循环。

    scanf("%d", &i); 
    getchar(); // To consume the trailing newline left 
               //in the input stream by scanf().
    
     while((c=getchar())!='\n'){
       //Do something
     } 
    

    #include <stdio.h>
    
    int main(void)
    {
        int i, j=0;
        char c;
        scanf("%d", &i);
        getchar();
        printf("%d\n", i);
    
        while((c=getchar())!='\n'){
          printf("%c-", c);
        }
        return 0;
    }
    

    我以与您相同的方式运行上述代码:在 Linux 上运行 ./a.out &lt; file,在 Windows 上使用 mingw,我没有发现任何问题。

    【讨论】:

    • 其他人的回答相同。我自己也尝试过。但这只是行不通。至少在 Windows 上没有。我试过'\r\n'。 '\r' 单独。什么都没有。
    • 你能发布你的代码吗?你不需要使用\r\n。您确定在循环之前没有任何其他类似的 scanf() 调用吗?
    • 没有额外的 scanf() 调用。只需一次 scanf() 调用,然后调用另一个正在使用 getchar() 的函数。
    • 读取您的 cmets,您似乎是从文件而不是标准输入读取。在这种情况下,您应该没有任何问题。但是您不应该使用fscanf() 来读取从文件吗?
    • 我不是从文件中读取,我只是从文件中提供输入。 Program.exe out.txt
    【解决方案2】:

    如果您采用字符或字符串输入,请在每个整数输入后使用getchar()。这将从输入缓冲区中删除\n

    scanf("%d", &i);
    getchar();
    while((c=getchar())!='\n'){//Do something} 
    

    【讨论】:

    • 如果我从文本文件输入输入,它会如何表现?因为它卡在了这条线上。我试过了。
    • 如果您从文本文件中获取输入,则您没有使用getchar()。那你用什么?
    • 我的意思是我正在使用 getchar()。它不选择'\n'。我在 Windows 上。我浏览了几个说我应该使用'\r\n'的博客,但没有奏效。单独尝试'\ r',没有奏效。输入文件包含以下内容:- 5 Abcde //5 后有 ENTER
    • 您的输入文件包含什么以及您从控制台获取什么输入?编辑这样说的问题。目前还不是很清楚。
    • @vish213 getchar() 不是从文件中读取,而是从标准输入中读取。您如何将文件提供给您的程序?
    【解决方案3】:

    如果您在scanf 格式说明符中的%d 之后添加一个空格,scanf 将在遇到任何非空白字符之前不会返回。这将有效地消耗输入中任意数量的换行符或其他空格。正如@BlueMoon 所指出的,请注意,这 依赖 程序在换行符之后接收更多非空白输入。所以它适用于这个例子,但可能会在其他地方引起麻烦。

    这是一个最小的例子:

    #include <stdio.h>
    
    int main()
    {
        int i, j=0;
        char c;
        scanf("%d ", &i);
        while((c=getchar())!='\n') printf("%d: %c\n", j++, c);    
        return 0;
    }
    

    样本输入:

    5   
    
    
    abcdefg
    

    输出:

    0: a
    1: b
    2: c
    3: d
    4: e
    5: f
    6: g
    

    编辑:请注意,可以通过使用fgets 将一行读入字符缓冲区,然后使用sscanf 提取整数来规避此问题:

    char buff[SIZE];
    fgets(buff, SIZE, stdin);
    sscanf(buff, "%d ", &i);
    while((c=getchar())!='\n') printf("%d: %c\n", j++, c);
    

    fgets 读取直到遇到换行符或文件结尾,或者已读取 SIZE-1 字节。假设您只希望该行包含一个整数,那么这个限制应该不是问题。只要SIZE 足够大,换行符就会被fgets 使用,循环中的后续getchar 将按预期工作。

    【讨论】:

    • If you want to consume all whitespace until other characters are entered, you can just add a space after the %d。不,这里的 scanf() 只是等待您输入一个非空白字符并且在您输入之前不会终止。
    • @BlueMoon 恐怕我不明白区别。这种方法是否有可能的负面影响?此外,这不正是 OP 所追求的吗?
    • 区别在于必须输入一个非空白字符来终止scanf()。使用剩余的空格(如果有)与强制输入非空格字符不同。
    • @BlueMoon 好点,我明白你的意思,谢谢。我已经更新了答案,希望它能更好地解释。
    • OP 明确指出整数后有一个新行,所以我认为 "%d " 可以很好地回答这个问题。
    【解决方案4】:

    由于您使用的是 Windows,因此在 '\n' 字符之前有一个 '\r' 字符。

    “在while 循环之前添加getchar();”技巧不起作用,因为这个getchar() 正在获取'\r' 字符。因此,当首次评估 while 条件时,c'\n'

    因此,一个简单的解决方法是使用两个getchar() 调用来使用'\r\n'。但是,这不是很便携,也就是说,它不能在其他系统上工作。

    所以我会使用以下内容:

    int main() {
        int i;
        char c;
        scanf("%d", &i);
        if(getchar()=='\r') getchar();
        while((c=getchar())!='\n') {
            printf("%c\n", c);
        }
        return 0;
    }
    

    【讨论】:

    • 在 Windows/Unix-line OS 中很好区分 EOL。
    猜你喜欢
    • 1970-01-01
    • 2011-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-08
    • 1970-01-01
    相关资源
    最近更新 更多