将参数放入char数组中,代码说明

时间:2014-11-22 17:28:06

标签: c arrays string pointers char

我真的想知道下面一段代码中发生了什么。在函数解析中,*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);  

5 个答案:

答案 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;,因为*argvchar *,而不是字符。这不是正式的错误; '\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

与上述相同的解释