读取二进制文件并显示条目

时间:2017-11-02 23:46:45

标签: c struct fwrite fread

我可能需要你的帮助来解决这个问题...... 我正在学习C并找到问题,如何正确读取二进制文件。

我填充了一个struct数组,然后在二进制文件上写入并尝试读取它,但这并没有显示任何内容。

代码在pastebin中

My code

#include <stdio.h>
#include <ctype.h>
#include <math.h>

typedef struct {
    int id;
    char name[100];
    char document[14];
    float testGrade;
} Candidate;

typedef struct {
    int id;
    float testGrade;
} Grade;

FILE * openFile(char filename[100], char filemode[3]) {
    FILE *p = fopen(filename, filemode);

    if (!p) {
        printf("Error to open %s file. \nThe program will be closed.",filename);
        exit(1);
    }
}


void addCandidate(int newId, int numbersOfNewCandidate, char candidateFilename[100], char gradeFilename[100]) {
    int counter = 0;
    float testGrade = 0;

    Candidate*candidate;
    candidate= malloc(sizeof(Candidate) * numbersOfNewCandidate);

    Grade *grade;
    grade= malloc(sizeof(Grade) * numbersOfNewCandidate);

    for(;counter< numbersOfNewCandidate; counter++) {
        system("@cls||clear");
        printf("Adding  #%d:",newId);
        printf("\n---------------\n");

        printf("\nName of candidate: ");
        gets(&candidate[counter].name);

        printf("\nDocument: ");
        gets(&candidate[counter].document);

        do {
            printf("\nTest grade (between 0 and 10): ");
            scanf("%f",&testGrade);
            printf("\n---------------\n");

            if (testGrade < 0 || testGrade > 10) {
                printf("\nERROR!\nTest grade %.2f invalid, please try again with a grade between 0 and 10.\n",testGrade);
            }

        } while(testGrade < 0 || testGrade > 10);

        candidate[counter].id = newId;
        grade[counter].id = newId;
        candidate[counter].testGrade = testGrade;
        grade[counter].testGrate = testGrade;
        newId++;
        fflush(stdin);
    }

    FILE *candidateFile = openFile(candidateFilename, "a+b");
    fwrite(candidate, sizeof(candidate),numbersOfNewCandidate, candidateFile );

    FILE *gradeFile = openFile(gradeFilename, "a+b");
    fwrite(grade, sizeof(grade),numbersOfNewCandidate, gradeFile );

    fclose(candidateFile);
    fclose(gradeFile);

    free(candidate);
    free(grade);
}

void showCandidate(int typeOfSearch, char valueToSearch[100]) {}

void listAllCandidates(char candid[100]) {
    FILE *fp = openFile(candidateFilename, "rb");

    //fseek(fp,0,SEEK_SET);

    Candidate *candidate = NULL;

    candidate = malloc(sizeof(Candidate) + 1);

    while(fread(&candidate,sizeof(Candidate),1,fp) == 1) {
        printf("\n\nId: %d \nName: %s \nDocument: %s \nGrade: %.2f",candidate->id,candidate->name,candidate->document, candidate->testGrade);
    }
    getche();
    free(candidate);
}

void main(){
    int lastId = 0;
    char candidateFilename[100] = "candidates.bin";
    char gradeFilename[100] = "classificationList.bin";
    char option;

    do {
        system("@cls||clear");
        printf("Menu: \n");
        printf("1 - Add candidates \n");
        // printf("2 - Search by name \n");
        // printf("3 - Search by document  \n");
        // printf("---------------------------\n");
        // printf("4 - Show Max Grade, Minimum, Avg \n");
        printf("5 - List candidates \n");
        printf("6 - Erase files \n");
        printf("---------------------------\n");
        printf("S - Exit \n");
        printf("\n\n");

        option = toupper(getche());

        switch(option) {
            case '1':
                system("@cls||clear");

                int numbersOfNewCandidate = 0;
                int newId = 0;

                printf("Home > Add candidates\n\n");
                printf("Please give the number of new candidates: ");
                scanf("%d",&numbersOfNewCandidate);
                newId = lastId;
                lastId += numbersOfNewCandidate;

                fflush(stdin);
                addCandidate(newId + 1, numbersOfNewCandidate, candidateFilename, gradeFilename);

                printf("\n\nAdding new candidates: Finished \n");
            break;
            // case '2':
            //     printf("\noption %c@\n",option);
            // break;
            // case '3':
            //     printf("\noption %c#\n",option);
            // break;
            // case '4':
            //     printf("\noption %c?\n",option);
            // break;
            case '5':
                listAllCandidates(candidateFilename);
            break;
            case '6':
                remove(candidateFilename);
                remove(gradeFilename);
                printf("\nRemoved!!\n");
            break;
            case 'S':
                printf("\noption %c, the program will be ended...\n",option);
            break;
            default:
                printf("\nWrong option!!\n");
            break;
        }
    } while (option != 'S');
}

