0

I wrote a program that collects user data and saves it to a file. At the moment when he wants to view the file, the program loops and shows only the first record. I do not know what this error is caused.

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

FILE *fptr;  

struct notification {
    char name[50];
    char lastname[50];
    char price[10];
    char descreption[100];
}notification;

void insertRecord()
{
    fptr=fopen("G:\\file.txt","a+");

    fflush(stdin);

    printf("Podaj imie: ");
    gets(notification.name);

    printf("Podaj nazwisko: ");
    gets(notification.lastname);

    printf("Podej cene: ");
    gets(notification.price);

    printf("Podaj opis usterki: ");
    gets(notification.descreption);

    strcat(notification.descreption,"\n");


    if(fwrite(&notification,sizeof(notification),1,fptr) != 1)
    {
        perror("Blad: ");
    } else{

        printf("Dane dodane poprawnie\n");

    }
    fclose(fptr);
}

void readDatabase()
{

    struct notification *object2=malloc(sizeof(struct notification));
    fptr=fopen("G:\\file.txt","rb");

    fread(object2,sizeof(struct notification),1,fptr);

    while(!feof(fptr))
    {

        printf("Imie: %s\n", object2->name);
        printf("Nazwisko: %s\n", object2->lastname);
        printf("Cena: %s\n", object2->price);
        printf("Opis: %s\n", object2->descreption);
        printf("==========\n");
    }

    fclose(fptr);
}

int main() {
    int i,option=0,check=0;

    do{
        printf("1) Dodaj rekord do bazy \n");
        printf("2) Odczytaj rekordy z bazy \n");
        printf("0) Zakoncz program \n");

        scanf("%d", &option);

        switch (option)
        {
            case 1:
                insertRecord();
                break;
            case 2:
                readDatabase();
                break;
            default:

                break;
        }    
    }while(check == 0); //petla dziala dopóki zmienna check bedzie równa 0

}

EDIT:

Correct insertRecord function:

void insertRecord()
{
    fptr=fopen("G:\\file.txt","a+");

    fflush(stdin);

    struct notification *obj = malloc(sizeof(struct notification));


    printf("Podaj imie: ");
    gets(obj->name);

    printf("Podaj nazwisko: ");
    gets(obj->lastname);

    printf("Podej cene: ");
    gets(obj->price);

    printf("Podaj opis usterki: ");
    gets(obj->descreption);

    strcat(notification.descreption,"\n");


    if(fwrite(obj,sizeof(struct notification),1,fptr) != 1)
    {
        perror("Blad: ");
    } else{

        printf("Dane dodane poprawnie\n");

    }
    free(obj);
    fclose(fptr);
}

Now ALL display and insert OK, but in file.txt I see Chinese characters, why?

lukassz
  • 3,135
  • 7
  • 32
  • 72

4 Answers4

1

Move this line:

fread(object2,sizeof(struct notification),1,fptr);

inside your while loop.

Buddy
  • 10,874
  • 5
  • 41
  • 58
1

scanf("%d", &option); followed by gets() leads to trouble. The first does not consume the '\n' after the number and the second only reads in the short line '\n'.

Do not use scanf(). Do not use gets(). Use fgets(), then parse the input.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • You write about my `scanf` in my `main` function yes? Why `scanf` to read number it's wrong? – lukassz Jan 28 '16 at 19:09
  • 1
    @lukassz It isn't that using `scanf("%d", &option);` is wrong to read a number. It is that `scanf("%d", &option);` leaves a problem for the _next_ input operation. You can save yourself time by never using `scanf()` for user input. It does not do the job well for many reasons. – chux - Reinstate Monica Jan 28 '16 at 19:16
  • I do not understand, I should to replace `scanf`? – lukassz Jan 28 '16 at 19:27
1

There are a variety of problems in the readDatabase function

  • while(!feof)-is-always-wrong
  • the fread needs to be in the loop.
  • you don't need to malloc the memory, but if you do malloc memory, you should free it when you're done with it
  • you always need to check the return value from fopen, because it can and does fail, e.g. because the file is not found

With all that in mind, the readDatabase function should look like this

void readDatabase( void )
{
    struct notification object2;

    if ( (fptr = fopen("G:\\file.txt","rb")) == NULL )
    {
        printf( "File not found\n" );
        return;
    }

    while ( fread( &object2, sizeof(struct notification), 1, fptr ) == 1 )
    {
        printf("Imie: %s\n", object2.name);
        printf("Nazwisko: %s\n", object2.lastname);
        printf("Cena: %s\n", object2.price);
        printf("Opis: %s\n", object2.descreption);
        printf("==========\n");
    }

    fclose(fptr);
}
Community
  • 1
  • 1
user3386109
  • 34,287
  • 7
  • 49
  • 68
  • Ok, thanks for this. But program read only 1 record propertly and shows 2 record empty. Mayby my write function it's wrong. Can you check this? – lukassz Jan 28 '16 at 19:13
  • Suggest `fread(pointer, sizeof *pointer, ..., ...)` rather than `fread(pointer, sizeof type, ..., ...)` --> `fread(&object2, sizeof object2, ..., ...)` – chux - Reinstate Monica Jan 28 '16 at 19:19
  • I correct function, please check my edited question. – lukassz Jan 28 '16 at 19:25
  • I usually check for (feof(fptr) or ferror(fptr)) as the first line of my while(fread()) loops to catch the rare reads that successfully return something I don't want. Probably not truly needed, but it makes me more comfortable and hasn't hurt performance of any of my stuff enough to notice. – Steve Valliere Jan 28 '16 at 19:52
  • "probably not truly needed" --> "positively absolutely unequivocally not needed". – user3386109 Jan 28 '16 at 20:12
0

scanf() will leave new line character in input stream by default. you can use getchar() function to clear this new line character or you can flush the input buffer like this.

while ((ch = getchar()) != '\n' && ch != EOF);

but don't use fflush(stdin) because if the file stream is for input use, as stdin is, the behaviour is undefined, therefore it is not acceptable to use fflush() for clearing keyboard input. As usual, there are some exceptions, check your compiler's documentation to see if it has a (non-portable) method for flushing input.