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

Consider the following code:

#include <stdio.h>

int main (void)
{
  char str1[128], str2[128], str3[128];

  printf ("\nEnter str1: ");
  scanf ("%[^\n]", str1);
  printf ("\nstr1 = %s", str1);

  printf ("\nEnter str2: ");
  scanf ("%[^\n]", str2);
  printf ("\nstr2 = %s", str2);

  printf ("\nEnter str3: ");
  scanf ("%[^\n]", str3);
  printf ("\nstr3 = %s", str3);

  printf ("\n");
  return 0;
}

When it is executed only the first scanf stops for the prompt. The program does not stop for the next scanf s. But if the format string is changed from "%[^\n]" to " %[^\n]" (note the blank space before %), then it works okay. Does some existing newline character from the previous input buffer is automatically accepted ? But flushing stdin does not solve this.

What is the cause of this.


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'

:)