Установка строки в пустую строку в C

Я хочу написать программу на C, которая будет принимать входной файл .txt, читать из него и применять функции или отображать текст на стандартном выходе или записывать его в выходной файл. Ради простоты я написал это, чтобы просто отображать слова.

Полный код:

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>

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

int c;

int output = 0;
FILE *infile;

while((c = getopt(argc, argv, "o:")) != -1){
    switch(c){

        case 'o':
            if (output){

                exit(EXIT_FAILURE);
            }
            output = 1;

            break;
        case '?':
            exit(EXIT_FAILURE);
        default:
            exit(EXIT_FAILURE);
    }
}

    for(; optind< argc; optind++) {
    infile = fopen(argv[optind], "r");


    size_t cpos = 0;
    char str[100];

    int ch;
    while((ch = fgetc(infile)) != EOF ) {
        if (ch == '\n' || ch == ' '){
            fprintf(stderr, "%s\n", str);
            str[0] = '\0';
            continue;
        } else{
            str[cpos++] = ch;
        }

    } 

    str[cpos] = 0;
    fprintf(stderr, "%s\n", str);

    fclose(infile);

    }
    exit(EXIT_SUCCESS);
    }

Моя проблема является частью инструкции while:

    for(; optind< argc; optind++) {
    infile = fopen(argv[optind], "r");

    size_t cpos = 0;
    char str[100];

    int ch;
    while((ch = fgetc(infile)) != EOF ) {
        if (ch == '\n' || ch == ' '){
            fprintf(stderr, "%s\n", str);
            str[0] = '\0';
            continue;
        } else{
            str[cpos++] = ch;
        }
    } 

    str[cpos] = 0;
    fprintf(stderr, "%s\n", str);

    fclose(infile);

    }

В infile = fopen(argv[optind], "r") я сохраняю имя файла из argv. В заявлении while я читаю символы от infile с fgetc до EOF. Я хочу читать каждый символ, пока не нажму пустую строку или пробел. Когда я нажимаю '\n' или ' ', я хочу отобразить это на stderr, сбросить эту строку, чтобы она была пустой, и продолжить чтение символов в следующей строке. В противном случае ch будет помещен на str[cpos] (cpos увеличивается в каждом цикле). В конце str[cpos] устанавливается на 0, чтобы отметить конец строки, последний str печатается и файл закрывается.

Проблема:

если я введу файл .txt (./program -o out.txt input.txt)

word1
word2
word3

Все, что я получаю, это

word1

Я попытался установить str[0]= '\0' как пустую строку, но после этого в str ничего не сохраняется. Как вывести все 3 слова?

Перед публикацией удалите несколько пустых строк.

klutt 08.04.2019 20:24

Проблема не в сбросе строки. Вам нужно выполнить базовую отладку. Поместите распечатки переменных внутри циклов, чтобы исследовать, что происходит.

klutt 08.04.2019 20:27

у вас есть потенциальный UB, распечатывающий неинициализированный str, если первый символ в файле '\n' или ' '. Кроме того, это утверждение continue; бесполезно.

yano 08.04.2019 20:35
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
78
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы не заканчивали нулем построенную вами строку и не сбрасывали cpos = 0; для следующего слова.

В результате вы продолжаете писать в str[] дальше, за пределы '\0', которым вы его завершили.

Цикл должен быть таким:

while((ch = fgetc(infile)) != EOF ) {
    if (ch == '\n' || ch == ' '){
        str[cpos] = '\0';               // terminate this string
        fprintf(stderr, "%s\n", str);
        cpos = 0;                       // for next word
    } else{
        str[cpos++] = ch;
    }
} 

Я вижу несколько потенциальных проблем:

  1. Вы должны сбросить cpos на ноль, когда встретите пробел.
  2. Перед вызовом fprintf в цикле вы должны обязательно обнулить текущую строку str.
  3. Если последним символом перед EOF является \n или , в конце будет выведена пустая строка.
  4. Я не знаю ваш набор данных, но я все равно буду помнить о превышении 99 символов ввода, так как вы можете переполнить буфер при первом столкновении со словом из 100 или более символов.

Когда вы знаете, что в вашем массиве str есть все символы из слова, вы должны добавить к массиву терминатор (нулевой байт) и сбросить cpos до 0, прежде чем собирать символы для нового слова.

Итак, представьте, что str это {'w', 'o', 'r', 'd'} и cpos 4 вы делаете str[cpos] = 0 а затем str {'w', 'o', 'r', 'd', 0} и это правильная строка с нулевым завершением

Пустая строка {0}, это правильно

В любом случае не забудьте сбросить cpos на 0, потому что иначе вы будете писать после терминатора.

Другие вопросы по теме