Home > Blockchain >  Copy an array of structs to another array and then write the contents to a binary file
Copy an array of structs to another array and then write the contents to a binary file

Time:07-28

I need to copy the defaultBankData struct to the bank struct repeatedly (i.e. when the user selects option 1 from the menu). However, nothing I've tried does seem to work.

I got the memcpy idea from this community but I can't figure out why it is not allowing the data stored in defaultBankData to be copied. It keeps crashing or simply does nothing whenever I call the GenerateBuyingSellingPrice function. Any tips please?

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define  CURRENCIES 3
#define  PRICES 2
#define ID_COL_WIDTH 4
#define DATE_COL_DAY_WIDTH 2
#define DATE_COL_MONTH_WIDTH 3
#define DATE_COL_YEAR_WIDTH 4
#define BANK_COL_NAME_WIDTH 5

const char* CURRENCY_HEADER_FORMAT_OUT = "Asss\n";
const char* BANK_DATA_HEADER_FORMAT_OUT = "%-9s%-16s%-10s%-8s%-8s%-7s%-8s%-8s%-10s\n";

typedef enum {USD = 1, GBP, CAD} CURRENCY;

typedef struct
{
    int yyyy;
    char mmm[3];
    int dd;
} Date;


typedef struct
{
    int bankId;
    Date exchangeDate;
    char bankName[5];
    float currencyPrice[CURRENCIES][PRICES];

} Bank;

CURRENCY type(int input);
int GetPrices();
int ValidateDate(Date *userDate);
bool SaveFXSummary(char *fileName, Bank *bank, int activeBanks);
Bank *ReadFXSummary(char * fileName, int *activeBanks);
void Menu(void);
void CreateBlankData(Bank *bank, int totalBanks);
void GenerateBuyingSellingPrice(Bank *bank, int activeBanks, Date *userDate);
void DisplayFXSummary(Bank *fileData, int activeBanks);
void ShowHeadingLines(int headingLength);



int main(void)
{
    srand(time(NULL));
    int  activeBanks = 0, totalBanks = 10, choice/*input*/, result = 0;
//    CURRENCY currency;
    Date userDate = {0};//instantiating date struct
    Bank *bank;
    Bank *fileData;

    ***bank = malloc(sizeof(Bank) * totalBanks);***//creates a dynamic array of struct bank
    Bank  blankBankData[totalBanks];
    CreateBlankData(blankBankData, totalBanks);
//    creates an array of struct that contains default data
    ***Bank defaultBankData[] =
    {
        {.bankId = 1001, .exchangeDate = {0,"mmm",0000}, .bankName = "JN\0",  .currencyPrice = {{0, 0},{0, 0},{0, 0}}},
        {.bankId = 1002, .exchangeDate = {0,"mmm",0000}, .bankName = "NCB\0", .currencyPrice = {{0, 0},{0, 0},{0, 0}}},
        {.bankId = 1003, .exchangeDate = {0,"mmm",0000}, .bankName = "BNS\0", .currencyPrice = {{0, 0},{0, 0},{0, 0}}},
        {.bankId = 1004, .exchangeDate = {0,"mmm",0000}, .bankName = "JMMB\0",.currencyPrice = {{0, 0},{0, 0},{0, 0}}},
    };***

    memcpy(bank, blankBankData, sizeof(blankBankData));//copies blankBankdata to bank struct
    DisplayFXSummary(bank, totalBanks);
    memcpy(bank, defaultBankData, sizeof(defaultBankData));//copies defaultBankData to bank struct
    activeBanks = sizeof(bank);

/*---------------------------------------------------------------------------------------------------------------------------
                                          MAIN PROGRAM FUNCTIONALITY MENU
---------------------------------------------------------------------------------------------------------------------------*/
    do
    {
        Menu();
        scanf("%d", &choice);
        printf("\n");

        switch(choice)
        {
            case 1:
                do
                    {
                        printf("\nEnter date [dd-mmm-yyyy]: ");
                        scanf("--%3s-%d", &userDate.dd, userDate.mmm, &userDate.yyyy);
                        result = ValidateDate(&userDate);
                        if(result != 1) printf("Invalid date. Please try again!\n");
                    }while(result != 1);
                    GenerateBuyingSellingPrice(bank, activeBanks, &userDate);
                    break;
            case 2:
                    fileData = ReadFXSummary("FXSummary.bin" ,&activeBanks);
                    if(fileData == NULL)
                    {
                        printf("Error reading from file.\n");
                        return 1;
                    }
                    printf("\nFile data retrieved successfully\n\n");
                    DisplayFXSummary(fileData, activeBanks);
                    free(fileData);
                    break;

        }


    }while(choice != 4);


    return 0;
}
/*---------------------------------------------------------------------------------------------------------------------------
                                            FUNCTION DEFINITIONS
---------------------------------------------------------------------------------------------------------------------------*/

