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

あなたはこの問題を考えすぎているのではないかと思います。質問の上部にある解析コードに基づいて、問題は既に解決されています。

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

私が言及した (私が知っている) 注意事項を説明する前に、これが機能 する理由strtokを簡単に説明します。最初の引数で見つかった最後のトークンのポインターを返します。このポインターは、この変数に書き込まれます: *parsed++(これは左辺値に評価される式です)。parsedこれは ( の要素である) が指すアドレスを逆参照しますparsed_arguments。最後に、後置++演算子は、完全な式が評価されたparsedの次の要素を指すだけです。parsed_arguments

注意すべき重要なことは、 がparsed占有するメモリの同じブロックを指していることparsed_argumentsです。を設定することparsed = parsed_argumentsで、*parsed = tokenと同等parsed_arguments[some_index] = tokenです。

ポインター演算を使用せずにコードを (それほどエレガントではありませんが) 表現できます。

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

これがあなたが探していた答えであるか、少なくとも提供された実際のコードに基づいて正しい方向に向けるのに役立つことを願っています(明らかな理由で多くが欠落しているparsed_bufため)buf 。、しかしそれらはコードにも存在します。あなたがやろうとしていることを完全に理解しているかどうかは100%確信が持てません。parsedparsed_arguments

注意事項

execvp(...)のドキュメントには、慣例により、引数の最初の要素はファイル名にする必要があると記載されています (これは既にご存知だと思います) が、それでも、プログラム名が最初の要素であることを確認してください。プログラム名を最初にするか、2 番目の要素から始めます。

execvp(...)また、最後の引数は NULL ポインターでなければならないと述べています。を呼び出してmemset(parsed_arguments, 0, sizeof(parsed_arguments));、ファイルが 64 個を超える引数を指定しないようにすることで、これを確実にすることができます。

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

最後に、(おそらくニッチピッキング)、(ほとんどの場合、それはAFAIKです)while (pointer)という前提で機能します。それがあなたにとってどれほど重要かはわかりませんが、0として定義されていない実装に遭遇した場合、それはいくつかの問題を引き起こす可能性があります。したがって、 と書いた方が安全です。とにかく私の2セント。NULL == 0(void *) 0NULLwhile ((*parsed++ = strtok(NULL, SEPARATORS)) != NULL)

于 2013-04-28T04:05:59.783 に答える