Why aren't scanf(“%*[^\n]\n”); and scanf(“%*[^\n]%*c”); clearing a hanging newline?

最后都变了- 提交于 2019-12-07 11:36:27

问题


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.

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).

Why neither of the scanf approaches worked?

Tested on: Ubuntu Linux - gcc 5.4.0

scanf("%*[^\n]\n"); 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]\n");

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

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

    return 0;
}

Output:

$ ./bug 
Write number: 
2
Write phrase: 


You wrote:2 and "
"

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;
}

Output:

$ ./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:

Working approach:

#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;
}

Output:

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


You wrote:4 and "phrase :D
"

回答1:


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");

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.



来源:https://stackoverflow.com/questions/41928145/why-arent-scanf-n-n-and-scanf-nc-clearing-a-hanging-newli

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!