1

This program that I am doing for class to create an EMPLOYEE records file. I created two structs. One called employee and one called date. The EMPLOYEE struct has one char array, one int, 6 float values and DATE(another Struct). The DATE struct has just three int values (month, day, year).

I have created an array of type EMPLOYEE called person[1000].

Here is my code, I keep getting a debug assertion failed error in visual studios pointing to fwrite.c Expression: (Stream !=NULL). I am sure it has to do with my fread or fwite as I have never tried to store structs.

The point of the beginning of this function is to populate the array if the file exists and is not empty, so when the user starts storing data to the array the subscript is updated. I know there are probably a few other issues here but first things first and that would be the reading and writing portion.

Thanks Again,

Mike

void loadPayRoll(EMPLOYEE person[], int *i) 
{
    char sValidate[5] = "exit";
    FILE *f;
    int count = 0;

    f = fopen("emplyeeRecords.bin", "rb");
    if(f){
        while(fread(&person[*i], sizeof(person), 1, f) > 0){
            (*i)++;
        }
        fclose(f);
    }
    else {

        while (strcmp( sValidate, person[*i].name)) {

            fopen("employeeRecords.bin", "ab+");
            printf("Please enter name or type exit to return to main menu: ");
            scanf("%s", person[*i].name);         //must use the '->' when passing by by refrence, must use '&' sign
            flush;

            if (!strcmp( sValidate, person[*i].name))
                break;

            printf("\nPlease enter age of %s: ", person[*i].name);
            scanf("%i", &person[*i].age);
            flush;
            printf("\nPlease enter the hourlyWage for %s: ", person[*i].name);
            scanf("%f", &person[*i].hourlyWage);
            flush;
            printf("\nPlease enter the hours worked for %s: ", person[*i].name);
            scanf("%f", &person[*i].hoursWkd);

            if (person[*i].hoursWkd > 40) {
                person[*i].regPay = person[*i].hoursWkd * 40;
                person[*i].otHoursWkd = person[*i].hoursWkd - 40;
                person[*i].otPay = person[*i].otHoursWkd * (person[*i].hourlyWage * 1.5);
                person[*i].totalPay = person[*i].regPay + person[*i].otPay;
            }
            else {
                person[*i].totalPay = person[*i].hoursWkd * person[*i].hourlyWage;
            }
            flush;
            printf("\nEnter 2 digit month: ");
            scanf("%i", &person[*i].payDate.month);   //must use the '->' when passing by by refrence, must use '&' sign
            flush;
            printf("\nEnter 2 digit day: ");
            scanf("%i", &person[*i].payDate.day);  //must use the '->' when passing by by refrence, must use '&' sign
            flush;
            printf("\nEnter 4 digit year: ");
            scanf("%i", &person[*i].payDate.year);   //must use the '->' when passing by by refrence, must use '&' sign 
            flush;
            fwrite(&person[*i], sizeof(person), 1, f);
            fclose(f);
            (*i)++;
        }
    }
}//end function loadPayRoll
4
  • 1
    Not sure why i is a pointer. It looks like you're using it as an index? It should probably be a regular integer. Other than that, please read here: stackoverflow.com/questions/3711233/… Commented Feb 22, 2013 at 21:52
  • There's no need to open and close the file inside the loop. Just open it before the loop and close it after. Commented Feb 22, 2013 at 21:54
  • i is a pointer because its being passed by another function, but now that I think about it. That might not be neccassary seeing as I dont think another function will need to know the ending subscript value. Commented Feb 22, 2013 at 22:18
  • @Micheal, even if you did need to know it, it'd be better to pass a regular integer as a copy and return its final value. Commented Feb 22, 2013 at 22:33

1 Answer 1

4

I'm pretty sure this:

fopen("employeeRecords.bin", "ab+");

sitting all by its lonesome on a single line without assigning the resulting FILE* has quite a bit to do with your problem.There are plenty of other issues for example:

flush;

Not really sure what thats all about. Perhaps you meant:

fflush(f);

Assuming f is ever actually assigned correctly,

And as pointed out in-comment, you should open the file before the loop starts, then write the data as needed, the close it after the loop is finished.

Sign up to request clarification or add additional context in comments.

9 Comments

Yes, I forgot to put f = fopen(). Flush is defined at the top of my program.
While I have your attention. Can I write the struct to the binary file in one shot even if I want to read certain values from the struct later on in the program? In another function I want to be able to pull only all of my float person[i].totalPay values for each instance of person.
@MichaelBrooks I would not advise it no matter what. Eventually you're going to need to get into the practice of properly packing and unpacking data int a protocol buffer of bytes. When you mem-write structs you risk differences in endian-ness, packing, alignments, etc, whenever the data is read back in. By defining a set of write/read functions that properly (and portably) write and read your data to a target file stream, your going to be better off in the long run.
When you say that you woul not advise it. Are you referring to writing the struct in one shot? Meaning it would be preferred to write each individual value one at a time. I only ask so I can at least get on the right track. I am currently looking into big and little endian now but I have also never heard of it until now.
@MichaelBrooks That is the nice part of using fixed-length records. You can literally walk through the file, one seek after another, to each offset of each record where the data you want is. read it, then move on to the next, etc. You can't do that with variable length data (i.e why XML makes a putrid file-based database). You're seeing it right. Sounds like you understand. But you would increment by 56 bytes every time if you record is 60 (since you just finished advancing by 4 when you read that 32bit value, think about that a min.).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.