What does scanf REMOVES from input after scanning?

2019-09-21 01:46发布

I have gone through many questions and blogs and books, but I guess I'm just not able to relate things properly. What does scanf do after scanning? It reads everything except space, tab and newline, but what does it do to newline?? I'm unable to remove newline any way after scanning input. For example, consider this as input:-

5
Abcdefgh

Now, I have scanned 5 as integer,

 scanf("%d", &i); 

but how do I remove '\n' in order to read everything ahead one character at a time? I want to use:-

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

The '\n' is supposed to be the one AFTER the string, but getchar() gets the one after 5 and loop terminates before even running once. I guess I'm just missing a very little trick.

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

Input File:-
5
ABCDEF
Expecting while loop to run, while it doesn't run. Because it catches '\n' after 5. I have tried adding getchar() in between scanf() and while(), but then program stucks and does nothing.

标签: c scanf getchar
4条回答
疯言疯语
2楼-- · 2019-09-21 02:26

If you add a space after the %d in your scanf format specifier, scanf will not return until it encounters any non-whitespace character. This will effectively consume any number of newlines or other spaces in your input. As pointed out by @BlueMoon, note that this relies on the program receiving more non-whitespace input after the newline. So it works for this example but might cause trouble elsewhere.

Here's a minimal example:

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

sample input:

5   


abcdefg

output:

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

edit: Note that this issue can be circumvented by using fgets to read a line into a character buffer, then extracting the integer using sscanf:

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

fgets reads until a newline or end of file is encountered, or SIZE-1 bytes have been read. Assuming you're only expecting the line to contain one integer, this limitation shouldn't be an issue. As long as SIZE is large enough, the newline will be consumed by fgets and the subsequent getchar in the loop will work as expected.

查看更多
聊天终结者
3楼-- · 2019-09-21 02:34

Since you are using Windows, there is a '\r' character before the '\n' character.

The "adding a getchar(); before your while loop" trick doesn't work because this getchar() is getting the '\r' character. So when the while condition is first evaluated, c is '\n'.

So a trivial fix would be to use TWO getchar() calls to consume the '\r\n'. However, this is not very portable, that is, it won't work on other systems.

So I would use the following:

int main() {
    int i;
    char c;
    scanf("%d", &i);
    if(getchar()=='\r') getchar();
    while((c=getchar())!='\n') {
        printf("%c\n", c);
    }
    return 0;
}
查看更多
我命由我不由天
4楼-- · 2019-09-21 02:34

You can use a getchar() right after the scanf() call to consume the \n so that it doesn't interfere with your loop.

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

I ran the above code in the same as you do: ./a.out < file on Linux and on windows using mingw and I don't see any problem.

查看更多
何必那么认真
5楼-- · 2019-09-21 02:38

If you take character or string inputs, use getchar() after every integer inputs. This will remove the \n from the input buffer.

scanf("%d", &i);
getchar();
while((c=getchar())!='\n'){//Do something} 
查看更多
登录 后发表回答