0

I wrote a program that operates like an ATM.It receives cards(by getting card numbers),define them into database and does withdrawal,deposit,etc. My program has a defineAccount(FILE* f) that receives card number,owner name,etc. and writes these information in file Database.txt.Alse I have a function showCardInformation(FILE* f,int cardNumber) that shows a information of a card that is defined in file. When I run the program at first time and save a card information in the file showCardInformation works correctly but when I run it again I receive run-time error with this function because card owner name in the file has changed to NULL.I have the same problem by another part in my program when card number in the file changes.Why I got this problem? My code:

typedef enum myBoolean {freezed,notFreezed} Boolean;
typedef struct database
    {
        int cardNumber;
        int password;
        char* ownerName;
        int accounts;
        Boolean accessStatus;
    } Database;

void showCardInformation(FILE* f,int cardNumber)
    {
        system("cls");
        puts("This is information of your card:");
        fseek(f,sizeof(Database)*(cardNumber-1000),SEEK_SET);
        Database load;
        fread(&load,sizeof(Database),1,f);
        printf("%-15s:%d\n%-15s:%s\n%-15s:%d Rials\n","Card Number",cardNumber,"Owner name",
            load.ownerName,"Finance",load.accounts);
        return;
    }

void defineAccount(FILE* f)
{
    system("cls");
    puts("You can open a new account here.");
    puts("Enter card number:");
    scanf("%[\n]");
    char cardNumberInput[100];
    fgets(cardNumberInput,99,stdin);
//I do some confinement for user input.This is one of the confinements:
    for(int index=0;index<strlen(cardNumberInput)-1;index++)
    {
        if(!isdigit(cardNumberInput[index]))
        {
            puts("invalid card number.Defining new account failed.");
            return;
        }//if
    }//for
    if(strlen(cardNumberInput)!=5)
    {
        puts("card number must have 4 digits.Defining new account failed.");
        return;
    }
    fseek(f,sizeof(Database)*(atoi(cardNumberInput)-1000),SEEK_SET);
    Database load;
    fread(&load,sizeof(Database),1,f);
    if(load.cardNumber<10000 && load.cardNumber>=1000)
    {
        puts("This card has been already defined in database.Defining new account failed.");
        return;
    }
    puts("Enter owner name:");
    char nameInput[100];
    fgets(nameInput,99,stdin);
    //confinements


    puts("Enter password:");
    char passwordInput[100];
    fgets(passwordInput,99,stdin);
    //confinements

    puts("Enter finance(in Rials):");
    char financeInput[100];
    fgets(financeInput,99,stdin);
    //confinements

    Database newAccount={atoi(cardNumberInput),atoi(passwordInput),strdup(nameInput),
        atoi(financeInput),notFreezed};
    fseek(f,sizeof(Database)*(atoi(cardNumberInput)-1000),SEEK_SET);
    fwrite(&newAccount,sizeof(Database),1,f);
return;
}

I have initialized the file as follows:

/*
    DatabaseFile=fopen("Database.txt","w");
    Database blank={0,0,"",0,freezed};
    for(int accounts=1000;accounts<10000;accounts++)
    {
        fwrite(&blank,sizeof(Database),1,DatabaseFile);
    }
    */
Mohammad
  • 362
  • 1
  • 7
  • 19

2 Answers2

1

You can't use fwrite and fread to save and restore data from disk when the object you are saving/restoring uses heap memory.

If you want to be able to use fwrite and fread to save and restore the data, you should change struct database to:

typedef struct database
{
   int cardNumber;
   int password;
   char ownerName[100];
   int accounts;
   Boolean accessStatus;
} Database;

It will be easier to create on object if you move ownerName to be the last member.

typedef struct database
{
   int cardNumber;
   int password;
   int accounts;
   Boolean accessStatus;
   char ownerName[100];
} Database;

Then, you can use:

Database newAccount=
{
   atoi(cardNumberInput),
   atoi(passwordInput),
   atoi(financeInput),
   notFreezed
};
strcpy(newAccount.ownerName, nameInput);
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • and how do I change `Database newAccount={atoi(cardNumberInput),atoi(passwordInput),strdup(nameInput), atoi(financeInput),notFreezed};`? – Mohammad Jan 17 '15 at 08:03
  • Heap memory is the memory segment where all dynamic allocations take place. There is different segments of memory in a process (the exact number depend on the OS), but you usually find : BSS (static data), stack (local variables and parameter), heap (dynamic allocations), text (program code). – Jean-Baptiste Yunès Jan 17 '15 at 10:57
1

Your problem is that you write Databases structure in your file and that it contains a pointer (ownerName). You can't serialize a C-string like this as you just write the pointer value into the file which is a non-sens across different runs.

To simplify I suggest you to define ownerName as a char array of some size :

char ownerName[MAX_OWNER_NAME_LENGTH];

Arrays are embedded into structures, so it will be correctly written and read back later.

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69