简体   繁体   English

我在将二进制文件读入 c 中的结构数组时遇到问题

[英]I have got a problem with reading binary file into array of structures in c

Here is part of my code: Here I want to transfer already saved .bin file into a new database structure student s , but it is not transferring more than one member of a structure.这是我的代码的一部分:在这里,我想将已保存的.bin文件传输到新的数据库结构student s中,但它不会传输结构的多个成员。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char name[20];
    int date;
    int month;
    int year;
    int id;
    int pnum;
}student;
int count = 0;
void swap(student* s1, student* s2) {
    student* temp;
    temp = s1;
    s1 = s2;
    s2 = temp;
}

void sort(student* s) {
    for (int i = 0; i < count - 1; i++) {
        for (int j = i + 1; j < count; j++) {
            if (strcmp((s + i)->name, (s + j)->name) > 0) {
                student temp = *(s + i);
                *(s + i) = *(s + j);
                *(s + j) = temp;
            }
        }
    }
}

void addInf(student* s) {
    printf("\t==================================Adding information=====================================\n\n");
    printf("\t\tPlease input following information: \n");
    printf("\tName: ");
    scanf("%s", (s + count)->name);
    printf("\tDate of birth (yyyymmdd): ");
    scanf("%4d%2d%2d", &(s + count)->year, &(s + count)->month, &(s + count)->date);
    printf("\tStudent ID: ");
    scanf("%d", &(s + count)->id);
    printf("\tPhone number: ");
    scanf("%d", &(s + count)->pnum);
    count++;
    printf("\tEntry succeded.\n");
    printf("\t=========================================================================================\n\n");
}

void print(student* s) {
    printf("\t\tName: %s\n", s->name);
    printf("\t\tBidthday: %d/%02d/%02d\n", s->year, s->month, s->date);
    printf("\t\tID: %d\n", s->id);
    printf("\t\tPhone number: %d\n", s->pnum);
}

void delInf(student* s, int n) {
    int com;
    printf("\t=================================Deleting information====================================\n\n");
    printf("\t=========================================================================================\n\n");

    char name[20];
    printf("\t\tPlease input name of the student that you want to delete: ");
    scanf("%s", &name);
    for (int i = 0; i < count; i++) {
        if ((strcmp(name, (s + i)->name)) == 0) {
            printf("\t\tInformation that you want to delete\n");
            print((s + i));

            for (int j = i; j < count; j++) {
                *(s + i) = *(s + i + 1);
                count--;
                printf("\t\tInformation was succesfully deleted.\n\n");
            }
        }
    }
}

void searchByID(student* s) {
    int key;
    printf("\t======================================Searching by ID====================================\n\n");
    printf("\t\tEnter ID: ");
    scanf("%d", &key);
    printf("\t=========================================================================================\n\n");
    int i;
    for (i = 0; i < count; i++) {
        if (key == (s + i)->id) {
            break;
        }
    }
    print((s + i));
}
void searchByName(student* s) {
    char key[20];
    int i;
    int size, check = 0;
    printf("\t======================================Searching by Name==================================\n\n");
    printf("\t\tEnter Name: ");
    scanf("%s", &key);
    printf("\t=========================================================================================\n\n");

    for (i = 0; i < count; i++) {
        if (strcmp(key, (s + i)->name) == 0) {
            print((s + i));
        }
    }
}

void searchByBirthDate(student* s) {
    int key, command;
    int i;
    printf("\t================================Searching by Birthdate================================\n\n");
    printf("\t\t1.By Date\t\t 2.By Month\t\t 3.By Year\t\t 4.By All\n");
    printf("\t\tCommand: ");
    scanf("%d", &command);
    printf("\t=========================================================================================\n\n");
    if (command == 1) {
        printf("Enter date: ");
        scanf("%2d", &key);
        printf("\t\tStudent with same date\n");
        for (i = 0; i < count; i++) {
            if (key == (s + i)->date) {
                printf("\t\t---------%d----------\n\n", i + 1);
                print((s + i));
            }
        }
    }
    if (command == 2) {
        printf("\t\tEnter month: ");
        scanf("%2d", &key);
        printf("\t\tStudent with same month\n");
        for (i = 0; i < count; i++) {
            if (key == (s + i)->month) {
                printf("\t\t---------%d----------\n\n", i + 1);
                print((s + i));
            }
        }
    }
    if (command == 3) {
        printf("\t\tEnter year: ");
        scanf("%4d", &key);
        printf("\t\tStudent with same year\n");
        for (i = 0; i < count; i++) {
            if (key == (s + i)->year) {
                printf("\t\t---------%d----------\n\n", i + 1);
                print(s + i);
            }
        }
    }
    if (command == 4) {
        int yy, mm, dd;
        printf("\t\tEnter birthdate: ");
        scanf("%4d%2d%2d", &yy, &mm, &dd);
        for (i = 0; i < count; i++) {
            if (yy == (s + i)->year && mm == (s + i)->month && dd == (s + i)->date) {
                break;
            }
        }
        print(s + i);
    }
}

