#c #io
#c #io
Вопрос:
Я пишу базовую программу для копирования текста в другой текстовый файл. Но в окне консоли после ввода имени файла, откуда должен быть взят текст, программа завершается и не идет дальше. Как я могу решить эту проблему?
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char filename1, filename2;
FILE *infile;
FILE *outfile;
printf("Enter a data file name:");
scanf("%s", filename1);
infile = fopen("filename1", "r");
printf("Enter a input file name:");
scanf("%s", filename2);
outfile = fopen("filename2", "w");
if (infile == NULL || outfile == NULL) {
printf("Problem in opening files");
exit(0);
}
printf("files opened successfully");
char characters;
do {
characters = getc(infile);
fprintf(outfile,"%s", characters);
printf("%s", characters);
} while (!feof(infile));
fclose(infile);
fclose(outfile);
return 0;
}
Комментарии:
1.
filename1
это achar
, а неchar
массив или указатель на первуюchar
выделенную память. Кроме того, вы используете%s
для печатиchar
s —fprintf(outfile,"%s",characters)
. Это UB.2. при компиляции всегда включайте предупреждения, а затем исправляйте эти предупреждения. (для
gcc
минимального использования:-Wall -Wextra -Wconversion -pedantic -std=gnu11
) Примечание: другие компиляторы используют разные параметры для получения тех же результатов. Примечание: одна переменная типа charfilename
не может использоваться в качестве целевого объекта для ascanf()
, который использует%s
для спецификатора преобразования формата ввода. Предложитеchar filename[30];
или аналогичный
Ответ №1:
В вашей программе есть несколько проблем:
- Вы используете
char
переменные для хранения имен файлов. Эти переменные должны бытьchar
массивами или указателями на первуюchar
часть некоторой выделенной памяти. fopen("filename2", "w")
кажется неправильным. Хотя первым аргументом должен быть achar *
, вы не читаете / записываете файлы, которые вы только что попросили пользователя ввести.fprintf(outfile,"%s",characters)
— Вы используете%s
для печати символов. Это вызовет UB.char characters
— Последний символ файла,EOF
символ гарантированно помещается вint
.characters
Переменная должна быть объявлена как anint
, чтобы она могла содержатьEOF
символ.
Вот программа, которая работает:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char filename1[10], filename2[10];
FILE *infile;
FILE *outfile;
printf("Enter a data file name:");
scanf("%s",filename1);
infile = fopen(filename1, "r");
printf("Enter a input file name:");
scanf("%s",filename2);
outfile = fopen(filename2, "w");
if (infile==NULL || outfile==NULL) {
printf("Problem in opening files");
exit(0);
}
printf("files opened successfully");
int characters;
/*do {
characters=getc(infile);
fprintf(outfile,"%s",characters);
printf("%s",characters);
} while(!feof(infile));
*/
while ((characters = getc(infile)) != EOF) {
fprintf(outfile, "%c", characters);
printf("%c", characters);
}
fclose(infile);
fclose(outfile);
return 0;
}
Комментарии:
1. Рассмотрите возможность использования
if (scanf("%9s", filename1) != 1) return 1;
для предотвращения неопределенного поведения при недопустимом вводе,putc(characters, outfile)
аputchar(characters)
также для симметрииgetc()
и эффективности.2. @chqrlie Спасибо, что указали на это. Я просто буду ленив в этом и позволю OP включить ваши предложения в свою программу.
Ответ №2:
Существует ряд проблем.
char filename1, filename2;
Это позволяет только filename1
и filename2
хранить один символ, а не строку C. Вам нужно зарезервировать память в виде массива символов. Нравится:
char filename1[64], filename2[64]; // Allow 63 chars for file name
Затем
scanf("%s",filename1);
действительно плохо, поскольку позволяет пользователю переполнять ваши входные буферы. Рассмотрите возможность использования fgets
или, по крайней мере, сделайте:
scanf("cs",filename1); // Limit user input to 63 chars as the buffer is 64
// The "last" char is for the string termination
Затем цикл:
Во-первых, characters
должно быть int
так, чтобы вы могли проверить EOF
. Далее, проверьте непосредственно getc
вместо использования feof
. И не используйте %s
для печати одного символа в выходной файл — используйте %c
. Нравится
int characters;
while(1) {
characters=getc(infile);
if (characters == EOF) break; // Break (aka jump out of the loop) on
// end-of-file or errors
fprintf(outfile,"%c",characters); // %c instead of %s
// or use: putc(characters, outfile)
// instead of fprintf
printf("%s",characters);
}