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 toline[i] = '\\0'
andi++;
?
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.