1

目前我正在阅读一行字符串并对其进行解析。我正在使用以下变量来执行此操作:char **parsedchar *parsed_arguments[64]. 这是我用来解析它的代码:

char newcommand []
parsed =  parsed_arguments;
*parsed++ = strtok(newcommand,SEPARATORS);   // tokenize input
while ((*parsed++ = strtok(NULL,SEPARATORS)))

那部分很好而且很花哨,但是当我尝试添加到 parsed_arguments 时出现了我的问题。我想要完成的是从文件中读取文本,将其放入char buffer[],标记,并将其添加到,parsed_arguments以便我可以将这些参数传递给使用execvp. 到目前为止,我能够阅读文本并将其放入我的缓冲区中,我什至尝试过对其进行标记,但最后一部分让我感到困惑。这里有更多代码详细说明我正在做的事情:

if(file_In)
  {
    //strcpy(input_File_Name,parsed_arguments[input_Index]);

    switch(pid =fork())
      {
      case -1:
        printf("fork error, aborting\n");
        abort();
      case 0:
        parsed_arguments[input_Index-1] = NULL; 
        input_File = freopen(parsed_arguments[input_Index],"r",stdin);
        fgets(buffer, 1023, input_File);

        buf =  parsed_buf;
        *buf++ = strtok(buffer,SEPARATORS);   // tokenize input
        while ((*buf++ = strtok(NULL,SEPARATORS)))

        //strcat(parsed, buf); // invalid

        printf("The buffer holds: %s\n", buffer);
        execvp(parsed_arguments[0],parsed_arguments);

        break;
      default:
        waitpid(pid,NULL,WUNTRACED);
4

1 回答 1

0

I think you might be overthinking this problem. Based on the parsing code at the top of your question, you have already solved the problem.

parsed =  parsed_arguments; 
/* parsed now points to the first element parsed_arguments */
*parsed++ = strtok(newcommand,SEPARATORS);   // tokenize input
while ((*parsed++ = strtok(NULL,SEPARATORS)))
    ; /* habit of mine */
/* At this point, parsed_arguments should be now populated with each
   token from newcommand by strtok
   Minus a few caveats, the following call should be valid */
execvp(parsed_arguments[0], parsed_arguments);

Before I describe the caveats that I mentioned (that I know of), I'll quickly explain why this should work: strtok returns the pointer of the last token found in its first argument. This pointer is then written in this variable: *parsed++ (which is an expression that evaluates into an l-value). This dereferences the address pointed to by parsed(which is an element of parsed_arguments). Finally, the post-fix ++ operator simply makes parsed point to the next element of parsed_arguments after the full expression is evaluated.

The important thing to note, is parsed points to the same block of memory occupied by parsed_arguments. By setting parsed = parsed_arguments, *parsed = token is equivalent to parsed_arguments[some_index] = token.

You could express your code (not quite as elegantly) without pointer arithmetic as such:

int argc = 0;
/* declarations, etc *SNIP* */
parsed_arguments[argc] = strtok(newcommand, delim);
while (parsed_arguments[argc++]) {
    parsed_arguments[argc] = strtok(NULL, delim);
}

I hope this is the answer you were looking for, or at least helps point you in the right direction, based on the actual code provided (since a lot is missing, for obvious reasons), and there is a parsed_buf, buf that seem to mimic parsed and parsed_arguments, but those also exist in the code, I am not 100% sure if I completely understand what you are trying to do.

Caveats

execvp(...)'s documentation states that by convention, the first element of the arguments should be the file name (I see that you already know this), but nonetheless, make sure the program name is the first element--either have your file's content have the program name first, or just start from the second element.

execvp(...) also states that the last argument should be a NULL pointer. You can ensure this by a call to memset(parsed_arguments, 0, sizeof(parsed_arguments)); and ensuring the file never specifies more than 64 arguments.

http://linux.die.net/man/3/execvp

Lastly, (possibly nit-picking), while (pointer) works on the premise that NULL == 0 (in most cases, it is (void *) 0 AFAIK), I don't know how important it is to you, but if you ever run into an implementation where NULL is not defined as 0, it might cause some issues. So, it would be safer to write while ((*parsed++ = strtok(NULL, SEPARATORS)) != NULL). My two cents anyway.

于 2013-04-28T04:05:59.783 回答