如果您发现有关我的代码的其他问题,请尝试解释一下这个问题。 我已经尝试过了,但还没有。

while(!feof(fp)) {
    fread(&candidate,sizeof(Candidate),1,fp);
    printf("\n\nId: %d \nName: %s \nDocument: %s \nGrade: %.2f",candidate->id,candidate->name,candidate->document, candidate->testGrade);
} 

1 个答案:

答案 0 :(得分:1)

Candidate *candidate = NULL;
candidate = malloc(sizeof(Candidate) + 1);
while(fread(&candidate,sizeof(Candidate),1,fp) == 1) {...}
free(candidate);

fread中的第一个参数应该是指针fread(void*,...),而candidate已经被声明为指针,它不应该有引用运算符。正确的用法是:

while(fread(candidate,sizeof(Candidate),1,fp) == 1) {...}

请注意,&

前面没有引用candidate运算符

<小时/> 有时您会看到一个引用运算符,但这是一个不同的情况:

Candidate cand;
while(fread(&cand,sizeof(cand),1,fp) == 1) {...}

这是一种更简单的方法,因为cand不需要与malloc分配,也不需要free

<小时/> 不必要的函数会引入更多错误:

FILE * openFile(char filename[100], char filemode[3]) {
    FILE *p = fopen(filename, filemode);
    if (!p) {
        printf("Error to open %s file. \nThe program will be closed.",filename);
        exit(1);
    }
}

该函数应该返回一个文件指针。函数参数也可以简单地写为const char* filenameconst char *filemode。例如:

FILE * openFile(const char* filename, const char* filemode) {
    FILE *p = fopen(filename, filemode);
    if (!p) printf("Error to open %s file. \nThe program will be closed.",filename);
    return p;
}

我会完全摆脱这个功能,因为它基本上没用。只需使用fopen即可。完成后,请务必使用fclose关闭手柄。

grade[counter].testGrate = testGrade;
                      ^

这是一个错字,它应该是grade[counter].testGrade。建议编译程序,警告级别设置为最大值,或者至少设置为级别4.编译器将告知错别字,错误和警告。您必须能够零错误和零警告编译程序。这是一个简单的版本:

void listAllCandidates(char* candidateFilename)
{
    FILE *fin = fopen(candidateFilename, "rb");
    Candidate cand;
    while(fread(&cand, sizeof(cand), 1, fin))
        printf("%s, %s, %d, %f\n", cand.name, cand.document, cand.id, cand.testGrade);
    fclose(fin);
}

int main() 
{
    char candidateFilename[] = "file.bin";

    FILE *fout = fopen(candidateFilename, "ab");
    Candidate cand;

    strcpy(cand.name, "name1");
    strcpy(cand.document, "document1");
    cand.id = 1;
    cand.testGrade = 1.1f;
    fwrite(&cand, sizeof(cand), 1, fout);

    strcpy(cand.name, "name2");
    strcpy(cand.document, "document2");
    cand.id = 2;
    cand.testGrade = 2.2f;
    fwrite(&cand, sizeof(cand), 1, fout);

    fclose(fout);

    listAllCandidates(candidateFilename);

    printf("\n");
    return 0;
}