Как скопировать текст из одного файла в другой на C?

#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;
}
  

окно Windows cmd, показывающее запуск программы

Комментарии:

1. filename1 это a char , а не char массив или указатель на первую char выделенную память. Кроме того, вы используете %s для печати char s — fprintf(outfile,"%s",characters) . Это UB.

2. при компиляции всегда включайте предупреждения, а затем исправляйте эти предупреждения. (для gcc минимального использования: -Wall -Wextra -Wconversion -pedantic -std=gnu11 ) Примечание: другие компиляторы используют разные параметры для получения тех же результатов. Примечание: одна переменная типа char filename не может использоваться в качестве целевого объекта для a scanf() , который использует %s для спецификатора преобразования формата ввода. Предложите char filename[30]; или аналогичный

Ответ №1:

В вашей программе есть несколько проблем:

  1. Вы используете char переменные для хранения имен файлов. Эти переменные должны быть char массивами или указателями на первую char часть некоторой выделенной памяти.
  2. fopen("filename2", "w") кажется неправильным. Хотя первым аргументом должен быть a char * , вы не читаете / записываете файлы, которые вы только что попросили пользователя ввести.
  3. fprintf(outfile,"%s",characters) — Вы используете %s для печати символов. Это вызовет UB.
  4. char characters — Последний символ файла, EOF символ гарантированно помещается в int . characters Переменная должна быть объявлена как an int , чтобы она могла содержать 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);
}