void printTable(student* s) {
    printf("\t============================================Table========================================\n\n");
    printf("\t\tName\t\t\tBirthday\t\t\tStudent ID\t\t\tPhone number\n\n");
    for (int i = 0; i < count; i++) {
        printf("\t%d. %s\t\t\t\t%d/%d/%d\t\t\t%d\t\t\t0%d\n\n", i + 1, (s + i)->name, (s + i)->year, (s + i)->month, (s + i)->date, (s + i)->id, (s + i)->pnum);
    }
    printf("\t=========================================================================================\n\n");
}

void search(student* s) {
    printf("\t=========================================Search==========================================\n\n");
    printf("\t\tAvailable commands: \n");
    printf("\t\t1. Search by name\t\t\t2. Search by ID\n\t\t3. Search by birthday\n");
    printf("\t=========================================================================================\n\n");
    printf("\t\tPlease choose command: ");
    int com;
    scanf("%d", &com);

    switch (com) {
    case 1: searchByName(s);
        break;
    case 2: searchByID(s);
        break;
    case 3: searchByBirthDate(s);
        break;
    }
}

void menu() {
    printf("\n\t======================================MENU===============================================\n");
    printf("\t\tAvailable commands: \n");
    printf("\t\t1. Add Student\t\t\t2.Delete student\n\t\t3. Find student\t\t\t4. Table of all students\n");
    printf("\t\t5. Transfer information from binary file\n\t\t6. Save information into binary file.\n\t\t0. Exit\n\n");
    printf("\t=========================================================================================\n\n");
    printf("\t\tPlease choose command: ");
}

int main() {
    FILE* fp;
    FILE* fpr;

    printf("\t\tEnter a name of binary file that you want to create: ");
    char filename[20];
    scanf("%s", &filename);
    strcat(filename, ".bin");

    fp = fopen(filename, "ab");
    if (fp == NULL) {
        printf("\t\tUnable to open the file.\nError\n");
        exit(1);
    }
    else printf("\t\t\tFile %s successfuly created\n\n", filename);
    int iCount;
    int n, c;
    student* s;
    printf("\t\tPlease enter number of students: ");
    scanf("%d", &n);
    printf("\n\n");

    s = (student*)calloc(n, sizeof(student));
    int quit = 1;
    while (quit) {
        menu();
        scanf("%d", &c);
        printf("\n");

        switch (c) {
        case 0:
            quit = 0;
            break;
        case 1:
            addInf(&s);
            break;
        case 2:
            delInf(&s, n);
            break;

        case 3:
            search(&s);

            break;
        case 4:
            if (count == 0) printf("\t\tThere is no any given information yet.\n\n");
            else printTable(&s);
            break;
        case 5:
            printf("\t\tEnter a name or path of file that you want to open: ");
            char readfilename[30];
            scanf("%s", &readfilename);
            strcat(readfilename, ".bin");
            fpr = fopen(readfilename, "rb+");
            if (fpr == NULL) {
                printf("\t\tUnable to open the file.\nError\n");
                break;
            }
            else printf("\t\tFile %s successfuly opened for reading\n", readfilename);
            printf("\t\t\ttransfering binary data from %s into database\n", readfilename);
            while ((fread(&s, sizeof(student), 1, fpr)) == 1) {
                count++;
            }
            printf("\t\t%d student information was successfuly transferred\n", count);
            break;
        case 6:

            iCount = fwrite(&s, sizeof(student), count, fp);
            if (iCount != count) printf("Information could be missed in %s file\n", filename);
            else printf("\t\tAll information was successfuly copied into %s file", filename);
        }
        sort(&s);
    }
    fclose(fp);

    return 0;
}

First of all, enable warnings when compiling, and follow up on them!首先,在编译时启用警告,并跟进它们! This should tell you that &s is wrong in every place where you used it.这应该告诉您&s在您使用它的每个地方都是错误的。 This causes your program to suffer from undefined behavior, which is a total pest when trying to debug your program!这会导致您的程序遭受未定义的行为,这在尝试调试您的程序时完全是有害的!

Now then, on to the code that reads students from file:现在,转到从文件中读取学生的代码:

while ((fread(s, sizeof(student), 1, fpr)) == 1) {
    count++;
}

Every student is read into the same memory area (pointed to by s ).每个学生都被读入同一个 memory 区域(由s指向)。 They overwrite each other, leaving only the last one read.它们相互覆盖,只留下最后一个读取。 Try s + count instead of s :尝试s + count而不是s

while ((fread(s + count, sizeof(student), 1, fpr)) == 1) {
    count++;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM