结构数组只采用 C 中的最后一个值

Array of structs only takes last value in C

我正在尝试制作一个简单的命令行界面,但我遇到了解析命令的问题:

process_t 是一个结构,包含要存储在变量 argv 中的参数的命令路径。

int parse_cmd(char* tokens[], process_t* commands) {
    assert(tokens!=NULL);
    assert(commands!=NULL);
    
    int position = 0;
    int commandNumber = 0;
        
    for(int i=0; tokens[i] != NULL; i++){
        if(is_reserved(tokens[i]) == 0 && tokens[i+1] != NULL) continue;
        int end = is_reserved(tokens[i]) == 0 ? i+1 : i;
        int argc = position;
        int count = 0;
        
        process_t newProcess;

        char* argv[MAX_CMD_SIZE] = {NULL};
        for(argc; argc < end; argc++) {
            argv[count] = tokens[argc];
            count = count + 1;
        }
        newProcess.path = tokens[position];
        newProcess.argv = argv;
        position = i + 1;
        commands[commandNumber] = newProcess;
        commandNumber = commandNumber + 1;
    }
}

int main(int argc, char* argv[]) {

    char path[MAX_LINE_SIZE];
    char line[MAX_LINE_SIZE];
    char* cmdline[MAX_CMD_SIZE];
    process_t cmds[MAX_CMD_SIZE];

    getcwd(path, MAX_LINE_SIZE);
    while (1) {
  
        printf("mini@shell:%s$ ", path);
        scanf("%[^\n]%*c", line);
        
        trim(line);
        clean(line);
        tokenize(line, cmdline);
        
        parse_cmd(cmdline, cmds);
        toString(cmds);
        
        break;.
    }
    return -1;
}

输入:ls -l ; grep ^a


为什么数组只包含最后一次迭代的 argv 值?


输出:

路径:ls => argv = {grep, ^a, (null)} 路径:grep => argv = {grep, ^a, (null)}


您正在尝试使用块局部数组 argv,它会为每个命令重新创建,更糟糕的是,在 parse_cmd 返回后甚至不再存在。必须使用具有足够生命周期的数组对象;你可以通过改变

来做到这一点
        char* argv[MAX_CMD_SIZE] = {NULL};

        char **argv = calloc(end-position+1, sizeof *argv);

请注意,您必须在不再需要时 free 此对象。

另请注意,您忘记从 parse_cmdreturn commandNumber;;否则,您无法知道找到了多少命令。

我还找到了一种方法,甚至不需要复制我声明的本地数组,只需更改包含保留字符的索引值即可。

所以令牌将是这样的:{« ls », « -l », NULL, « grep », « ^a », NULL}

int parse_cmd(char* tokens[], process_t* commands) {
    assert(tokens!=NULL);
    assert(commands!=NULL);
    
    int position = 0;
    int commandNumber = 0;
    
    for(int i=0; tokens[i] != NULL; i++){
        if(is_reserved(tokens[i]) == 0 && tokens[i+1] != NULL) continue;
        int end = is_reserved(tokens[i]) == 0 ? i+1 : i;
        
        commands[commandNumber].path = tokens[position];
        commands[commandNumber].argv = &tokens[position];
        commands[commandNumber].next = &commands[commandNumber]+1;
        tokens[end] = NULL;
        commandNumber = commandNumber + 1;
        position = i + 1;
    }
    return 0;
}