0

前回の質問以来、多くの作業を行ってきたので、白紙の状態にするために新しい質問を開始するのが適切であると考えました。これが間違った方法である場合は、お知らせください。(私は新しいです!)

これが私のコードです:

int do_command(char **args){

    // In the end, this function should take an array of args
    // and separate them into UNIX commands that lie before and after
    // pipes that are entered and put them into an array called
    // arrayOfCommands.
    // For example, if the char array args comes in 
    // with {"ls", "-1", "|", "wc"}, there would be two commands
    // which would be "ls -l" and "wc"

    // The following number is in my real program, 
    // but using the contents of args above, there will be two
    // commands ("ls -l" and "wc" separated by a pipe)
    // The number is found dynamically by looking for the number
    // of pipes earlier (in our examples so far, just one) and 
    // simply adding one since there has to be a command on either
    // side of the pipe or an error is thrown.
    const int commands = 2;

    // I want to create an array that is 2 wide (int commands)
    // and 5 tall (just a constant number because I don't know
    // how many flags a user will enter after each UNIX command
    //
    //  0 1 
    // 0[][]
    // 1[][]
    // 2[][]
    // 3[][]
    // 4[][]
    //
    // Each column holds a UNIX command (Ex: "ls -s")
    // In this example, "ls" would be stored in arrayOfCommands[0][0];
    // And "-l" would be stored in arrayOfCommands[0][1];
    //
    // If there are more than one command (Ex: "ls -s | wc")
    // They would be stored like this:
    // "ls" in arrayOfCommands[0][0];
    // "-l" in arrayOfCommands[0][1];
    // "wc" in arrayOfCommands[1][0];

    char arrayOfCommands[commands][5]; //!!! (Declaration)

    //counts which column in arrayOfCommands we are on
    int commandNum = 0;

    //Counts which part of a command we are on
    int count = 0;

    //Array Counters
    int i = 0;
    int j;

    //Go through args until we reach the end
    while (args[i] != NULL){
        //if we find something that's not a pipe...
        if(strcmp(args[i], "|")){
            //put it into the array of commands
            arrayOfCommands[commandNum][count] = args[i]; \\!!! (Copying)
            count++;
        }
        //otherwise if we find a pipe...
        else if (!strcmp(args[i], "|")) {
            //we know we are done with that command
            count = 0;
            commandNum++;
        }
        //Looking at the next value in args
        i++;
    }

    //Print the new arrayOfCommands
    int col=0;
    int row=0;
    for (col=0;col<commands;col++){
        printf("Command #%d: ",col);
        for (row=0;row<10;row++){
            printf("%c ",arrayOfCommands[col][row]); \\!!! (Printing)
        }
        printf("\n");
    }
}

誰もが私のコードを理解できるように、コードに狂ったようにコメントしました。さらに説明すると、C で UNIX シェルを作成しています。私のプログラムは UNIX コマンドをユーザー入力の形式で受け取り、スペースで区切って「args」という配列に入れます。

上記のコードは特にパイプを使用しており、パイプ ("|") の前後にあるコマンドにコードをさらに分離しようとしています。先に進んで質問してください。私の思考過程を説明できるように最善を尽くします。

コーディング部分はある程度正しいと思いますが、arrayOfCommands を出力しようとすると、次のようになります。

コマンド 0: % # ! #$
コマンド 1: * ^@ @!
(もちろん、これらは実際の記号です)

「//!!!」を入れました。問題を引き起こしていると思われる行の背後にあります。

4

2 に答える 2

2

あなたが見れば:

char arrayOfCommands[commands][5]; //!!! (Declaration)
...
arrayOfCommands[commandNum][count] = args[i]; \\!!! (Copying) 

を に代入しchar*ていcharます。

C 文字列は文字配列です。つまりchar、文字で終了する一連の sへのポインターがあることを意味しますNULargs[i]返されるのは、その開始文字のメモリ アドレスです。したがって、「コピー」は、 characterとして指定された配列内の要素にunsigned int メモリアドレスを割り当てるだけです。それ(32 ビット) を文字 (8 ビット) に切り捨てます。これがおそらく、奇妙な値が表示される理由です。unsigned int

指示どおりにコマンドを保存する場合は、2 次元配列arrayOfCommandsから 2 次元配列に変更する必要があります。さらに、配列内の各文字列へのポインターエイリアスを作成するだけでなく、実際に文字列をコピーしたい場合は、次を使用して2次元配列の各要素を割り当てます(そして、完了したらメモリを解放します、) を使用するか、固定の最大サイズを選択してスタックに割り当てます。次のようなプログラムでは、簡単にするためにおそらく後者を実行します。charchar *args[]malloc()free()

char arrayOfCommands[2][5][256];  // 5 rows, 2 columns, maximum command length of 255 characters + NUL character

次に、コピーを行うときは、文字列コピー関数を使用する必要があります。

strcpy(arrayOfCommands[row][column], args[i]); // Copy string at args[i] into arrayOfCommands[row][column]

これにより、発生している問題が修正されるはずです。

于 2012-09-26T19:25:12.320 に答える
0

理解した。私は 2D ではなく 1D アレイ ルートを使用することにしました。このコードは、以前は "ls" "-l" "|" として分割されていた引数を取るようになりました。"wc" に分割し、"arrayOfCommands" という新しい配列へのパイプがあるかどうかに基づいてそれらを分離します。これが完了すると、arrayOfCommands の内容は「ls -l」と「wc」になります。コードは次のとおりです。

int do_command(char **args,) {
const int commands = 2;
int i = 0;

int commandNum = 0;
int firstCommand = 1;

char *arrayOfCommands[commands];

//Go through args until we reach the end
while (args[i] != NULL){
    //First case            
    if(firstCommand){
        arrayOfCommands[commandNum] = args[i];
        firstCommand = 0;
    }
    //Rest of the cases
    else{
        //if we find something that's not a pipe...
        if(strcmp(args[i], "|")){
            //Add a space to what was a previous part of the same command
            arrayOfCommands[commandNum] = strcat(arrayOfCommands[commandNum]," ");
            arrayOfCommands[commandNum] = strcat(arrayOfCommands[commandNum],args[i]);
        }
        //But if we do find a pipe...
        else if (!strcmp(args[i], "|")) {
            //We know it's time for a new command
            commandNum++;
            firstCommand = 1;
        }               
    }
    //Looking at the next value in args
    i++;
}

for(i = 0; i < commands; i++)
    printf("Command #[%d]: %s\n", i, arrayOfCommands[i]);
}
于 2012-09-27T05:27:02.113 に答える