WedX - журнал о программировании и компьютерных науках

При чтении из файла и использовании цикла strtok while печатает только первое слово каждой строки

Я программист Java, проверяющий свою удачу в C. Я пытаюсь прочитать файл построчно, а затем подсчитать каждое отдельное слово. До сих пор мне не удавалось разделить каждую строку на слова. Я могу видеть каждую строку и правильно перебирать файл, но мой вывод - это только первое слово каждой строки. Что я здесь делаю неправильно?

char printword[1024]= "";

void print() {
    printf("%s", printword);    
}
main()
{
    FILE* f;
    errno_t err;
    err = fopen_s(&f, FILE_NAME, "r");
    if (&f == NULL) {
    exit(EXIT_FAILURE);
    }
    char line[1024];
    while (fgets(line, 1024, f) != NULL) {
        char * word;
        char *context = " ";
        word = strtok(line, " ");
        while (word != NULL) {
        strcpy(printword, strcat(word," "));
        print();
        word = strtok(NULL, " ");
        }
        printf("\n", NULL);
    }
    //}
    fclose(f);
    printf("Press any key to continue");
    getchar();
    exit(0);
}
10.05.2017

  • Я думаю, что вызов strcat() внутри вашего самого внутреннего цикла может повредить операции. К strtok() нужно подходить осторожно, так как он изменяет строку, которую вы токенизируете, во время каждого последующего вызова. Бьюсь об заклад, он не ожидает, что исходный буфер (слово) будет изменен между вызовами. 10.05.2017
  • Что вы намерены с вызовом функции strcat? 10.05.2017
  • Если вы просто хотите напечатать слово с пробелом после него, забудьте обо всем этом копировании и объединении. Строки C не похожи на строки в других языках; с ними несколько сложно работать. Если вам нужен пробел, поместите его в строку формата printf. Замените свою функцию print, и все внутри цикла запустит строку strtok с помощью printf("%s ", word);. 10.05.2017

Ответы:


1

@BlueStrat, похоже, указал на проблему своим комментарием.

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

one two three

fgets() прочитает это в ваш массив line:

       0         1
offset 0123456789012 3
line   one two three\0

Первый вызов strtok() возвращает указатель на символ со смещением 0, устанавливает символ со смещением 3 в терминатор и устанавливает свою внутреннюю переменную состояния так, чтобы она указывала на символ со смещением 4:

       0         1
offset 012 3456789012 3
line   one\0two three\0
       ^    ^
       |    |
       |    +-- (next)
       +------- word 

Затем вы strcat добавляете дополнительный символ в конец word, получая:

       0         1
offset 0123 456789012 3
line   one \0wo three\0
       ^    ^
       |    |
       |    +-- (next)
       +------- word 

Теперь изучите это на мгновение. Вы не только испортили данные, следующие за первым токеном, вы сделали это таким образом, что внутренний указатель состояния указывает на признак конца строки. Когда вы в следующий раз вызовете strtok(), эта функция увидит, что она находится в конце строки (строки), и вернет NULL, чтобы сообщить, что маркеров больше нет.

Вместо того, чтобы манипулировать токеном, что опасно, объедините его содержимое с буфером printword, а затем объедините дополнительное пространство с этим.

10.05.2017

2

Я думаю, что BlueStrat прав. Попробуйте сначала скопировать слово в печатное слово, а затем кошку " " в печатное слово

strcpy(printword, word);
strcat(printword, " ");
10.05.2017
Новые материалы

Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

Объяснение документов 02: BERT
BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

Как проанализировать работу вашего классификатора?
Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

Работа с цепями Маркова, часть 4 (Машинное обучение)
Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..


Для любых предложений по сайту: [email protected]