为什么不是scanf(“%* [^ \ n] \ n”);和scanf(“%* [^ \ n]%* c”);清除挂线?

时间:2017-01-30 02:04:58

标签: c scanf stdin fgets

在致电scanf("%d", &variable);后,我们会在 stdin 处挂一个换行符,该换行符应在拨打fgets之前清除,否则我们最终会将其输入换行并使其过早返回。

我发现答案建议在第一次拨打scanf("%*[^\n]%*c");之后使用scanf来丢弃换行符,而其他人建议使用scanf("%*[^\n]\n");。从理论上讲,两者都应该有效:第一个会消耗所有非换行符(但不包括换行符本身),然后消耗完全一个字符(换行符)。第二个将消耗不是换行符(不包括它)的所有内容,然后\n(空白字符)将指示scanf读取每个空格字符直到第一个非空白字符。 / p>

然而,尽管我看起来这些方法在某些答案中起作用,但我无法让他们在这里工作(下面的代码)。

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

测试: Ubuntu Linux - gcc 5.4.0

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

#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");方法:

#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 "
"

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

工作方法:

#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
"

1 个答案:

答案 0 :(得分:3)

基本问题是scanf模式%[^\n]匹配 ONE OR MORE 不是换行符的字符。因此,如果下一个字符 是换行符,则该模式将失败并且scanf将立即返回而不会读取任何内容。添加*不会更改该基本事实。事实证明,只有一次通话你无法做到这一点,你需要两个:

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

请注意,将裸线换入扫描模式几乎总是没用 - 它会导致scanf读取并丢弃所有空格,直到它看到非空白字符(将留在输入缓冲区中)。特别是如果您尝试在交互式程序中使用它,它将一直挂起,直到您输入非空白行。