我正在尝试将数据从二进制文件读取到链表,但我无法理解如何添加条件和只读特殊条目。例如,如何阅读place = street?
的汽车STRUCT:
typedef struct S_RacingCar {
char name[12];
char place[12];
int speed;
struct S_RacingCar *next;
struct S_RacingCar *previous;
} RacingCar;
从文件中读取:
RacingCar *ReadNextFromFile(RacingCar *start, FILE *pFile) {
size_t returnValue;
if(start == NULL) {
start = malloc(sizeof(RacingCar));
returnValue = fread(start, sizeof(RacingCar), 1, pFile);
start->next = NULL;
start->previous = NULL;
} else {
RacingCar *indexCar = start;
RacingCar *newCar = malloc(sizeof(RacingCar));
while(indexCar->next != NULL) {
indexCar = indexCar->next;
}
returnValue = fread(newCar, sizeof(RacingCar), 1, pFile);
indexCar->next = newCar;
newCar->next = NULL;
newCar->previous = indexCar;
}
return start;
}
RacingCar *ReadListIn(RacingCar *start) {
FILE *pFile;
pFile = fopen("myList.bin", "rb");
if(pFile != NULL) {
CleanUp(start);
start = NULL;
fseek(pFile, 0, SEEK_END);
long fileSize = ftell(pFile);
rewind(pFile);
int numEntries = (int)(fileSize / (sizeof(RacingCar)));
printf("numEntries:%d\n",numEntries);
int loop = 0;
for(loop = 0; loop < numEntries; ++loop) {
fseek(pFile, (sizeof(RacingCar) * loop), SEEK_SET);
start = ReadNextFromFile(start, pFile);
}
} else {
printf("FILE OPEN ERROR FOR READ\n");
}
return start;
}
答案 0 :(得分:2)
您可能希望在修改列表之前添加条件。例如,
RacingCar temp;
returnValue = fread(&temp, sizeof temp, 1, pFile);
if (returnValue != 1) {
if (ferror(pFile)) {
puts("Error reading from file");
}
return start;
}
if (strncmp(temp.place, "street", sizeof temp.place)) {
return start;
}
一旦这两个条件通过,我们可以保证我们将使用一些内存,因此我们可以分配一些动态内存来存储对象并将汽车添加到列表中:
RacingCar *newCar = malloc(sizeof *newCar);
if (newCar == NULL) {
puts("Error allocating car");
return start;
}
*newCar = temp;
newCar->next = NULL;
newCar->previous = indexCar;
indexCar->next = newCar;
答案 1 :(得分:2)
ReadNextFromFile()的以下代码修复了一些/一些问题,但还有更多,我还没有解决。
我没有添加代码来在发生错误时清理所有已分配的内存。
我没有添加任何检查来区分EOF和I / O错误。
a struct should not be typedef'd. There are several reasons why.
among those reasons are:
1) typedef'ing a struct clutters the code
2) typedef'ing a struct leads to mis-understandings, especially for typedef'd pointers
3) typedef'ing a struct clutters the compiler namespace
struct RacingCar
{
char name[12];
int speed;
struct RacingCar *next;
struct RacingCar *previous;
};
'magic' numbers should not be used.
They greatly reduce the understandability of the code,
and they make for maintenance nightmares.
use a #define, with a meaningful name
then use that name through out the code
When calling 'fgets()' the full length of the
input buffer should be used.
fgets() will properly stop before overflowing the input buffer
#define MAX_USER_INPUT_LENGTH (16)
struct RacingCar *ReadNextFromFile( struct RacingCar *start, FILE *pFile)
{
if( NULL == start )
{
if( NULL == (start = malloc(sizeof( struct RacingCar))
{ // then malloc failed
perror( "malloc for struct RacingCar failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
if( 1 != fread(start, sizeof(struct RacingCar), 1, pFile)
{ // then fread failed
perror( "fread for struct RacingCar, from file, failed");
exit( EXIT_FAILURE );
}
// implied else, fread successful
start->next = NULL;
start->previous = NULL;
}
else
{
struct RacingCar *indexCar = start;
struct RacingCar *newCar = NULL;
if ( NULL == (newCar = malloc(sizeof( struct RacingCar )) ) )
{// then, malloc failed
perror( "malloc for new car failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
while(indexCar->next != NULL)
{
indexCar = indexCar->next;
}
if( 1 != fread( newCar, sizeof(struct RacingCar), 1, pFile)
{ // then fread failed
perror( "fread for struct RacingCar, from file, failed" );
start = NULL;
}
// implied else, fread successful
indexCar->next = newCar;
newCar->next = NULL;
newCar->previous = indexCar;
}
return start;
} // end function: ReadNextFromFile