Home > Back-end >  Array of structs only takes last value in C
Array of structs only takes last value in C

Time:11-06

I'm trying to make a simple command line interface, but i'm having a probleme for parsing commands :

process_t is a structure contient the path of the command with arguments to be stored in the variable 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;
}

Input: ls -l ; grep ^a


Why the array contain only the value of argv of the last iteration ?


Output :

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


CodePudding user response:

You're trying to use the block-local array argv, which is recreated for every command and, what's worse, doesn't even exist any longer after parse_cmd has returned. An array object with sufficient lifetime has to be used; you can do this by changing

        char* argv[MAX_CMD_SIZE] = {NULL};

to

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

Note that you'd have to free this object when no longer needed.

Also note that you forgot to return commandNumber; from parse_cmd; without that, you have no way of knowing how many commands were found.

CodePudding user response:

I found also a way without even need to copy the local array that i declared, just by changing the value of the index that contain the reserved character.

So the tokens will be like this : {« 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;
}
  • Related