为什么不是scanf(“%* [^ \ n] \ n");和scanf(“%* [^ \ n]%* c");清除挂起的换行符? [英] Why aren't scanf("%*[^\n]\n"); and scanf("%*[^\n]%*c"); clearing a hanging newline?

查看:116
本文介绍了为什么不是scanf(“%* [^ \ n] \ n");和scanf(“%* [^ \ n]%* c");清除挂起的换行符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在调用scanf("%d", &variable);之后,我们在 stdin 上保留了换行符,应该在调用fgets之前清除该换行符,否则我们最终将其换行并生成它会过早返回.

After a call to scanf("%d", &variable); we are left with a newline hanging at the stdin, which should be cleared before a call to fgets, or we end up feeding it a newline and making it return prematurely.

在第一次调用scanf放弃换行符后,我已经找到建议使用scanf("%*[^\n]%*c");的答案,而其他建议使用scanf("%*[^\n]\n");的答案.从理论上讲,两者都应该起作用:第一个将使用所有不是换行符的内容(但不包括换行符本身),然后完全使用 个字符(换行符).第二个会消耗掉所有不是换行符的内容(不包括换行符),然后\n(一个空白字符)将指示scanf读取每个空白字符,直到第一个非空白字符为止.

I've found answers suggesting using scanf("%*[^\n]%*c"); after the first call to scanf to discard the newline and others suggesting using scanf("%*[^\n]\n");. Theoretically, both should work: The first would consume everything that isn't a newline (but not including the newline itself) and then consume exactly one character (the newline). The second would consume everything that isn't a newline (not including it) and then \n, a whitespace character, would instruct scanf to read every whitespace characters up to the first non-whitespace character.

但是,就我所知,这些方法在某些答案中确实奏效,但我无法在这里使它们奏效(下面的代码).

However, as much as I've seem those approaches working in some answers, I couldn't get them to work here (codes below).

为什么scanf方法都不起作用?

Why neither of the scanf approaches worked?

经过以下测试: Ubuntu Linux-gcc 5.4.0

Tested on: Ubuntu Linux - gcc 5.4.0

#include <stdio.h>

int main(int argc, char **argv){
    int number;
    char buffer[1024];

    printf("Write number: \n");
    scanf("%d", &number);

    //Clearing stdin?
    scanf("%*[^\n]\n");

    printf("Write phrase: \n");
    fgets(buffer, 1024, stdin);

    printf("\n\nYou wrote:%u and \"%s\"\n", number, buffer);

    return 0;
}

输出:

$ ./bug 
Write number: 
2
Write phrase: 


You wrote:2 and "
"

scanf("%*[^\n]%*c");方法:

scanf("%*[^\n]%*c"); approach:

#include <stdio.h>

int main(int argc, char **argv){
    int number;
    char buffer[1024];

    printf("Write number: \n");
    scanf("%d", &number);

    //Clearing stdin?
    scanf("%*[^\n]%*c");

    printf("Write phrase: \n");
    fgets(buffer, 1024, stdin);

    printf("\n\nYou wrote:%u and \"%s\"\n", number, buffer);

    return 0;
}

输出:

$ ./bug2 
Write number: 
3
Write phrase: 


You wrote:3 and "
"


以下方法是唯一按预期方式工作的方法:


The following approach was the only one that worked the way it was expected to:

#include <stdio.h>

int main(int argc, char **argv){
    int number;
    char buffer[1024];

    printf("Write number: \n");
    scanf("%d", &number);

    //Clearing stdin!
    int c;
    while((c = getchar()) != '\n' && c != EOF){
        //Discard up to (and including) newline
    }

    printf("Write phrase: \n");
    fgets(buffer, 1024, stdin);

    printf("\n\nYou wrote:%u and \"%s\"\n", number, buffer);

    return 0;
}

输出:

$ ./notbug 
Write number: 
4
Write phrase: 
phrase :D


You wrote:4 and "phrase :D
"

推荐答案

基本问题是scanf模式%[^\n]与不是换行符的一个或多个字符匹配.因此,如果下一个字符换行符,则模式将失败并且scanf将立即返回而不会读取任何内容.添加*不会更改该基本事实.因此,事实证明您不能仅凭一个电话就可以做到这一点,您需要两个:

The basic problem is that the scanf pattern %[^\n] matches ONE OR MORE characters that are not newlines. So if the next character is a newline, the pattern will fail and scanf will return immediately without reading anything. Add a * doesn't change that basic fact. So it turns out you can't do this with only one call, you need two:

scanf("%*[^\n]"); scanf("%*c");

请注意,将空白的换行符放在扫描模式中几乎总是无用的-它导致scanf读取并丢弃所有空白,直到看到一个非空白字符(它将留在输入缓冲区中).尤其是如果您尝试在交互式程序中使用它,它将显示为挂起状态,直到您输入非空白行为止.

Note that putting a bare newline into the scan pattern is almost always not useful -- it causes scanf to read and discard all whitespace until it sees a non-whitespace character (which will be left in the input buffer). Particularly if you try to use it in an interactive program, it will appear to hang until you enter a non-blank line.

这篇关于为什么不是scanf(“%* [^ \ n] \ n");和scanf(“%* [^ \ n]%* c");清除挂起的换行符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