Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scanf: "%[^\n]" skips the 2nd input but " %[^\n]" does not. why?

Tags:

c

scanf

People also ask

Why does scanf skip one input every time the loop runs?

That means the next time you read from standard input there will be a newline waiting for you (which will make the next scanf() call return instantly with no data). To avoid this, you can modify your code to something like: scanf("%c%*c", &currentGuess);

What is %[ n in scanf?

In C, %n is a special format specifier. In the case of printf() function the %n assign the number of characters printed by printf(). When we use the %n specifier in scanf() it will assign the number of characters read by the scanf() function until it occurs.

Does scanf skip newline?

The scanf() function skips leading whitespace automatically before trying to parse conversions other than characters. The character formats (primarily %c ; also scan sets %[…] — and %n ) are the exception; they don't skip whitespace.

Can I use multiple scanf in c?

If you have multiple format specifiers within the string argument of scanf, you can input multiple values. All you need to do is to separate each format specifier with a DELIMITER - a string that separates variables.


You just need to 'consume' the '\n' character after you've read what you want. Use the following format directive:

"%[^\n]%*c"

Which will read everything up to the newline into the string you pass in, then will consume a single character (the newline) without assigning it to anything (that '*' is 'assignment suppression').

Otherwise,the newline is left in the input stream waiting to immediately terminate the the subsequent "%[^\n]" format directives.

The problem with adding a space character to the format directive (" %[^\n]") is that the space will match any white space. So, it will eat the newline from the end of the previous input, but it will also eat any other whitespace (including multiple newlines).

Update to your example:

  char* fmt = "%[^\n]%*c";

  printf ("\nEnter str1: ");
  scanf (fmt, str1);
  printf ("\nstr1 = %s", str1);

  printf ("\nEnter str2: ");
  scanf (fmt, str2);
  printf ("\nstr2 = %s", str2);

  printf ("\nEnter str3: ");
  scanf (fmt, str3);
  printf ("\nstr2 = %s", str3);

  printf ("\n");

When you use scanf() to read the strings, your format string (%[^\n]) tells the function to read every character that is not '\n'. That leaves the '\n' character in the input buffer. So when you try to read str2 and str3, scanf() finds the first thing in the buffer is '\n' each time and, because of the format string, doesn't remove it from the input buffer. What you need is a getchar() between the times that you read from the input buffer (often placed immediately after scanf()). Since there is already a '\n' in the buffer, your program won't appear to hang because it won't have to wait for input for getchar() to receive. Try it. :)

For those who haven't a clue what that scanf() modifier does, here is a relevant excerpt from http://linux.die.net/man/3/scanf -

[

Matches a nonempty sequence of characters from the specified set of accepted characters; the next pointer must be a pointer to char, and there must be enough room for all the characters in the string, plus a terminating null byte. The usual skip of leading white space is suppressed. The string is to be made up of characters in (or not in) a particular set; the set is defined by the characters between the open bracket [ character and a close bracket ] character. The set excludes those characters if the first character after the open bracket is a circumflex (^). To include a close bracket in the set, make it the first character after the open bracket or the circumflex; any other position will end the set. The hyphen character - is also special; when placed between two other characters, it adds all intervening characters to the set. To include a hyphen, make it the last character before the final close bracket. For instance, [^]0-9-] means the set "everything except close bracket, zero through nine, and hyphen". The string ends with the appearance of a character not in the (or, with a circumflex, in) set or when the field width runs out.


ALSO: To read a string:

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

// it means read until you meet '\n', then trash that '\n'

:)


Just adding a bit further to above answer- If we want to remove some specific pattern, suppose numbers 0-9, from input stream then we will have to use getchar() for flushing buffer.

scanf("%[^0-9\n]", str1);
while(getchar() != '\n'); // this approach is much better bcz it will
                         // remove any number of left characters in buffer.
scanf("%c", &ch);

So here if you pass ashish019 then only ashish will be copied to str and 019 would be left in buffer so for clearing that you need getchar() multiple times.


Just use a getchar() after the scanf() function.