C: strtok возвращает сначала значение, а затем NULL

Я просто пытаюсь вернуть каждое слово в строке, но strtok возвращает первое слово, а затем сразу же возвращает null:

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

    // Get the interesting file contents
    char *filestr = get_file(argv[1]);

    printf("%s\n", filestr);

    char *word;

    word =  strtok(filestr, ";\"'-?:{[}](), \n");

    while (word != NULL) {
        word = strtok(NULL, ";\"'-?:{[}](), \n");
        printf("This was called.  %s\n", word);
    }

    exit(0);
}

get_file просто открывает указанный путь и возвращает содержимое файла в виде строки. Команда printf("%s\n", filestr);, показанная выше, успешно распечатывает любой файл целиком. Следовательно, я не думаю, что get_file() является проблемой.

Если я вызову strtok для char test[] = "this is a test string" вместо filestr, то он правильно вернет каждое из слов. Однако, если я сделаю содержимое файла, полученного с помощью get_file(), «это строка», тогда он вернет «это», а затем (ноль).

По запросу вот код для get_file():

// Take the path to the file as a string and return a string with all that
//  file's contents
char *get_file (char *dest) {
    // Define variables that will be used
    size_t length;
    FILE* file;
    char* data;
    file = fopen(dest, "rb");

    // Go to end of stream
    fseek(file, 0, SEEK_END);
    // Set the int length to the end seek value of the stream
    length = ftell(file);
    // Go back to the beginning of the stream for when we actually read contents
    rewind(file);

    // Define the size of the char array str
    data = (char*) malloc(sizeof(char) * length + 1);

    // Read the stream into the string str
    fread(data, 1, length, file);

    // Close the stream
    fclose(file);

    return data;
}

person Xander Dunn    schedule 05.02.2012    source источник
comment
Один вопрос: ваш printf() находится после второго strtok(), поэтому вы не видите первое напечатанное слово файла, вы должны видеть второе? Мне кажется, код правильный. Вы уверены, что разместили именно тот код, который не работает?   -  person peterept    schedule 05.02.2012
comment
Спасибо. Ваше использование strtok() выглядит нормально. Одна проблема (возможно, не связанная с этой проблемой) заключается в том, что get_data() не завершает нулем строку, которую он читает. Это просто текстовый файл, который вы ему даете?   -  person FatalError    schedule 05.02.2012
comment
Если вы посмотрите на то, что вы говорите, выше вы сказали, что когда он читает файл, он печатает This и NULL. Для меня это означает, что ваш файл не является простым ASCII. Первый printf печатает This. Первый strtork читает это, а второй (в цикле) затем переходит к следующему, который, если конец строки, и печатает NULL.   -  person peterept    schedule 05.02.2012
comment
@FatalError: Да, я даю простой текстовый файл. Постой, однако. По просьбе peterept я попытался убедиться, что код, который я разместил, был правильным кодом сбоя, поэтому я скопировал его в новый проект C, и он работал, как и ожидалось! Позвольте мне комментировать строки во всей моей программе, которые я считал не связанными, пока не обнаружу, что вуду заставляет ее перестать работать в моей более крупной программе.   -  person Xander Dunn    schedule 05.02.2012
comment
@peterept: Да, я ошибся при копировании кода в StackOverflow. Я знаю, что код, который я разместил, на самом деле не напечатает первое слово. В этом случае он просто напечатает (null). Извиняюсь.   -  person Xander Dunn    schedule 05.02.2012
comment
Я обнаружил, что проблема была в том, что я вызывал другую функцию, get_words(), до того, как попытался получить все слова в файле.   -  person Xander Dunn    schedule 05.02.2012


Ответы (1)


Вы передаете двоичный файл с нулевыми символами?

get_file() правильно возвращает символьный буфер, но (например), если я даю вашей функции файл .png, буфер выглядит так

(gdb) p data[0] @32 $5 = "\211PNG\r\n\032\n\000\000\000\rIHDR\000\000\003\346\000\000\002\230\b\ 006\000\000\000\376?"

Вы можете видеть, что после PNG\r\n в нем есть нулевые символы, поэтому вы не можете рассматривать возвращаемое значение get_file() как строку. Вам нужно будет обращаться с ним как с массивом символов и возвращать общую длину вручную и не полагаться на нулевое завершение.

Затем, как написано в настоящее время, вы не можете полагаться на strtok, поскольку он прекращает обработку после того, как достигает ваших первых нулевых символов. Вы можете обойти это, выполнив проход по вашим данным и преобразовав все нулевые символы во что-то еще, или вы можете реализовать версию strtok, которая работает с буферами заданной длины.

person Bren    schedule 05.02.2012
comment
Спасибо. К сожалению, я сбил нас с пути, думая, что проблема была в коде, который я изначально опубликовал. Я отправил сообщение, указывающее на настоящую проблему, хотя я не вижу, как ее исправить. - person Xander Dunn; 05.02.2012
comment
отредактировал, увидев, как реализована функция get_file(). Хотя, похоже, вы решили свою проблему. :) - person Bren; 05.02.2012