Не удается получить последний токен из буфера файлов

Я написал некоторый код, который читает текстовый файл и загружает каждую строку в буфер. Затем этот буфер обрабатывается с использованием функции strtok() с "," в качестве разделителя. Я получаю первые 3 токена просто отлично, но не могу получить последний токен. Это первый раз, когда я столкнулся с этим. При последнем вызове strtok(), когда я должен получить указатель на последний токен, strtok() возвращает ноль.

Частичный код:

   for(j = 0, token = strtok(buffer, del); token != NULL; token = strtok(NULL, del), j++) {
            printf("j: %d, token: %s\n",j, token);
            switch(j) {
                case 0:
                    index = fnv1aHash(token, (reqdata_len-1));
                    t_indices[i] = index;
                    addNode(&(table[index]));
                    table[index][0].course = (char *) malloc(1 + strlen(token));
                    strcpy(table[index][0].course, token);
                    break;
                case 1:
                    table[index][0].category = (char *) malloc(1 + strlen(token));
                    strcpy(table[index][0].category, token);
                    break;
                case 2:
                    strcpy(prereqbuff, token);
                    addPrereqs(prereqbuff, &(table[index][0].prereqs));
                    break;
                case 3:
                    table[index][0].notes = (char *) malloc(1 + strlen(token));
                    strcpy(table[index][0].notes, token);
                    break;
            }
        }

Оператор switch предназначен только для управления тем, что и куда идет в структуре, которая организует информацию о строках по столбцам (разделенные запятыми). Таким образом, образец строки будет выглядеть так:

Words words,Wordswords,Words,Words\n // (where \n represents a new line)

Я пытался добавить \ n в качестве разделителя, но это не помогло. Я даже не попадаю внутрь "case 3:", так как токен указывает на ноль.

ЗАКЛЮЧИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ

Я понял мою проблему. addPrereqs() вызывает strtok внутри себя, и, конечно, это означает, что в моей основной функции портится мой первоначальный вызов strtok. Я читал, что можно использовать strtok_r() в качестве обходного пути. В конце концов, я вызвал strtok() еще раз перед вызовом addPrereqs () и сразу же использовал этот токен для того, чего изначально хотел. Соответствующий раздел кода ниже:

for(j = 0, token = strtok(buffer, del); token != NULL; token = strtok(NULL, del), j++) {
    switch(j) {
        case 0:
            index = fnv1aHash(token, (reqdata_len-1));
            t_indices[i] = index;
            addNode(&(table[index]));
            table[index][0].course = (char *) malloc(1 + strlen(token));
            strcpy(table[index][0].course, token);
            break;
        case 1:
            table[index][0].category = (char *) malloc(1 + strlen(token));
            strcpy(table[index][0].category, token);
            break;
        case 2:
            strcpy(prereqbuff, token);
            token = strtok(NULL, del);
            table[index][0].notes = (char *) malloc(1 + strlen(token));
            strcpy(table[index][0].notes, token);
            addPrereqs(prereqbuff, &(table[index][0].prereqs));
            break;
    }
}

2 ответа

Это calloc(strlen(token), sizeof(char)); это проблема,

  1. Не использовать calloc() если вы перезапишете нули немедленно.
  2. Что еще более важно, вам нужно еще 1 байт для хранения строки.

    table[index][0].notes = malloc(1 + strlen(token));
    

    в вашем коде, strcpy() пишет окончание '\0' в недопустимом месте, что вызывает неопределенное поведение.

Я сделал минимальный компилируемый пример вашего кода (из опубликованных деталей), и в этом просто нет ничего плохого - как изложено в вопросе. Извлекает все жетоны. Я бы критиковал, однако, то, как он сложен - ужасная смесь for и подразумевается while а также switch,

#include <stdio.h>
#include <string.h>

int main(void) {
    int j;
    char *token;
    char buffer[] = "Words words,Wordswords,Words,Words\n";
    char del[] = ",\n";
    for(j = 0, token = strtok(buffer, del); token != NULL; token = strtok(NULL, del), j++) {
            printf("j: %d, token: %s\n",j, token);
            switch(j) {
                case 0:
                    break;
                case 1:
                    break;
                case 2:
                    break;
                case 3:
                    break;
            }
        }
    return 0;
}

Выход программы:

j: 0, token: Words words
j: 1, token: Wordswords
j: 2, token: Words
j: 3, token: Words
Другие вопросы по тегам