Я хочу написать программу на 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 слова?
Проблема не в сбросе строки. Вам нужно выполнить базовую отладку. Поместите распечатки переменных внутри циклов, чтобы исследовать, что происходит.
у вас есть потенциальный UB, распечатывающий неинициализированный str
, если первый символ в файле '\n'
или ' '
. Кроме того, это утверждение continue;
бесполезно.
Вы не заканчивали нулем построенную вами строку и не сбрасывали 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;
}
}
Я вижу несколько потенциальных проблем:
cpos
на ноль, когда встретите пробел.\n
или
, в конце будет выведена пустая строка.Когда вы знаете, что в вашем массиве str есть все символы из слова, вы должны добавить к массиву терминатор (нулевой байт) и сбросить cpos до 0, прежде чем собирать символы для нового слова.
Итак, представьте, что str это {'w', 'o', 'r', 'd'} и cpos 4 вы делаете str[cpos] = 0 а затем str {'w', 'o', 'r', 'd', 0} и это правильная строка с нулевым завершением
Пустая строка {0}, это правильно
В любом случае не забудьте сбросить cpos на 0, потому что иначе вы будете писать после терминатора.
Перед публикацией удалите несколько пустых строк.