Search code examples
cstringappendtoken

How to append tokens to a string variable in C?


So I have the following code:

//Get the line

fgets(line, MAX, stdin);

//Remove trailing new line character

line[strcspn(line, "\r\n")] = 0;

//Count number of tokens

int tokenCounter = 1;
for (int i = 0; i < strlen(line); i++){
    if (line[i] == ' '){
        tokenCounter++;
    }
}if (tokenCounter >= 3){
    command = strtok(line, " ");
    id = strtok(NULL, " ");
    name = strtok(NULL, " ");
    if (tokenCounter > 3){
        for (char *p = strtok(NULL," "); p != NULL; p = strtok(NULL, " ")){
            strcat(name, p);
        }
    }
    printf("Command: %s -- ID: %s -- Name: %s\n", command, id, name);
}

What the code is supposed to do is it is supposed to save the first word in the line in the "command" variable, the second word in the line in the "id" variable and the rest of the words in a single variable called "name". But currently its not working properly. It works as described below:

Input  >  word1 word2 word3
Output >  Command: word1 -- ID: word2 -- Name: word3

Input  >  word1 word2 word3 word4
Output >  Illegal Instruction: 4

The correct outputs are supposed to be as follows :

Input  >  word1 word2 word3
Output >  Command: word1 -- ID: word2 -- Name: word3

Input  >  word1 word2 word3 word4
Output >  Command: word1 -- ID: word2 -- Name: word3 word 4

Am I doing something wrong in the loop? if yes, what could be changed?


Solution

  • There's lots that could be wrong with your incomplete code, but one clear problem is the loop:

    for (int i = 3; i <= tokenCounter; i++){
        name = strtok(NULL, " ");
        if (tokenCounter > 3)
            strcat(name, strtok(NULL, " "));
    }
    

    The first time through the loop, this will assign name to be pointer to the scanning buffer, which will not work if name is char name[MAX]; (which it needs to be for any of your code to have any hope of working), so you should be seeing a compile error. Then, strtok returns NULL when it gets to the end of the input, which will likely cause an immediate crash when you pass it to strcat. What you need is something more like

        name = strcpy(strtok(NULL, " "));
        while (char *tmp = strtok(NULL, " ")) {
            strcat(name, " ");
            strcat(name, tmp);;
        }
    

    Not that this is all that good, as it does not check for buffer overflows, and is just splitting an reassembling tokens, so why bother? Just use strtok(NULL, "\n"); to get the whole rest of the line as a single "token".


    If you've erroneously declared char *name;, that probably explains your crash. When you do

    name = strtok(NULL, " ");
    if (tokenCounter > 3){
        for (char *p = strtok(NULL," "); p != NULL; p = strtok(NULL, " ")){
            strcat(name, p);
    

    The first line makes name point at the strtok buffer, and then in the loop you attempt to append part of the buffer to itself, which causes undefined behavior.