Чтение и запись из файла в C - PullRequest
1 голос
/ 07 февраля 2020

Я застрял в каком-то базовом c коде обработки файлов в C. В основном я хочу проанализировать входной файл, чтобы получить некоторую информацию, а затем поместить его в другой файл (более подробная информация находится во входном файле). Я использовал для этого онлайн компилятор g cc, и все было замечательно. Когда я enter code here компилирую код в cmd с помощью команды g cc, выходной файл команды пуст.

#include <stdio.h>
#include <string.h>

int main() {
    char c[1000];
    FILE *fptr,*resultfp;
    if ((fptr = fopen("inputfile.txt", "r")) == NULL) {
        printf("can't be opened");
    }
    if ((resultfp = fopen("outputfile.txt", "w")) == NULL) {
        printf("can't be opened");
    }
    while(strcmp(c,"END OF FILE")){
 fscanf(fptr, "%[^\n]", c);
 fseek(fptr, 1,SEEK_CUR);
 if(strstr(c,"Example name") || strstr(c,"Example description") )
 {
    fscanf(fptr, "%[^\n]", c);
    fprintf(resultfp,"%s\n", c);
 }

    }

    fclose(fptr);
    fclose(resultfp);
    return 0;
}

, и это входной файл:

This is an example
Example name:
example1
Example description:
description1
Example name:
example2
Example description:
description2
I want to parse this file
In order to get example name and example description
END OF FILE

Ответы [ 2 ]

1 голос
/ 07 февраля 2020

В вашей программе много проблем, но она убивает тот факт, что предполагается, что символ новой строки является одним символом, что

fseek(fptr, 1,SEEK_CUR);

будет пропущено.

Но на самом деле это не так в Windows: библиотека stdio переведет \r\n в \n для совместимости, но fseek пропустит только один байт.

Если вы измените это на

fseek(fptr, 2,SEEK_CUR);

, ваша программа будет работать - для ОЧЕНЬ широкого определения «работы».

1 голос
/ 07 февраля 2020

Во-первых, даже если OP-код работал без проблем, во входном файле возникла проблема. Ни один экземпляр второго критерия во входном файле никогда не будет прочитан или размещен в выходном файле. то есть критерии поиска в коде:

"Example description"

Но строка inputfile.txt:

"Example descripton:"//mis-spelled

Далее строки ...

char c[1000];
...
while(strcmp(c,"END OF FILE")){

... приводит к доступу к переменной c до ее инициализации. Это в свою очередь приводит к неопределенному поведению . Исправление простое, всегда инициализируйте переменные перед их первым использованием: `char c [1000] = {0};

Кроме того, эта строка ...

 while(strcmp(c,"END OF FILE")){

будет иметь разные результаты в зависимости от содержимого c. Прочитайте о strcmp здесь .

Наконец, эта строка:

fseek(fptr, 1,SEEK_CUR);

При использовании fseek с текстовыми файлами, одно из следующих должно быть true:

  • смещение должно быть равно нулю.
  • смещение - это значение, возвращаемое предыдущим вызовом ftell, а origin устанавливается в начало файла.

Значение 1 для смещения не соответствует ни одному из этих критериев.

Если вы готовы попробовать более простой метод чтения / анализа с использованием конструкции while(fgets(...)){...} использует более простой синтаксический анализ, чем можно сделать, используя варианты fscanf. Следующие циклы пока не найдет указанный тег, а затем читает следующую строку в файле для значения. Когда fgets видит EOF , он выходит из l oop. (Обратите внимание, что EOF присущ текстовым файлам, исключая необходимость в последней строке в вашем inputfile.txt)

int main() {
    char c[1000] = {0};//always initialize before using
    FILE *fptr,*resultfp;
    if ((fptr = fopen("inputfile.txt", "r")) == NULL) {
        printf("can't be opened");
        return 0;
    }
    if ((resultfp = fopen("outputfile.txt", "w")) == NULL) {
        printf("can't be opened");
        fclose(fptr);
        return 0;
    }
    // all is well so far, continue

    while(fgets(c, sizeof(c), fptr))
    {
         if(strstr(c,"Example name") || 
            strstr(c,"Example description") )
         {
            fgets(c, sizeof(c), fptr);
            fprintf(resultfp,"%s\n", c);
         }
     }

    fclose(fptr);
    fclose(resultfp);
    return 0;
}   

Из-за способа указания входного файла его достаточно и просто проверить каждая полная строка для различных пар тег-значение, в данном случае представленная в отдельных строках, этот метод упрощает разбор и тестирование каждой пары.

...