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

The subprogram which creates the binary file is working, but the listing of the information into a text file is not working. When I run the code it's not happening anything and the space occupied by the text file is growing as I keep open the console. I don't really have experience with the subprograms, but I know the structure of listing into a text file.

This is for a homework task.

halfer
  • 19,824
  • 17
  • 99
  • 186
Andreea Elena
  • 135
  • 1
  • 8
  • 1
    You will want to look at [**Why is while ( !feof (file) ) always wrong?**](https://stackoverflow.com/questions/5431941/why-is-while-feoffile-always-wrong) and [Why gets() is so dangerous it should never be used!](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-dangerous-why-should-it-not-be-used) – David C. Rankin Mar 13 '19 at 19:36
  • The professor from my course always use !feof(file) and the code works always perfectly , also the gets(). I don't think that this is the problem. – Andreea Elena Mar 13 '19 at 19:46
  • Well prof and you have not looked carefully enough: the last data is likely to be repeated if you don't check (and act on) the return value from `fread`. But in this case you do check `feof` before acting on the read. – Weather Vane Mar 13 '19 at 19:51
  • @AndreeaElena even I redirect stdin (e.g. `./a.out < file`) feof() is never true in creare_fisier() ... but of course gets does nothing, and raport.txt is just explosing my disk never finishing to grow – bruno Mar 13 '19 at 20:03
  • 1
    @AndreeaElena Many professors are not real programmers, and they pass on many common errors like this, and we have to fix students like you. – Barmar Mar 13 '19 at 20:05
  • So instead to ease my work, the professor makes it more difficult :)) yey . That's why I'm really struggling in doing these homeworks :(( – Andreea Elena Mar 13 '19 at 20:10
  • @AndreeaElena: maybe, but don't get into the habit of blaming your educator exclusively. CS courses still need hard work on the part of students (i.e. students should not seek for others to do their work for them). – halfer Mar 13 '19 at 20:33
  • 1
    Uh, I now see you used `feof` twice. The usage in `creare_fisier()` is incorrect, but the usage in `afisare_fisier()` is like it was intended to be used. Still, you should check the returned status value of the input functions. – Weather Vane Mar 13 '19 at 20:36
  • 1
    @halfer , thank you for your advices – Andreea Elena Mar 13 '19 at 20:46
  • @AndreeaElena I added more remarks in my answer since you accepted it, they can interest you, reread my answer – bruno Mar 13 '19 at 21:07
  • the function: `gets()` has been depreciated for years and completely removed from the more recent versions of the C language. I.E. Your compiler should have told you this. Suggest using `fgets()` instead ( read the MAN page for `fgets()` as the parameters are different than those for `gets()` – user3629249 Mar 14 '19 at 00:53
  • The function: `main()` only has two valid signatures: `int main( void )` and `int main( int argc, char *argv[] )` Notice that they all have a return type of `int`. Not `void` – user3629249 Mar 14 '19 at 00:56
  • OT: regarding: `printf("Eroare");` 1) Error messages should be output to `stderr`, not `stdout` 2) when the error is from a C library function should also output (to stderr) the text reason the system thinks the error occurred. Suggest calling `perror()` as that performs both outputs to `stderr` – user3629249 Mar 14 '19 at 00:59
  • OT: regarding: `fopen_s(&g, nume, "w");` ALWAYS check (!=NULL) the returned value to assure the operation was successful – user3629249 Mar 14 '19 at 01:00
  • regarding: `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);` Much much better to use the returned value from `fread()` to control the loop, similar to: ` while( fread(&f, sizeof(FLOARE), 1, g) == 1) { fprintf(g, "%d %s %s %f", f.codf, f.floare, f.culoare, f.pret); }` and since this is outputting a text file, suggest appending a '\n' to the end of the format string I.E. "%d %s %s %f\n" – user3629249 Mar 14 '19 at 01:04
  • OT: for ease of readability and understanding: 1) follow the axiom: *only one statement per line and (at most) one variable declaration per statement.* 2) please consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces – user3629249 Mar 14 '19 at 01:07
  • OT: the function: `scanf_s()` returns the number of input format specifiers successfully read. Code should ALWAYS check that returned value to assure the operation was successful – user3629249 Mar 14 '19 at 01:12
  • OT: regarding: `typedef struct { char floare[40]; char culoare[30]; float pret; int codf; }FLOARE;` 1) should always include a 'tag' name because that is what most debuggers use to enable displaying the contents of the individual fields. 2) for flexability (and other reasons) should separate the definition of the struct from a typedef for that struct – user3629249 Mar 14 '19 at 01:15

1 Answers1

2

When I run the code it's not happening anything and the space occupied by the text file is growing as I keep open the console.

This is because you use feof and you mix gets and scanf

Note you also (try to) read in g rather than in h in afisare_fisier

Here a proposal :

I always use fgets to read on stdin, first because that allows to indicate the max size to read while gets can overflow the received buffer, and to not have to do a getchar() or equivalent in the hope to bypass a newline etc.

The newline are part of the read strings so in fields floare and culoare, probably you have to remove them.

In case floare and culoare are words and do not contain space(s) you can replace the fgets (+ sscanf) by fscanf to not have the newlines in floare and culoare (do not forget to indicate the max size when you fscanf a string).

Note that using the result of fgets to detect EOF (rather than feof) I do not have to put it two times in the source.

I added the check all time a file is open

I give the name of the two files in argument to afisare_fisier because there is no reason that one knows the name of the input file.

Because EOF is not easy from stdin I also stop to read when it is not possible to sscanf the Cod floare, that allows to terminate on an empty line (the user just hit <enter> without digit before)

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

Compilation and execution :

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

Note : I hit <enter> when the third Cod floare was requested

bruno
  • 32,421
  • 7
  • 25
  • 37