你不应该那样使用feof()
。您应该使用fgets()
或等效。您可能需要使用鲜为人知(但存在于标准 C89 中)的转换说明符%n
。
#include <stdio.h>
int main(void)
{
char buffer[1024];
while (fgets(buffer, sizeof(buffer), stdin) != 0)
{
char *str = buffer;
char word[256];
int posn;
while (sscanf(str, "%255s%n", word, &posn) == 1)
{
printf("Word: <<%s>>\n", word);
str += posn;
}
}
return(0);
}
这会读取一行,然后sscanf()
迭代地使用从该行中获取单词。%n
格式说明符不计入成功的转换,因此与 1 进行比较。注意使用以%255s
防止word
. 还要注意,在转换规范中指定的 255 计数之后可能会写入 null,因此声明 of和转换说明符sscanf()
之间的差异为 1 。char word[256];
%255s
显然,您可以决定如何处理提取的每个单词。这里的代码只是打印它。
与基于任何解决方案的任何解决方案相比,此技术的一个优点strtok()
是sscanf()
不会修改输入字符串,因此如果您需要报告错误,您可以在错误报告中使用原始输入行。
编辑问题后,似乎一个单词中都不需要分号之类的标点符号;上面的代码将包含标点符号作为单词的一部分。在这种情况下,您必须更加努力地考虑要做什么。起点很可能是使用字母数字扫描集作为转换规范来代替%255s
:
"%255[a-zA-Z_0-9]%n"
然后,您可能必须查看下一个组件开头的字符中的内容,如果它不是字母数字则跳过它:
if (!isalnum((unsigned char)*str))
{
if (sscanf(str, "%*[^a-zA-Z_0-9]%n", &posn) == 0)
str += posn;
}
导致:
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char buffer[1024];
while (fgets(buffer, sizeof(buffer), stdin) != 0)
{
char *str = buffer;
char word[256];
int posn;
while (sscanf(str, "%255[a-zA-Z_0-9]%n", word, &posn) == 1)
{
printf("Word: <<%s>>\n", word);
str += posn;
if (!isalnum((unsigned char)*str))
{
if (sscanf(str, "%*[^a-zA-Z_0-9]%n", &posn) == 0)
str += posn;
}
}
}
return(0);
}
您需要考虑所选字母数字范围的 I18N 和 L10N 方面;可用的内容可能取决于您的实现(不幸的是,POSIX 没有在scanf()
扫描集中指定对符号的支持,例如[[:alnum:]]
)。