void GenerateBuyingSellingPrice(Bank *bank, int activeBanks, Date *userDate)
{
    int SPREAD = 5;
    for(int i = 0; i < activeBanks; i  )//iterates over list of banks
    {
        //adds date to file
        bank[i].exchangeDate.dd  = userDate->dd;
        strcpy(bank[i].exchangeDate.mmm, userDate->mmm);
        bank[i].exchangeDate.yyyy = userDate->yyyy;
        for(int j = 0; j < CURRENCIES; j  )//iterates over each currency
            {
                for(int k = 0; k <  PRICES; k =2)//iterates over each selling price
                {
                    bank[i].currencyPrice[j][k] = GetPrices();//assign prices
                    //adds spread to selling price for each currency for each bank
                    bank[i].currencyPrice[j][k 1] = bank[i].currencyPrice[j][k]   SPREAD;
                }
            }
    }
    if(SaveFXSummary("FXSummary.bin", bank, activeBanks))
        {
            printf("Records saved successfully\n");
        }
    else
        {
            printf("Error writing to file.\n");
            exit(1);
        }
    free(bank);
}//end of GenerateBuyingSellingPrice function

bool SaveFXSummary(char *fileName, Bank *bank, int activeBanks)
{
    FILE *file;

    file = fopen(fileName, "ab");

    if(file == NULL) return false;

    if(fwrite(&activeBanks, sizeof(int), 1, file)!= 1) return false;

    if(fwrite(bank, sizeof(Bank), activeBanks, file) != activeBanks) return false;

    if(fclose(file) == EOF) return false;

    return true;


}//end of SaveFXSummary function

Bank *ReadFXSummary(char * fileName, int *activeBanks)
{
    FILE *file;

    file = fopen(fileName, "rb");

    if(file == NULL) return NULL;

    if(fread(activeBanks, sizeof(int), 1, file) != 1) return NULL;

    Bank *bankData = malloc(sizeof(Bank) * *activeBanks);

    if(fread(bankData, sizeof(Bank), *activeBanks, file) != *activeBanks)
    {
        free(bankData);
        return NULL;
    }
    if(fclose(file) == EOF)
    {
        free(file);
        return NULL;
    }

    return bankData;

}//end of ReadFXSummary function

void DisplayFXSummary(Bank *fileData, int activeBanks)
{
    printf(CURRENCY_HEADER_FORMAT_OUT,"USD","GBP","CAD");
    ShowHeadingLines(85);
    printf(BANK_DATA_HEADER_FORMAT_OUT, "BankID", "Date", "Bank", "Ask", "Bid", "Ask", "Bid", "Ask", "Bid");
    ShowHeadingLines(85);
    for(int i = 0; i < activeBanks; i  )
    {
        printf("%-.*d\t", ID_COL_WIDTH, fileData[i].bankId);
        printf("%-.*d",DATE_COL_DAY_WIDTH, fileData[i].exchangeDate.dd);
        printf("-%-.*s", DATE_COL_MONTH_WIDTH,fileData[i].exchangeDate.mmm);
        printf("-%-.*d\t",DATE_COL_YEAR_WIDTH,fileData[i].exchangeDate.yyyy);
        printf("%.*s\t",BANK_COL_NAME_WIDTH, fileData[i].bankName); /*"%5s\t"*/
        for(int j = 0; j < CURRENCIES; j  )
            {
                for(int k = 0; k < PRICES; k  )
                {
                    printf("%6.2f\t", fileData[i].currencyPrice[j][k]);
                }
            }
            printf("\n");
}


}//end of DisplayFXSummary function

CURRENCY type(int input)
{
   CURRENCY currencyType = USD;
   if(input == 1) currencyType = USD;
   if(input == 2) currencyType = GBP;
   if(input == 3) currencyType = CAD;
   return currencyType;
}//end of type function

int GetPrices()
{
    int price, minPrice = 80, maxPrice = 150;
    return price = rand() % (maxPrice - minPrice   1)   minPrice;
}//end of GetPrices function

