1

私のプログラムでは、ユーザー入力を受け取り、それを2dchar配列に解析しています。配列は次のように宣言されます。

char parsedText[10][255] = {{""},{""},{""},{""},{""},
            {""},{""},{""},{""},{""}};

そして、fgetsを使用してユーザー入力を取得し、sscanfで解析しています。これはすべて、私が思うように機能します。

この後、parsedTextをexecvpに渡したいので、parsedText [0]にパスが含まれている必要があり、引数が指定されている場合は、parsedText[1]からparsedText[10]にある必要があります。

execvp(parsedText [0]、parsedText [1])の何が問題になっていますか?

おそらく言及する価値のあることの1つは、引数なしで「ls」などのコマンドを指定するだけで、問題なく機能するように見えることです。

これが私のコードです:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "308shell.h"

int main( int argc, char *argv[] )
{
char prompt[40] = "308sh";
char text[40] = "";
char parsedText[10][40] = {{""},{""},{""},{""},{""},
                           {""},{""},{""},{""},{""}};

// Check for arguments to change the prompt.
if(argc >= 3){
    if(!(strcmp(argv[1], "-p"))){
        strcpy(prompt, argv[2]);
    }
}

strcat(prompt, "> ");

while(1){
    // Display the prompt.
    fputs(prompt, stdout);
    fflush(stdout);

    // Grab user input and parse it into parsedText. 
    mygetline(text, sizeof text);
    parseInput(text, parsedText);

    // Check if the user wants to exit.
    if(!(strcmp(parsedText[0], "exit"))){
        break;
    }
    execvp(parsedText[0], parsedText[1]);
    printf("%s\n%s\n", parsedText[0], parsedText[1]);
}

return 0;
}

char *mygetline(char *line, int size)
{
if ( fgets(line, size, stdin) )
{
    char *newline = strchr(line, '\n'); /* check for trailing '\n' */
    if ( newline )
    {
        *newline =  '\0'; /* overwrite the '\n' with a terminating null */
    }
}

return line;
}

char *parseInput(char *text, char parsedText[][40]){
char *ptr = text;
char field [ 40 ];
int n;
int count = 0;

while (*ptr != '\0') {
    int items_read = sscanf(ptr, "%s%n", field, &n);
    strcpy(parsedText[count++], field);
    field[0]='\0';
    if (items_read == 1)
        ptr += n; /* advance the pointer by the number of characters read     */
    if ( *ptr != ' ' ) {
        strcpy(parsedText[count], field);
        break; /* didn't find an expected delimiter, done? */
    }
    ++ptr; /* skip the delimiter */
}

}
4

1 に答える 1

2

execvpchar **配列へのポインタではなく、ポインタ()へのポインタを取ります。これは、ポインタの配列の最初の要素へのchar *ポインタであり、nullポインタで終了することになっています。

編集:ポインタの配列を次のようなものに適したものにする1つの(あまり良くない)方法は次のexecvpとおりです。

char argbuf[10][256] = {{0}};
char *args[10] = { argbuf[0], argbuf[1], argbuf[2], /* ... */ };

もちろん、現実の世界では、引数はおそらくユーザーが入力したコマンドライン文字列から来ており、それらの間に少なくとも1文字(スペースなど)がある可能性があるため、元の文字列を変更する方がはるかに優れています。配置するか、複製を作成してから複製を変更し、各引数の後にnullターミネータを追加args[i]し、文字列の右側のオフセットを指すように設定します。

代わりに、すべてのステップで多くの動的割り当て(malloc)を実行できますが、その場合は、考えられるすべての障害点を処理するコードを作成する必要があります。:-)

于 2011-02-05T22:17:55.620 に答える