产生正确输出的代码的两个次要变体。
变体 A
#include <string.h>
#include <stdio.h>
int main(void)
{
char line[4096];
if (fgets(line, sizeof(line), stdin) != 0)
{
static const char delims[] = " \"\n";
char *token = strtok(line, delims);
while (token != NULL)
{
printf("\"%s\"\n", token);
token = strtok(NULL, delims);
}
}
return 0;
}
这避免了使用可变长度数组。在 C 中,const int mysize = 100;
andchar mystr[mysize];
创建一个 VLA 因为mysize
不是编译时常量表达式。C++ 将创建一个常规数组。差异在很大程度上无关紧要,但它确实告诉我您正在使用 C99 编译器(或 C++ 编译器)。
但是,常数确实没有任何好处mysize
。你应该sizeof(mystr)
在对 的调用中使用fgets()
,然后mysize
只被引用一次,所以它也可以用一个常量替换——我习惯性地使用 4096 作为单行输入,因为除了书签文件之外的任何东西都不太可能是一条比那更长的单行。
使用变量delims
意味着字符串不重复;如果分隔符更改,则只需更改一行。
我还重命名了变量;'my' 前缀在我看来总是像 'baby talk' 并且从未出现在我的代码中。
请注意,代码在调用fgets()
. 养成检查每个输入函数的返回状态的习惯永远不会太早!在检查输出函数时,我和其他人一样懒惰printf()
,但输入函数真的很重要。
我还消除了输出行的尾随空白;这些真的让我很恼火——就像任何地方的代码中的尾随空格一样。
另请注意,虽然'\0'
它是一个空指针常量,但它不是一种传统的编写方式,并且会导致(轻微的)混乱,然后对滥用'\0'
. 使用NULL
or0
表示空指针;专门'\0'
用于字符。
变体 B
变体 A 代码中有明显的重复;该函数有两次调用strtok()
,但我们可以编写代码,这样只有一次调用,导致:
#include <string.h>
#include <stdio.h>
int main(void)
{
char line[4096];
if (fgets(line, sizeof(line), stdin) != 0)
{
char *token;
for (char *source = line; (token = strtok(source, " \n\"")) != NULL; source = NULL)
printf("\"%s\"\n", token);
}
return 0;
}
由于现在只有一个调用strtok()
,因此只有一个对分隔符的引用,因此它们可以再次成为文字字符串。循环行for
有点长(91 个字符),主要是因为变量名很长。使用src
and tok
(和 0 表示 NULL)可以将其减少到 80 个字符以下,而不会严重损害可读性。
两种变体都对输入行进行标记:
"this is a string"
进入输出:
"this"
"is"
"a"
"string"