Как написать подпрограмму для чтения из двоичного файла и записи в текстовом файле? - PullRequest
2 голосов
/ 13 марта 2019
#include<stdio.h>

typedef struct {
  char floare[40];
  char culoare[30];
  float pret;
  int codf;
}FLOARE;


void creare_fisier(char*nume) {
  FILE*g;
  FLOARE f;
  fopen_s(&g, nume, "wb");
  if (!g)
    printf("Eroare");
  else
  {
    printf("Cod floare:"); scanf_s("%d", &f.codf);
    while (!feof(stdin)) {
        getchar();
        printf("Nume floare:"); gets(f.floare);
        printf("Culoare floare:"); gets(f.culoare);
        printf("Pret:"); scanf_s("%f", &f.pret);
        fwrite(&f, sizeof(FLOARE), 1, g);
        printf("Cod floare:"); scanf_s("%d", &f.codf);
    }
    fclose(g);
  }
}

void afisare_fisier(char*nume) {
  FILE*h;
  FLOARE f;
  fopen_s(&h, "lista.dat", "rb");
  if (!h)
    printf("Eroare");
  else {
    FILE*g;
    fopen_s(&g, nume, "w");
    fread(&f, sizeof(FLOARE), 1, g);
    while (!feof(h)) {
        fprintf(g, "%d %s %s %f", f.codf, f.floare, f.culoare, f.pret);
        fread(&f, sizeof(FLOARE), 1, g);
    }
    fclose(g), fclose(h);
  }
}

void main() {
  char numef[] = "lista.dat";
  creare_fisier(numef);
  char numetxt[] = "raport.txt";
  afisare_fisier(numetxt);
}

Подпрограмма, которая создает двоичный файл, работает, но листинг информации в текстовый файл не работает. Когда я запускаю код, ничего не происходит, и пространство, занимаемое текстовым файлом, растет, когда я держу консоль открытой. У меня нет опыта работы с подпрограммами, но я знаю структуру листинга в текстовый файл.

Это для домашнего задания.

1 Ответ

2 голосов
/ 13 марта 2019

Когда я запускаю код, ничего не происходит, и пространство, занимаемое текстовым файлом, увеличивается, когда я держу консоль открытой.

Это потому, что вы используете feof и вы смешиваете получает и scanf

Обратите внимание, что вы также (пытаетесь) читать в г , а не в ч in afisare_fisier

Вот предложение:

Я всегда использую fgets для чтения stdin , сначала потому, что это позволяет указатьмаксимальный размер для чтения, пока получает может переполнить полученный буфер, и не нужно делать getchar () или эквивалентный в надежде обойти новую строку и т. д.

Новая строка является частью строк чтения, поэтому в полях floare и culoare , вероятно, вам придется удалить их.

В случае floare и culoare являются словами и не содержат пробелов, которые можно заменить fgets (+ sscanf ) на fscanf , чтобы нечасave переводы строк в floare и culoare (не забудьте указать максимальный размер при fscanf строке).

Обратите внимание, что при использованиирезультат fgets для обнаружения EOF (вместо feof ) Мне не нужно ставить его два раза в источнике.

Я все время добавлял проверкуфайл открыт

Я присваиваю имена двух файлов в аргументе afisare_fisier, потому что нет никакой причины, что кто-то знает имя входного файла.

Потому что EOF не легко из стандартного ввода. Я также прекращаю читать, когда невозможно sscanf Cod floare , что позволяет завершить работу на пустой строке (пользователь просто нажал <enter> без цифры)

typedef struct {
  char floare[40];
  char culoare[30];
  float pret;
  int codf;
}FLOARE;


void creare_fisier(char*nume) {
  FILE*g;
  FLOARE f;
  fopen_s(&g, nume, "wb");
  if (!g)
    printf("Eroare");
  else
  {
    char s[32];

    for (;;) {
      printf("Cod floare:");
      if ((fgets(s, sizeof(s), stdin) == NULL) ||
          (sscanf(s, "%d", &f.codf) != 1))
        break;
      printf("Nume floare:"); 
      if (fgets(f.floare, sizeof(f.floare), stdin) == NULL)
        break;
      printf("Culoare floare:"); 
      if (fgets(f.culoare, sizeof(f.culoare), stdin) == NULL)
        break;
      printf("Pret:");
      if ((fgets(s, sizeof(s), stdin) == NULL) ||
          (sscanf(s, "%f", &f.pret) != 1))
        break;
      fwrite(&f, sizeof(f), 1, g);
    }
    fclose(g);
  }
}

void afisare_fisier(char * in, char * out) {
  FILE*h;
  FLOARE f;
  fopen_s(&h, in, "rb");
  if (!h)
    printf("Eroare (in)");
  else {
    FILE*g;
    fopen_s(&g, out, "w");
    if (!g)
      printf("Eroare (out)");
    else {
      while (fread(&f, sizeof(f), 1, h) == 1) { /* read in h, not in g */
        fprintf(g, "%d %s %s %f\n", f.codf, f.floare, f.culoare, f.pret);
      }
      fclose(g);
    }
    fclose(h);
  }
}

int main() {
  char numef[] = "lista.dat";
  creare_fisier(numef);
  char numetxt[] = "raport.txt";
  afisare_fisier(numef, numetxt);
}

Компиляция и выполнение:

pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra f.c
pi@raspberrypi:/tmp $ ./a.out
Cod floare:123
Nume floare:nume1
Culoare floare:culoare1
Pret:12.34
Cod floare:456
Nume floare:nume2
Culoare floare:culoare2
Pret:21.4
Cod floare:
pi@raspberrypi:/tmp $ cat raport.txt
123 nume1
 culoare1
 12.340000
456 nume2
 culoare2
 21.400000

Примечание: я нажимаю <enter>, когда запрашивается третий Треска

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...