简体   繁体   中英

Putting arguments into a char array, code explanation

I'd really want to know what is going on in a following piece of code. In function parse, what does *line++ = '\\0'; mean? Is it equal to line[i] = '\\0' and i++; ?

Next, what is this *argv++ = line; doing? How can it assign whole variable line to I assume first argv[0], then argv[1] etc? Wouldn't that be too long?

Next while is just skipping through line array till it reaches a word.

Now, after the parse function is done, what does calling argv and argv* do? is *argv the first argument?

Thanks in advance, I really need to understand that : (

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';   
}

and in main:

 char  line[1024];      
 char  *argv[64];    
 while (1) {  
      ....
      gets(line); 
      ...
      parse(line, argv);  

The expression *line++ = '\\0'; is straight-forward. As some people have noted, the ++ operator has a higher precedence than the * operator, so the expression could be parenthesized as *(line++) = '\\0'; .

The line++ operator evaluates to the current value of line and then increments the value in line. The *line++ therefore evaluates to the character that line currently points at. The assignment means that a null byte '\\0' is assigned to the current position, and line is incremented past this position. It is a shorthand for:

*line = '\0';
line++;

In the question, you ask:

What does *line++ = '\\0'; mean? Is it equal to line[i] = '\\0' and i++; ?

The first part has been addressed. The second part is more or less accurate; strictly, it only applies if i = 0; is assigned first (so i would be 1 after the increment), or if you always used i to index line without changing the value of line itself.

Note that the line *argv = '\\0'; line would be more conventionally written *argv = NULL; or *argv = 0; since *argv is a char * , not a character. It is not formally incorrect; '\\0' is an integer constant zero, and therefore a valid null pointer constant, but it is aconventional to write it that way.

In the given code:

void parse(char *line, char **argv)
{
     while (*line != '\0') {
          while (*line == ' ' || *line == '\t' || *line == '\n')
               *line++ = '\0';

There's no need to zap the leading blanks; it would be sufficient to write line++ . It's also tempting to suggest the use of isspace() or isblank() . I observe that input from gets() (which is shown in the main() program and should not be used) never contains a newline, so the newline test is redundant in this context.

          *argv++ = line;

          while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n')
               line++;
     }
     *argv = '\0';
}

The idea is that if the input line is:

arguments   about   the  meaning of life

then afterwards, you'd be able to make all of the following assertions safely:

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);

Given that you're chopping up the input line, it might be sensible to consider the POSIX strtok_r() function or Microsoft's strtok_s() (or, if the worst comes to the worst, strtok() , but using strtok() requires extreme caution — no code calling this function can be using strtok() at the time the call is made, for example).

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;
}

It might also be sensible to redesign the function to report how many (non-null) arguments there are:

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;
}

The *line++ = '\\0' is equal to:

*line = '\0';
line++;

It is used to null-terminate a string, as it should be in C.

The *argv++ = line is meant to parse the next argument from the arguments supplied in the char **argv (pointer to the char array).

char * line

means that you get a pointer to a char. So let's make clear that

*line

would get you the actual character (this is called dereferencing) So what *line++ = '\\0'; does is:

*line = '\0';
line++;

So it is the same as line[i++] = '\\0' .

Exactly the same applies to *argv++ = line;

Notice that *line++ is completely different than (*line)++ .

Actually since the assignment operator has higher precedence over the ++ then *line++ = '\\0'; actually equals to:

*line = '\0';
*line++;          // Increment the pointer in sizeof(char)

Now, regarding you question about argv, then please note that it is defined as an array of strings. The type of *argv is then char* which match the type of line. The assignment *argv++ = line means placing the address pointed by line to *argv (and not a full copy of the string in line) so there is no risk of writing too much into it (unless argv does not contain enough elements to hold the number of lines). Finally, the statement *argv = '\\0' is probably there to mark that we just reached the end of the array of strings, in a similar way end of string is marked in C.

The ++ operator has higher precedence than * so

*line++ will lead to pointer line being inceremented first.

line++;

Then

*line++ = '\0';

argv is a double pointer here and *argv will be pointing to line .

*argv++ = line

Same explanation as above

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM