我不知道如何将行与单词“ exit”进行比较,以便在退出键盘输入时程序将退出。 #定义MAX_LINE 4096 #define MAX_WORDS MAX_LINE / 2
int main()
{
char line[MAX_LINE], *words[MAX_WORDS], message[MAX_LINE];
int stop=0,nwords=0;
while(1)
{
printf("OSP CLI $ ");
fgets(line,MAX_LINE,stdin);
if(strcmp(line,"exit")==0)
{
exit(0);
}
void tokenize(char *line, char **words, int *nwords)
{
*nwords=1;
for(words[0]=strtok(line," \t\n");
(*nwords<MAX_WORDS)&&(words[*nwords]=strtok(NULL, " \t\n"));
*nwords=*nwords+1
); /* empty body */
return;
}
该代码是正确的,但我不知道它的作用。因此,for(words [0] = strtok(line,“ \ t \ n”);读取该行的第一个单词。“ line”是用户在运行时输入的键盘输入,它只是一个字符串,如:hello worldblah dee doo。但是在那之后,下一行用nwords <.....在for之后就什么都不懂了。
答案 0 :(得分:3)
for (a; b; c) d;
可以翻译为:
a;
while (b) {
d;
c;
}
所以:
void tokenize(char *line, char **words, int *nwords)
{
*nwords=1;
for(words[0]=strtok(line," \t\n");
(*nwords<MAX_WORDS)&&(words[*nwords]=strtok(NULL, " \t\n"));
*nwords=*nwords+1
); /* empty body */
return;
}
可以翻译成(经过一些其他改进,例如int *a; if (a)
与int *a; if (a != NULL)
相同)
void tokenize(char *line, char **words, int *nwords)
{
*nwords = 1;
words[0] = strtok(line, " \t\n");
while (
*nwords < MAX_WORDS &&
(words[*nwords] = strtok(NULL, " \t\n")) != NULL
) {
/* empty body */
*nwords = *nwords + 1;
}
}
让我们再详细一点:
void tokenize(char *line, char **words, int *nwords)
{
*nwords = 1;
words[0] = strtok(line, " \t\n");
while (*nwords < MAX_WORDS) {
words[*nwords] = strtok(NULL, " \t\n");
if (words[*nwords] == NULL) {
break;
}
/* empty body */
*nwords = *nwords + 1;
}
}
此函数很危险,或者可能是更大的一部分的一部分(不检查参数是否为null,如果行为空则省略)。
words
是一个指针,它是char*
指针的数组。 words
指针的长度似乎至少为MAX_WORDS
长。 nwords
是指向words
指针的返回长度的指针。调用者希望此函数用字符串中的标记填充words
存储器和nwords
存储器。假定所有指针都不是NULL且有效,MAX_WORDS > 0
和strlen(line) != 0
或字符串line
不仅仅由我们使用的" \t\n"
分隔符组成,因此存在始终是第一个令牌。
nwords
用1
初始化,然后提取第一个令牌words[0] = strtok(line, " \t\n");
。 MAX_WORDS
为止,提取下一个令牌words[*nwords] = strtok(NULL, " \t\n")
strtok
手册开始-从strtok
返回的值是“如果没有更多令牌,则返回NULL”。如果strtok
返回NULL,则意味着我们完成了字符串-因此我们从函数返回。MAX_WORDS
,并且我们提取了下一个有效令牌,则会增加计数*nwords = *nwords + 1;
words
字符串内的指针初始化了line
,并用令牌计数初始化了nwords
后面的内存,并将line
数组修改为用终止零'\0'
代替令牌定界符。答案 1 :(得分:2)
让我们重新编写代码,使其更简洁,更易读:
void tokenize(char *line, char **words, int *nwords)
{
*nwords=1;
words[0]=strtok(line," \t\n");
while (*nwords < MAX_WORDS) {
words[*nwords] = strtok(NULL, " \t\n");
if (!words[*nwords])
break;
*nwords = *nwords + 1;
}
}
使此代码更难理解的一件事是,它始终通过nwords
指针间接访问单词数。没有这个速记,这里还有一个重写:
void tokenize(char *line, char **words, int *nwords)
{
int wordCount = 1;
words[0]=strtok(line," \t\n");
while (wordCount < MAX_WORDS) {
words[wordCount] = strtok(NULL, " \t\n");
if (!words[wordCount])
break;
wordCount = wordCount + 1;
}
*nwords = wordCount;
}
最后,对于指针p
,测试!p
与测试p == NULL
相同。因此,检查if (!words[wordCount])
的意思是“如果words
中当前的最后一个元素是空指针。”当strtok
返回空指针,表明它已完成解析时,可能会发生这种情况。
希望现在已经清楚了。
通常,该函数使用strtok
从line
中提取单词并将它们存储到数组words
的连续元素中,存储的单词数返回到{{1} }。
它将重复提取一个单词,存储它,并增加单词数。这一直持续到以下任何一种情况:
nwords
,或MAX_WORDS
返回一个空指针,表示strtok
中没有剩余的单词。