从二进制文件中读取数据



我试图从二进制文件到链表读取数据,但我无法理解如何添加条件和只读特殊条目。例如,如何读取car with place = street?

结构:

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:%dn",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 READn");
    }
    return start;
}

下面的代码,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

您可能希望在修改列表之前添加条件。例如,

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;

相关内容

  • 没有找到相关文章

最新更新