The last line in the string array (parsed from strtok) has garbage

I'm a little confused. Basically:

int main() {
    char **symbols = (char **) malloc(3 * sizeof(char *)); // allocate 3 (char *)'s
    for (int i = 0; i < 3; i++)
        symbols[i] = (char *)malloc(3); // allocate string of length 3

}

      

Then the user enters three string characters, delimited by a space, on one line:

111 010 101

      

Then I parse this buffered string into an array of strings like this:

void parseSymbols(char *line, int k, char **symbols) {
    // k == 3
    // Ignore leading spaces
    while (*line != '\0' && is_whitespace(*line))
            line++;

    char *p = strtok(line, " ");
    int cnt = 0;
    symbols[cnt++] = p;
    while (p) {
            p = strtok(NULL, " \n");
            symbols[cnt++] = p;
    }

    // Let call this FOOBAR
    //for (int i = 0; i < k; i++)
    //        printf("%d. %s\n", i, symbols[i]);

      

}

Basically when I print 3 lines in characters I get this:

0. '111'
1. '010'
2. ' s'

      

But when I don't comment out the last two lines of parseSymbols, I get:

0. '111'
1. '010'
2. '101'

      

Why does the FOOBAR block "patch" my array of strings, and more importantly, how can I get parseSymbols to work properly without printing something to the screen? Are the characters [2] with "\ 0" needed? (But doesn't strtok do it for me?)

+3


source to share


1 answer


Your first problem is that you are causing a memory leak by assigning the resulting pointer to strtok

the symbol table. This is because you are simply copying the reference to the next start of the token, rather than copying the resulting string along these lines:symbols[cnt++] = p;

Then you have to make sure you don't exceed k when evaluating the results in the symbol table. Your code always writes NULL at the last position of your symbol table. Once you have parsed 3 characters, you will be writing to unallocated memory causing undefined behavior.

I would recommend fixing these things first and then trying again.



Note that strtok modifies your original buffer by replacing the delimiter with "\ 0" at the end of the token, so there is no need to copy the string. Also note that strtok skips the sequential occurrence of one of the delimiters. So your first loop can be replaced by checking if the length of the first token is> 0 (or, in other words, the first byte of the resulting string!= '\0'

Note that C-Strings always need 1 byte more space than you want to store. This extra byte is used for '\ 0' Termination. In your example, you are parsing chunks of 3 bytes, allocating only 3 bytes per chunk (where there should be 4):symbols[i] = (char *)malloc(3); // allocate string of length 3

+1


source







All Articles