Why C program terminated unexpectedly after file handling operations?

I have written down a simple c program related to a medical store which is saving medicine name, dose, stock and where it is stored in a rack. Here is a code.

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

// Global variable
char *databasePath;

/* function declaration */
void InitConfiguration(FILE *fWrite, FILE *fRead);
void GetUserName();
void ShowMenu();
struct Medicine GetMedicine();
void SearchMedicine(FILE *fWrite, FILE *fRead);
void AddCart(FILE *fWrite, struct Medicine medicine);
void UpdateMedicineStock(FILE *fWrite, struct Medicine medicine);
void AddMedicine(FILE *fWrite);
void SaveMedicine(FILE *fWrite, struct Medicine medicine);
void ConvertToLowerCase(char* string);
struct Medicine SearchMedicineInDatabase(FILE *fRead, struct Medicine medicine);
char* GetStringFromInt(int value);
char* GetStringFromLong(long value);

struct MedicineInfo
{
    long int cupboardNo;
    long int rackNo;
    long int boxNo;
};

struct Medicine
{
    char name[50];
    char dose[15];
    long int stock;
    struct MedicineInfo medicineInfo;
};

void main()
{
    FILE *fWrite, *fRead;
    InitConfiguration(fWrite, fRead);

    // Show welcome message and get user's name.
    GetUserName();
    ShowMenu(fWrite, fRead);

    getch();
    free(databasePath);
}

void ConvertToLowerCase(char *string) {
    int i;
    for (i = 0; i < strlen(string); i++)
    {
        if (string[i] >= 'A' && string[i] <= 'Z') {
            string[i] = string[i] + 32;
        }
    }
}

char* GetStringFromInt(int value)
{
    char* str = malloc(3);
    sprintf(str, "%d", value);
    return str;
}

char* GetStringFromLong(long value)
{
    char* str = malloc(9);
    sprintf(str, "%d", value);
    return str;
}

void InitConfiguration(FILE *fWrite, FILE *fRead)
{
    int fileSize = 0;

    //Try to open configuration file.
    fRead = fopen("program.config", "r");

    fflush(fRead);
    //First time file won't be exist, so create it.
    if (fRead == NULL)
    {
        FILE *fWrite = fopen("program.config", "wb+");

        fflush(fWrite);
        //Write initial database path to configuration file.
        fprintf(fWrite, "%s", "program.config");
        fflush(fWrite);
        printf("Initial configuration sucessfully done!\n");
        fclose(fWrite);
    }
    else
    {
        fseek(fRead, 0, SEEK_END);
        fileSize = ftell(fRead);
        rewind(fRead);
        databasePath = malloc(fileSize * (sizeof(char)));
        fread(databasePath, sizeof(char), fileSize, fRead);
        fclose(fRead);
    }
    //Some compiler doesn't support clear screen, hence this code is commented
    //clrscr();
    system("cls");
}

void GetUserName()
{
    char username[50];
    printf("Welcome to Medical Store Managemant System. \n");
    printf("Please enter your name:  \n");
    gets(username);

    //Some compiler doesn't support clear screen, hence this code is commented
    //clrscr();
    system("cls");

    printf("\nWelcome %s \n\n", &username);
}

void ShowMenu(FILE *fWrite, FILE *fRead)
{
    int selectedOption;

    printf("Please choose your operation: \n");
    printf("Press 1: Search medicine \n");
    printf("Press 2: Add medicine stock \n");
    printf("Press 3: Add medicine \n");
    printf("Press 4: Exit \n");

    scanf("%d", &selectedOption);
    printf("You have selected %d", selectedOption);

    system("cls");
    fflush(stdin);
    switch (selectedOption)
    {
    case 1:
        SearchMedicine(fWrite, fRead);
        break;
    case 2:
        UpdateMedicineStock(fWrite, GetMedicine());
        break;
    case 3:
        AddMedicine(fWrite);
        break;
    case 4:
        exit(0);
        break;
    }
    system("cls");
    ShowMenu(fWrite, fRead);
}

void AddMedicine(FILE *fWrite)
{
    struct Medicine medicine;
    struct MedicineInfo medicineInfo;

    printf("\nEnter medicine details:\n");
    printf("Name:");
    gets(medicine.name);
    printf("Dose:");
    gets(medicine.dose);
    printf("Stock:");
    scanf("%ld", &medicine.stock);

    printf("Cupboard No:");
    scanf("%ld", &medicineInfo.cupboardNo);
    printf("Rack No:");
    scanf("%ld", &medicineInfo.rackNo);
    printf("Box No:");
    scanf("%ld", &medicineInfo.boxNo);

    medicine.medicineInfo = medicineInfo;
    SaveMedicine(fWrite, medicine);

    //Some compiler doesn't support clear screen, hence this code is commented
    //clrscr();
    system("cls");
}

void SaveMedicine(FILE *fWrite, struct Medicine medicine)
{
    ConvertToLowerCase(medicine.name);
    ConvertToLowerCase(medicine.dose);

    strncat(databasePath, medicine.name, strlen(medicine.name));
    strncat(databasePath, "-", strlen("-"));
    strncat(databasePath, medicine.dose, strlen(medicine.dose));
    strncat(databasePath, ".dat", strlen(".dat"));

    FILE *fRead = fopen(databasePath, "r");

    fflush(fRead);
    if (fRead == NULL)
    {
        fWrite = fopen(databasePath, "w");
        if (fWrite == NULL)
        {
            printf("File Correpted!!\n");
        }

        fflush(fWrite);

        fprintf(fWrite, "%s\t%s\t%ld\t%ld\t%ld\t%ld", medicine.name, medicine.dose, medicine.stock, medicine.medicineInfo.cupboardNo, medicine.medicineInfo.rackNo, medicine.medicineInfo.boxNo);
        fclose(fWrite);

        printf("Data save sucessfully!!\n");
    }
    else
    {
        printf("Medicine already exist.!!\n");
    }

    fclose(fRead);
    return 0;
}

