[英]Can scanf identify a format character within a string?

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:



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?


3 个解决方案


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.



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.

如果您實際使用的是C ++,請研究c ++字符串和流類的使用,這些類更強大,更安全。


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].

我想最好為此編寫自己的解析函數。但是如果你仍然喜歡scanf,盡管存在陷阱,你可以做一些解決方法,只需用%[^,\ t \ r \ n]代替%s。

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).

%s匹配非空白字符序列的問題,所以它也吞下逗號。因此,如果用%[^,\ t \ r \ n \ n]替換%s,它將幾乎相同(不同之處在於%s使用isspace(3)來匹配空格字符,但在這種情況下,您明確指定了哪些空格字符匹配和此列表可能與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".

請注意,如果要在逗號之前和之后允許空格,則必須在格式字符串中添加空格。格式字符串“%[^,\ t \ r \ n],%[^,\ t \ r \ n]”匹配“hello,world”,“hello,world”,“hello,world”等字符串。



粤ICP备14056181号  © 2014-2021