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 Shell。我的程序以用户输入的形式接收 UNIX 命令,并将它们放入一个名为“args”的数组中,用空格分隔。

上面的代码专门用于管道,并试图将代码进一步分离为位于管道(“|”)之前和之后的命令。继续提问,我会尽力帮助解释我的思考过程。

我认为我的编码部分有些正确,但是当我尝试打印 arrayOfCommands 时,我得到如下信息:

命令 0:% # !##$
命令 1:* ^@ @!
(当然,这些是实际的符号)

我放了“//!!!” 在我认为导致问题的线后面。

4

2 回答 2

2

如果你看:

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

您正在将 a 分配char*到 achar中。

C 字符串是字符数组。这意味着您有一个指向一系列char以字符结尾的 s的指针NULargs[i]将返回的是该起始字符的内存地址。因此,您的“副本”只是将unsigned int 内存地址分配给指定为字符的数组中的元素。unsigned int它会将那个(32 位)截断为一个“字符”(8 位)。这可能就是您看到奇怪值的原因。

如果要按照指示存储命令,则必须将arrayOfCommands二维char数组更改为二维char *数组。此外,如果您想实际复制字符串,而不仅仅是为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

弄清楚了。我决定采用 1D 阵列路线而不是 2D 方式。代码现在采用 args,之前被拆分为 "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 回答