I need to find the costumer register that is stored in a binary file using his code, as it is definide on the structure above.
typedef struct Employee{
int code;
char name[30];
char cpf[11];
char birthday[11];
double wage;
}TEmployee;
There are 100 registers of the struct above stored in a binary file, and i have to use a sequencial search to find a employee by passing his code as a parameter to the search function. Above is the function i´m currently working on. Can you guys give me some help to make this work? The output is always that the employee was not found.
TEmployee *sequencial_search(int code, FILE *file) {
int i = 0;
while (i < 100) {
fseek(file, sizeof(struct Employee), SEEK_SET);
TEmployee *emp = read(file);
if (code == emp->code) {
return emp;
}
i ;
}
return NULL;
}
read function
TEmployee *read(FILE *in) {
TEmployee *emp = (struct Employee *) malloc(sizeof(struct Employee));
if (fread(&emp->code, sizeof(int), 1, in) <= 0) {
free(emp);
return NULL;
}
fread(emp->name, sizeof(char), sizeof(emp->name), in);
fread(emp->cpf, sizeof(char), sizeof(emp->cpf), in);
fread(emp->birthday, sizeof(char), sizeof(emp->birthday), in);
fread(&emp->wage, sizeof(double), 1, in);
return emp;
}
main
FILE *file = fopen("prova1.dat", "wb ");
TEmployee *emp = sequencial_search(8, file);
if (emp != NULL) {
printf("### EMPLOYEE REGISTER FOUND!!! ### \n\n");
printf("Code: %d \n", emp->code);
printf("Name: %s \n", emp->name);
printf("Cpf: %s \n", emp->cpf);
printf("Birthday: %s \n", emp->birthday);
printf("Wage: %.2f \n", emp->wage);
} else {
printf("Employee register not found! \n");
return 1;
}
free(emp);
fclose(file);
CodePudding user response:
Problems:
Size
Size of struct
differs from the sum of the size of its members due to padding.
Instead, read a whole struct
.
TEmployee *read(FILE *in) {
TEmployee *emp = malloc(sizeof *emp);
if (emp) {
if (fread(emp, sizeof *emp, 1, in) <= 0) {
free(emp);
return NULL;
}
}
return emp;
}
Quitting too early
If code == emp->code
is false, function returns. Better to keep going until emp == NULL
or code == emp->code
.
Memory leak
Make sure a free(emp)
occurs for each malloc()
.
Why seek?
fseek(file, sizeof(struct Employee), SEEK_SET);
not needed. @kaylum
Others?
Other issues may exist.
Tip: size to the object, not the type.
CodePudding user response:
Rather than attempting to write a line-by-line review of the code, it is less confusing to provide an annotated example of what would achieve your objective. "Don't do this" and "do that this way" can lead to misunderstandings and frustration.
I hope the following is easy to follow, and points you toward your objective.
Before getting into it, though, you need to be aware that "not all int
s are int
s" (same, too, for floating point numbers). First off is the difference between 32bit and 64 bit hardware these days. Very old compilers considered int
to be 16bits. Secondly is the Big Endian
vs Small Endian
nature of hardware. It may not be safe to presume that this binary file is what it seems to be.
#include <stdio.h>
#include <stdlib.h>
typedef struct { // no need for "Employee" token in this source
int code;
char name[30];
char cpf[11];
char birthday[11];
double wage;
} TEmployee;
int sequencial_search( char *, int, TEmployee * ); // forward declaration
// main() uses a function to retrieve a single record (or fail to find it)
// prints out info if target record found
int main() {
char *fname = "prova1.dat"; // filename should be prominent
int findCode = 8; // target record ID should be prominent
TEmployee emp; // 'record' buffer to use
// pass file name, the 'target', and a buffer to be filled in (or not).
// function returns 0 for failure to open file or find record
if( !sequencial_search( fname, findCode, &emp ) ) {
printf( "Employee register not found! \n" );
return 1;
// early exit if failed saves one level of indent
}
// function succeed, so show what was found
printf( "### EMPLOYEE REGISTER FOUND!!! ### \n\n" );
printf( "Code: %d\n", emp.code );
printf( "Name: %s\n", emp.name );
printf( "Cpf: %s\n", emp.cpf);
printf( "Birthday: %s\n", emp.birthday );
printf(" Wage: %.2f\n", emp.wage );
return 0;
}
// returns 1 if found and passed buffer valid, or 0 if not found
int sequencial_search( char *fname, int code, TEmployee *emp ) {
FILE *fp = fopen( fname, "rb" ); // open file here, and ensure it is closed later
// always test for failure (bad filename, for instance)
if( fp == NULL ) {
fprintf( stderr, "Cannot open %s\n", fname );
return 0;
// again, "early return" if cannot proceed
}
int found = 0; // an int 'flag' set to 1 if record found
// read in complete single records
// let fread() determine how many records it can find
while( !found && fread( emp, sizeof *emp, 1, fp ) == sizeof *emp )
found = emp->code == code; // set flag true (1) if this record satisfies
// found or not, close the file
fclose( fp );
return found;
}
I don't have your dataset, so cannot fully test that this is correct.