Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between `"%[^\n]"` and `"%[^\n]\n"` and `"%[^\n]%*c"` in C how do they work?

Tags:

I could not find the answer anywhere else.

%[^\n] - When I run this one, scanf is getting input and terminating after I press enter. ( Probably leaving \n in the input system)

%[^\n]\n - this one is getting the input but scanf is NOT terminating immediately after I press enter like the one above. I hit more enter and it makes more newlines. When I give a character and then press enter it finally terminates. Example:

int main(void)
{
    char s[100];

    scanf("%[^\n]\n", s);

    printf("%s", s);

    return 0;
}

The results:

enter image description here

Last one:

%[^\n]%*c - When I give some input and press enter. scanf immediately terminates.

How do those 3 work and how do they differ?

like image 450
Ali Uyanık Avatar asked May 28 '20 18:05

Ali Uyanık


People also ask

What does %[ n ]%* c mean in c?

^\n stands for taking input until a newline isn't encountered. Then, with this %*c, it reads the newline character and here, the used * indicates that this newline character is discarded. Follow this answer to receive notifications.

What does %[ n s do in c?

So scanf("%[^\n]", s); will read all characters until you reach \n (or EOF ) and put them in s . It is a common idiom to read a whole line in C.

What does scanf %[ n ]%* c name mean?

In short, the statement. scanf(“%[^\n]%*c”,name); means that all the characters entered as the input, including the spaces, until we hit the enter button are stored in the variable, name; provided we allocate sufficient memory for the variable.

What's the difference between \n and \n s in AC scanf?

%[^\n] is for reading string until hit to \n or EOF. Whitespaces can be included in the string. %s is for reading string until hit to whitespace or EOF.


1 Answers

All 3 format begin with "%[^\n]".

"%[^\n]" is poor code2 that lacks a width limit and is susceptible to buffer overrun. Use a width limit like "%99[^\n]" with char s[100];.

"%[...]" does not consume leading whitespace like many other specifiers.

This specifier directs reading input until a '\n'1 is encountered. The '\n' is put back into stdin. All other characters are saved in the matching destination's array s.

If no characters were read (not counting the '\n'), the specifier fails and scanf() returns without changing s - rest of the format is not used. No null character appended.

If characters were read, they are saved and a null character is appended to s and scanning continues with the next portion of the format.


"\n" acts just like " ", "\t", "any_white_space_chracter" and reads and tosses 0 or more whitespace characters. It continues to do so until a non-white-space1 is read. That non-whitespace character is put back into stdin.

Given line buffered input, this means a line with non-whitespace following input is needed to see the next non-whitespace and allow scanf() to move on.

With scanf(), a "\n" at the end of a format is bad and caused OP's problem.


"%*c" reads 1 character1 and throws it away - even if it is not a '\n'. This specifier does not contribute to the return count due to the '*'.


A better alternative is to use fgets().

char s[100];
if (fgets(s, sizeof s, stdin)) {
   s[strcspn(s, "\n")] = '\0';  // To lop off potential trailing \n

A lesser alternative is

char s[100] = { 0 };
scanf("%99[^\n]", s);
// With a separate scanf ....
scanf("%*1[\n]");  // read the next character if it is a \n and toss it.

1 ... or end-of-file or rare input error.

2 IMO, worse than gets().

like image 136
chux - Reinstate Monica Avatar answered Oct 05 '22 16:10

chux - Reinstate Monica