我真的想知道下面一段代码中发生了什么。在函数解析中,*line++ = '\0';
是什么意思?它等于line[i] = '\0'
和i++;
吗?
接下来,*argv++ = line;
做了什么?它如何分配整个变量行我假设首先是argv [0],然后是argv [1]等?不会太长了吗?
接下来只是跳过线阵直到它到达一个单词。
现在,在解析函数完成后,调用argv和argv *会做什么? * argv是第一个参数吗?
在此先感谢,我真的需要理解:(
void parse(char *line, char **argv)
{
while (*line != '\0') {
while (*line == ' ' || *line == '\t' || *line == '\n')
*line++ = '\0';
*argv++ = line;
while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n')
line++;
}
*argv = '\0';
}
并在主要:
char line[1024];
char *argv[64];
while (1) {
....
gets(line);
...
parse(line, argv);
答案 0 :(得分:2)
表达式*line++ = '\0';
是直截了当的。正如一些人所指出的那样,++
运算符的优先级高于*
运算符,因此表达式可以括号为*(line++) = '\0';
。
line++
运算符求值为line
的当前值,然后按行递增值。因此,*line++
会计算line
当前指向的字符。赋值意味着将空字节'\0'
分配给当前位置,line
递增超过此位置。这是一个简写:
*line = '\0';
line++;
在问题中,你问:
*line++ = '\0';
是什么意思?它等于line[i] = '\0'
和i++;
吗?
第一部分已得到解决。第二部分或多或少准确;严格来说,它仅适用于首先分配i = 0;
(因此i
在增量后为1
),或者如果您始终使用i
索引line
不改变line
本身的值。
请注意,*argv = '\0';
行更常规地写为*argv = NULL;
或*argv = 0;
,因为*argv
是char *
,而不是字符。这不是正式的错误; '\0'
是一个整数常量零,因此是一个有效的空指针常量,但以这种方式写它是常规的。
在给定的代码中:
void parse(char *line, char **argv)
{
while (*line != '\0') {
while (*line == ' ' || *line == '\t' || *line == '\n')
*line++ = '\0';
没有必要消除领先的空白;写line++
就足够了。建议使用isspace()
或isblank()
也很有吸引力。我观察到来自gets()
的输入(显示在main()
程序中且不应该使用)从不包含换行符,因此在此上下文中换行测试是多余的。
*argv++ = line;
while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n')
line++;
}
*argv = '\0';
}
这个想法是,如果输入行是:
arguments about the meaning of life
然后,您可以安全地进行以下所有断言:
assert(strcmp(argv[0], "arguments") == 0);
assert(strcmp(argv[1], "about") == 0);
assert(strcmp(argv[2], "the") == 0);
assert(strcmp(argv[3], "meaning") == 0);
assert(strcmp(argv[4], "of") == 0);
assert(strcmp(argv[5], "life") == 0);
assert(argv[6] == 0);
鉴于您正在切断输入行,考虑POSIX strtok_r()
函数或Microsoft strtok_s()
(或者,如果最坏的情况发生在那里)可能是明智的。最糟糕的是,strtok()
,但使用strtok()
需要格外小心 - 例如,调用此函数的代码不能在调用时使用strtok()
。
void parse(char *line, char **argv)
{
char *token = line;
char *extra;
while ((token = strtok_r(token, " \t\n", &extra)) != 0)
{
*argv++ = token;
token = 0;
}
*argv = 0;
}
重新设计函数来报告有多少(非空)参数可能也是明智的:
int parse(char *line, char **p_argv)
{
char *token = line;
char *extra;
char **argv = p_argv;
while ((token = strtok_r(token, " \t\n", &extra)) != 0)
{
*argv++ = token;
token = 0;
}
*argv = 0;
return argv - p_argv;
}
答案 1 :(得分:1)
*line++ = '\0'
等于:
*line = '\0';
line++;
它用于空终止字符串,因为它应该在C中。
*argv++ = line
用于解析char **argv
中提供的参数的下一个参数(指向char
数组的指针)。
答案 2 :(得分:1)
char * line
表示您获得指向char的指针。所以让我们明确一下
*line
可以获得实际角色(这称为解除引用)
那么*line++ = '\0';
的作用是:
*line = '\0';
line++;
所以它与line[i++] = '\0'
相同。
完全相同适用于* argv ++ = line;
注意 * line ++与(* line)++完全不同。
答案 3 :(得分:0)
实际上由于赋值运算符的优先级高于++
,因此*line++ = '\0';
实际上等于:
*line = '\0';
*line++; // Increment the pointer in sizeof(char)
现在,关于你关于argv的问题,请注意它被定义为一个字符串数组。
*argv
的类型是char*
,它与行的类型相匹配。赋值*argv++ = line
意味着将行指向的地址放在* argv中(而不是字符串的完整副本),因此不存在写入太多内容的风险(除非argv不包含足够的元素来保存)行的数量。
最后,语句*argv = '\0'
可能标记为我们刚刚到达字符串数组的末尾,类似地,字符串的结尾在C中标记。
答案 4 :(得分:-1)
++
运算符的优先级高于*
所以
*line++
将导致指针line
首先被复制。
line++;
然后
*line++ = '\0';
argv
此处为双指针,*argv
将指向line
。
*argv++ = line
与上述相同的解释