Link to home
Start Free TrialLog in
Avatar of Janak Seth
Janak Seth

asked on

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.

User generated imageUser generated image
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.
Avatar of Zoppo
Zoppo
Flag of Germany image

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
ASKER CERTIFIED SOLUTION
Avatar of Fabrice Lambert
Fabrice Lambert
Flag of France image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
solution provided