int ValidateDate(Date *userDate)
{
    const int MAX_YR = 9999, MIN_YR = 1900;
    int i, validMonth = 0, validDay = 0, validyear = 0, result = 0/*, isLeapYear = 0*/; //TODO: implement leapYear logic
    int daysInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    char* months[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};

    //evaluates whether year is leap year and change # of days for Feb to 29
    if(userDate->yyyy % 400 == 0 || (userDate->yyyy % 100 != 0 && userDate->yyyy % 4 == 0))
    {
        daysInMonth[1] = 29;
//        isLeapYear = 1;
    }

    for(i = 0; i < 12; i  )
    {

        if(!strcmp(userDate->mmm, months[i]))
        {
//            printf("Month validated successfully!\n");
            validMonth  = 1;
        }
    }

    if(validMonth == 1)
    {
        if(userDate->dd <= daysInMonth[i-1])
        {

//            printf("Day validated successfully!\n");
            validDay = 1;
        }
    }
    if(userDate->yyyy >= MIN_YR && userDate->yyyy <= MAX_YR)
    {
//        printf("Year validated successfully!\n");
        validyear = 1;
    }
    if(validDay && validMonth && validyear) result = 1;

    return result;

}//end of ValidateDate function


void ShowHeadingLines(int headingLength)
{
    for(int i = 0; i < headingLength; i  )
    {
        printf("-");
    }
    printf("\n");
}

void CreateBlankData(Bank *bank, int totalBanks)
{
    for(int i = 0; i < totalBanks; i  )
    {
        bank[i].bankId = 0;
        bank[i].exchangeDate.dd = 0;
        strcpy(bank[i].exchangeDate.mmm,"");
        bank[i].exchangeDate.yyyy = 0;
        strcpy(bank[i].bankName, "");
        for(int j = 0; j < CURRENCIES; j  )
        {
            for(int k = 0; k < PRICES; k  )
            {

                bank[i].currencyPrice[j][k] = 0;
            }
        }
    }

}


void Menu(void)
{
    printf("\n");
    ShowHeadingLines(50);
    printf("Welcome to Campus Forex Brokers(CFB) System\n");
    ShowHeadingLines(50);
    printf("1-----> Generate Buying and Selling Price\n");
    printf("2-----> Display Foreign Exchange Summary\n");
    printf("3-----> Buy Foreign Exchange\n");
    printf("4-----> Exit\n");
    ShowHeadingLines(50);
    printf("\nSelect an option [1-4]: ");

}//end of Menu function

CodePudding user response:

I figured out a trick that works. The below code includes the struct instances which creates a new instance of each default struct which I can then add more data to. Let me know if anyone wants me to share the entire code to test it for themselves and even offer a better solution. This is one version of two though.

void GenerateBuyingSellingPrice()
{
    int SPREAD = 5;
    char dateInput[12];

    printf("\nEnter date [dd-mmm-yyyy]: ");
    scanf("%s", dateInput);

    Bank bank1 = {.bankId = 1001, .dateInput = "00-mmm-0000", .bankName = "JN\0",  .currencyPrice = {{0, 0},{0, 0},{0, 0}}};
    Bank bank2 = {.bankId = 1002, .dateInput = "00-mmm-0000", .bankName = "NCB\0", .currencyPrice = {{0, 0},{0, 0},{0, 0}}};
    Bank bank3 = {.bankId = 1003, .dateInput = "00-mmm-0000", .bankName = "BNS\0", .currencyPrice = {{0, 0},{0, 0},{0, 0}}};
    Bank bank4 = {.bankId = 1004, .dateInput = "00-mmm-0000", .bankName = "JMMB\0",.currencyPrice = {{0, 0},{0, 0},{0, 0}}};

    strcpy(bank1.dateInput, dateInput);strcpy(bank2.dateInput, dateInput);strcpy(bank3.dateInput, dateInput);strcpy(bank4.dateInput, dateInput);

    for(int j = 0; j < CURRENCIES; j  )//iterates over each currency
        {
            for(int k = 0; k <  PRICES; k =2)//iterates over each selling price
            {
                bank1.currencyPrice[j][k] = GetPrices();//assign prices
                bank1.currencyPrice[j][k 1] = bank1.currencyPrice[j][k]   SPREAD;/*adds spread to selling price for each currency for each bank*/
                bank2.currencyPrice[j][k] = GetPrices();
                bank2.currencyPrice[j][k 1] = bank2.currencyPrice[j][k]   SPREAD;
                bank3.currencyPrice[j][k] = GetPrices();
                bank3.currencyPrice[j][k 1] = bank3.currencyPrice[j][k]   SPREAD;
                bank4.currencyPrice[j][k] = GetPrices();
                bank4.currencyPrice[j][k 1] = bank4.currencyPrice[j][k]   SPREAD;
            }
        }
    SaveFXSummary(FILE_NAME, bank1);
    SaveFXSummary(FILE_NAME, bank2);
    SaveFXSummary(FILE_NAME, bank3);
    SaveFXSummary(FILE_NAME, bank4);
    printf("Records saved successfully\n");
}//end of GenerateBuyingSellingPrice function
  • Related