1

假设我希望标准输入中的项目列表是用逗号分隔的,如下所示:

 item1, item2, item3,...,itemn

而且我还想允许用户在项目和逗号之间发出空格,所以这种输入在我的程序中是合法的:

item1,item2,item3,...,itemn

如果我scanf这样使用:

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

当没有空格(我测试过)时它将失败,因为它将整个输入称为一个字符串。那么如何仅使用 C 标准库函数来解决这个问题呢?

4

3 回答 3

8

快速的答案是永远不要使用 scanf 来读取用户输入。它旨在从文件中读取严格格式化的输入,即使这样也不是很好。至少,您应该阅读整行,然后使用 sscanf() 解析它们,这给了您一些纠正错误的机会。充其量你应该编写自己的解析函数

如果您实际使用 C++,请研究 c++ 字符串和流类的使用,它们更加强大和安全。

于 2009-07-12T20:02:21.987 回答
7

你可以看看strtok。首先将行读入缓冲区,然后标记化:

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);
}

但是,strtok您需要注意与 reentrence 相关的潜在问题

于 2009-07-12T19:59:12.710 回答
2

我想最好为此编写自己的解析函数。但是,如果您仍然喜欢 scanf,尽管它存在缺陷,您可以做一些解决方法,只需将 %s 替换为 %[^, \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".

于 2009-07-12T20:35:00.047 回答