You could call fread
in a loop until it returns 0
, and then print the last record read:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct accountNum
{
int sequence;
char sAccountNum[16];
} ACCOUNTNUM;
int main( void )
{
FILE *fp;
ACCOUNTNUM info;
bool success = false;
//open file and verify that it is open
fp = fopen( "acctNumbers.dat", "r" );
if ( fp == NULL )
{
fprintf( stderr, "Error opening file!\n" );
exit( EXIT_FAILURE );
}
//skip to last record
while( ( fread( &info, sizeof info, 1, fp) ) == 1 )
{
//set variable to indicate that we have found at
//least one record
success = true;
}
//print last record, if it exists
if ( success )
printf( "Acc No: %s\n", info.sAccountNum );
else
printf( "No records found.\n" );
//cleanup
fclose( fp );
}
However, this is only guaranteed to work if you are sure that the last fread
will not perform a partial read, i.e. if you are sure that the file size is an exact multiple of sizeof(ACCOUNTNUM)
. Because if fread
does perform a partial read, then the buffer content will be indeterminate.
If you cannot exclude the possibility of a partial read, then you could use two buffers for reading, and use them alternately:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct accountNum
{
int sequence;
char sAccountNum[16];
} ACCOUNTNUM;
int main( void )
{
FILE *fp;
ACCOUNTNUM info[2];
int current_index = 0;
bool success = false;
size_t ret;
//open file and verify that it is open
fp = fopen( "acctNumbers.dat", "r" );
if ( fp == NULL )
{
fprintf( stderr, "Error opening file!\n" );
exit( EXIT_FAILURE );
}
for (;;) //infinite loop, equivalent to while(1)
{
//read record from file
ret = fread( &info[current_index], sizeof *info, 1, fp);
//swap buffer index
current_index = current_index == 0 ? 1 : 0;
//restart loop if successful
if ( ret == 1 )
{
//set variable to indicate that we have found at
//least one record
success = true;
continue;
}
//break out of loop
break;
}
//print last record, if it exists
if ( success )
printf( "Acc No: %s\n", info[current_index].sAccountNum );
else
printf( "No records found.\n" );
//cleanup
fclose( fp );
}
Or you could use a single buffer and change the way you are calling the function fread
, by swapping the second and third function arguments, so that you can detect whether a partial read occurred. If it does occur, you can print an error message and terminate the program.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct accountNum
{
int sequence;
char sAccountNum[16];
} ACCOUNTNUM;
int main( void )
{
FILE *fp;
ACCOUNTNUM info;
bool success = false;
size_t ret;
//open file and verify that it is open
fp = fopen( "acctNumbers.dat", "r" );
if ( fp == NULL )
{
fprintf( stderr, "Error opening file!\n" );
exit( EXIT_FAILURE );
}
//read one record per loop iteration
while ( ( ret = fread( &info, 1, sizeof info, fp) ) != 0 )
{
//verify that no partial read occurred
if ( ret != sizeof info )
{
fprintf( stderr, "Error: Partial read detected!\n" );
exit( EXIT_FAILURE );
}
//set variable to indicate that we have found at
//least one record
success = true;
}
//print last record, if it exists
if ( success )
printf( "Acc No: %s\n", info.sAccountNum );
else
printf( "No records found.\n" );
//cleanup
fclose( fp );
}