void UpdateMedicineStock(FILE *fWrite, struct Medicine medicine)
{
    long int purchaseQty;

    printf("Enter no. of medicine:");
    scanf("%ld,", &purchaseQty);

    medicine.stock = medicine.stock - purchaseQty;
    SaveMedicine(fWrite, medicine);
}

struct Medicine GetMedicine()
{
    struct Medicine medicine;
    printf("\nEnter Medicine Name:");
    gets(medicine.name);

    printf("Enter Medicine Dose:");
    gets(medicine.dose);
    return medicine;
}

void SearchMedicine(FILE *fWrite, FILE *fRead)
{
    struct Medicine medicine = GetMedicine();

    //SearchMedicineInDatabase will be implemented in future.
    medicine = SearchMedicineInDatabase(fRead, medicine);

    printf("Medicine details");
    printf("Name:  %s", medicine.name);
    printf("Dose:  %s", medicine.name);
    printf("Stock: %ld", medicine.stock);

    if (medicine.stock == 0)
        printf("%s is not available.", medicine.name);
    else
        AddCart(fWrite, medicine);
}

struct Medicine SearchMedicineInDatabase(FILE *fRead, struct Medicine medicine)
{
    int fileSize = 0;

    ConvertToLowerCase(medicine.name);
    ConvertToLowerCase(medicine.dose);

    strncat(databasePath, medicine.name, strlen(medicine.name));
    strncat(databasePath, "-", strlen("-"));
    strncat(databasePath, medicine.dose, strlen(medicine.dose));
    strncat(databasePath, ".dat", strlen(".dat"));

    //Try to open database file.
    fRead = fopen(databasePath, "r");
    if (fRead != NULL)
    {
        fflush(fRead);
        fscanf(fRead, "%s\t%s\t%ld\t%ld\t%ld\t%ld", medicine.name, medicine.dose, medicine.stock, medicine.medicineInfo.cupboardNo, medicine.medicineInfo.rackNo, medicine.medicineInfo.boxNo);
    }
    else
        printf("Medicine not available.");

    fclose(fRead);
    return medicine;
}

void AddCart(FILE *fWrite, struct Medicine medicine)
{
    char isAddCart;

    printf("Would you like to add medicine in cart? (y/n)");
    getch(isAddCart);

    switch (isAddCart)
    {
    case 'y':
        UpdateMedicineStock(fWrite, medicine);
        break;
    case 'n':
        break;
    default:
        //Some compiler doesn't support clear screen, hence this code is commented
        //clrscr();
        AddCart(fWrite, medicine);
        break;
    }
}

Open in new window


After saving/getting medicine information program is giving some inappropriate message as below.

Screenshot--1-.pngScreenshot--2-.png
As it's not showing appropriate specific message, I can't give more information about the exception. Please let me know if you need anything else. Guys! I am not good at C, so please try to help as possible as you can.
Janak SethAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

ZoppoCommented:
Hi Janak Seth,

first you should try to debug the problem using a debugger. It's very hard to say what's going wrong from reading the source-code only.

Anyway, there's at least one error I found:

You're passing two pointers to InitConfiguration by value, so no matter what you're doing with the pointers in that function the pointers in the calling function are unchanged, so when you later pass them to ShowMenu they aren't pointers to the files opened before.

Too retrieve pointers by reference you have to pass either pointer to pointer, i.e. somehow like this:
void InitConfiguration(FILE **fWritePtr, FILE **fReadPtr);

...

void main()
{
    FILE *fWrite, *fRead;
    InitConfiguration( &fWrite, &fRead );
    ...
}

...

void InitConfiguration(FILE **fWritePtr, FILE **fReadPtr)
{
    FILE *fWrite;
    FILE *fRead;
    int fileSize = 0;

    if ( NULL == fWritePtr || NULL == fReadPtr )
    {
        // handle error, NULL was passed instead of pointer to FILE*
        return;
    }

    // allocate and initialize the FILE-pointers, the code you already have should work unchanged.
    ...

    // 'pass back' the allocated FILE-pointers
    *fWritePtr = fWrite;
    *fReadPtr = fRead;
}

Open in new window

Hope this helps,

ZOPPO
0
Fabrice LambertFabrice LambertCommented:
Hi,

My C skills are a bit rusty but:
In your SaveMedicine function, you attempt to open a file for reading.
If it fail, you open a 2nd one for writing.
But you close the first file, regardless the open operation was successfull or not.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
sarabandeCommented:
if (fRead == NULL)
    {
        ...
        printf("Data save sucessfully!!\n");
    }
    else
    {
         ...
    }
    fclose(fRead);

as you can see the success message when looking at the console output, the fRead definitively is NULL at fclose(fRead);

i would second Fabrice that this might be the reason for the crash.

Sara
0
Fabrice LambertFabrice LambertCommented:
solution provided
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.