tags:

views:

382

answers:

3

Let's say that I expect a list of items from the standard input which are separated buy commas, like this:

 item1, item2, item3,...,itemn

and I also want to permit the user to emit white-spaces between items and commas, so this kind of input is legal in my program:

item1,item2,item3,...,itemn

If I use scanf like this:

scanf("%s,%s,%s,%s,...,%s", s1, s2, s3, s4,...,sn);

it will fail when there are no white-spaces (I tested it) because it will refer to the whole input as one string. So how can I solve this problem only with C standard library functions?

+7  A: 

You could have a look at strtok. First read the line into a buffer, then tokenize:

const int BUFFERSIZE = 32768;
char buffer[BUFFERSIZE];
fgets(buffer, sizeof(buffer), stdin);

const char* delimiters = " ,\n";
char* p = strtok(buffer, delimiters);
while (p != NULL)
{
  printf("%s\n", pch);
  p = strtok(NULL, delimiters);
}

However, with strtok you'll need to be aware of the potential issues related to reentrance.

Pukku
Use strtok_r() to get around re-entrance problems. If your platform doesn't have strtok_r() there's a public domain implementation here: http://snipplr.com/view/16918/strtokr/
Michael Burr
+8  A: 

The quick answer is never, ever use scanf to read user input. It is intended for reading strictly formatted input from files, and even then isn't much good. At the least, you should be reading entire lines and then parsing them with sscanf(), which gives you some chance to correct errors. at best you should be writing your own parsing functions

If you are actually using C++, investigate the use of the c++ string and stream classes, which are much more powerful and safe.

anon
+2  A: 

I guess it is better to write your own parsing function for this. But if you still prefer scanf despite of its pitfalls, you can do some workaround, just substitute %s with %[^, \t\r\n].

The problem that %s match sequence of non white space characters, so it swallows comma too. So if you replace %s with %[^, \t\r\n] it will work almost the same (difference is that %s uses isspace(3) to match space characters but in this case you explicitly specify which space characters to match and this list probably not the same as for isspace).

Please note, if you want to allow spaces before and after comma you must add white space to your format string. Format string "%[^, \t\r\n] , %[^, \t\r\n]" matches strings like "hello,world", "hello, world", "hello , world".

Uh, I don't think Regular Expressions work in `scanf`.
GMan
@GMan: did you check that it doesn't work? It works here.
Adrian Panasiuk
caf