ammasum
ammasum

Reputation: 128

%[^\n]s in scanf does not wait for input and gets skipped

In the loop in the code below, scanf("%[^\n]s",array) is not working. It does not wait for input and gets skipped. But a space before % fixes the issue. Why?

Here is the wrong program:

#include <string.h>
#include <stdio.h>

int main()    
{    
    int t;
    scanf("%d",&t);
    while(t--){
        char arr[199];
        scanf("%[^\n]s",arr);
        printf("%s",arr);
    }
    return 0;
}

Here is right code:

#include <string.h>
#include <stdio.h>

int main()
{    
    int t;
    scanf("%d",&t);
    while(t--){
        char arr[199];
        scanf(" %[^\n]s",arr);
        printf("%s",arr);
    }
    return 0;
}

Why does it need a space before % for it to work as expected?

Upvotes: 6

Views: 2622

Answers (2)

Spikatrix
Spikatrix

Reputation: 20244

First of all, the trailing s is not part of the %[ format specifier, so remove it and lets talk about %[^\n].

Now, what %[^\n] tells scanf to do is scan everything until a newline character ('\n') or EOF, whichever comes first, and stores it in its corresponding argument, in this case, arr.

And here is the catch: %[^\n] fails if the first character to be read is a \n.

'Wait', you say. 'I did not type in a lone enter. So, why'd it fail?'. True. You did not. But remember the Enter you pressed for the previous line? Turns out, the previous call to scanf grabs everything until the \n, leaves the \n there and returns. So, in the next iteration of the loop, the scanf sees this \n character left over by the previous call to scanf, fails and returns 0.

As for the space, it is a whitespace character. And a whitespace character in scanf instructs it to scan and discard all whitespace characters until the first non-whitespace character. So, it removes the \n (since it is a whitespace character) and scanf will wait for further input.

Upvotes: 3

P.P
P.P

Reputation: 121387

With this format %[^\n], scanf() stops after reading a newline. So, after the first input, there's a newline left which isn't consumed. So, subsequent scanf() calls don't read any input at all.

With a space in %[^\n], scanf() ignores any number of whitespace chars. Hence, scanf() ignores the leftover newlines. From scanf:

A sequence of white-space characters (space, tab, newline, etc.; see isspace(3)). This directive matches any amount of white space, including none, in the input.

By the way, you don't need that extra s at the end of the format string.

Use fgets() which is generally superior to scanf() (fgets() will read the newline char into the buffer if there's space). Also see: Why does everyone say not to use scanf? What should I use instead?.

Upvotes: 1

Related Questions