首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何根据从二进制文件中读取的数据来动态分配结构字段?

如何根据从二进制文件中读取的数据来动态分配结构字段?
EN

Stack Overflow用户
提问于 2017-12-17 22:23:55
回答 2查看 340关注 0票数 0

我有一个看起来像这样的结构:

代码语言:javascript
复制
typedef struct Student {    //dynamically allocated structure
    char *first_name;
    char *last_name;
    float grade;
}Student;

我要做的是从二进制文件中读取数据,并为first_namelast_name字段动态分配内存。当我读取一个普通的.txt文件时,我成功地完成了这项任务。代码如下:

代码语言:javascript
复制
void Read_From_File(const char *file_name, Student *p_destination, const int number_of_students)
{
    FILE *p_file = fopen(file_name, "r");
    if (!p_file)
    {
        perror("Error opening the file. \n");
        exit(EXIT_FAILURE);
    }
    int index = 0;
    while (index < number_of_students)
    {
        unsigned char buffer[256];
        fscanf (p_file, "%s", buffer);
        p_destination[index].last_name = (char*)malloc(strlen(buffer) + 1);
        strcpy(p_destination[index].last_name, buffer);

        fscanf(p_file, "%s", buffer);
        p_destination[index].first_name = (char*)malloc(strlen(buffer) + 1);
        strcpy(p_destination[index].first_name, buffer);

        fscanf(p_file, "%f", &p_destination[index].grade);
        index++;
    }
    fclose(p_file);
}

这很简单,因为fscanf可以单独读取数据,并且具有如下类型说明符:%s姓氏/ %s名字/ %f等级。我不知道如何像使用fscanf那样使用fread来读取单个数据。以下是我到目前为止尝试过的方法,但它不起作用:

代码语言:javascript
复制
int number_of_students = 0;
unsigned char buffer[256];
char file_name[10];
FILE *p_file = NULL;
Student *p_students = NULL;

printf("Enter file name. \n");
scanf("%s", file_name);

p_file = fopen(file_name, "rb");

fread(&number_of_students, sizeof(number_of_students), 1, p_file);
p_students = (Student *)malloc(number_of_students * sizeof(Student));
if (!p_students)
{
    perror("Could not allocate memory. \n");
    exit(EXIT_FAILURE);
}

for (int index = 0; index < number_of_students; ++index)
{
    fread(buffer, sizeof(char), 1, p_file);
    p_students[index].last_name = (char *)malloc(strlen(buffer) + 1);
    if (!p_students[index].last_name)
    {
        printf("Could not allocate memory. \n");
        exit(EXIT_FAILURE);
    }
    strcpy(p_students[index].last_name, buffer);

    fread(buffer, sizeof(char), 1, p_file);
    p_students[index].first_name = (char *)malloc(strlen(buffer) + 1);
    if (!p_students[index].first_name)
    {
        printf("Could not allocate memory. \n");
        exit(EXIT_FAILURE);
    }
    strcpy(p_students[index].first_name, buffer);

    fread(&p_students[index].grade, sizeof(float), 1, p_file);
}
Print_Students(p_students, number_of_students);

此外,Print_Students函数如下所示:

代码语言:javascript
复制
void Print_Students(Student *p_students, int number_of_students)
{
    printf("================================================================================================\n");
    for (unsigned int index = 0; index < number_of_students; ++index)
    {
        printf("\t\t===================== Student %d =====================\n\n", index);
        printf("Last name: %s\n", p_students[index].last_name);
        printf("First name: %s\n", p_students[index].first_name);
        printf("Grade: %.2f\n", p_students[index].grade);
    }
    printf("\n");
}

input.txt文件如下所示:

代码语言:javascript
复制
19
Terresa Minaya 9.50
Otto Pleiman 7 
Illa Holzman 5.25
Alona Greeson 3.40
Natalya Vickrey 10
Catrina Cho 9.34
Loida Dinapoli 9.43
Neely Mcelligott 8.30
Salome Urban 8.75
Rosetta Dagenhart 9.10
Diane Cooksey 10
Novella Longmire 3
Gilberte Manganaro 4
Joye Humbert 5
Justa Larock 6
Delana Bufkin 7
Genaro Kenison 8.98
Refugio Arena 4.56
Iona Nida 7.65

我将这个文件中的数据加载到我的学生矢量中,然后根据矢量中的数据使用编写input.bin文件。我使用了以下代码来编写二进制代码:

代码语言:javascript
复制
void Write_To_Binary(const char *file_name, Student *p_source, const int number_of_students)
{   
    size_t successfully_written = 0;
    FILE *p_file = fopen(file_name, "wb");
    if (!p_file)
    {
        perror("Error opening the file. \n");
        exit(EXIT_FAILURE);
    }
    successfully_written = fwrite(&number_of_students, sizeof(number_of_students), 1, p_file);
    if (successfully_written != 1)
    {
        perror("Error writing to the file. \n");
        exit(EXIT_FAILURE);
    }
    successfully_written = fwrite(p_source, sizeof(Student), number_of_students, p_file);
    if (successfully_written != number_of_students)
    {
        perror("Error writing all the student data. \n");
        exit(EXIT_FAILURE);
    }
    fclose(p_file);
}

更新:我遵循了iBug的解决方案,它起作用了。我按如下方式更改了数据字段: sizeof( last_name ) last_name sizeof( first_name ) first_name grade。

我将在这里发布我用来写入bin文件的函数,并从中读取。

下面是函数Write_To_Binary

代码语言:javascript
复制
    void Write_To_Binary(const char *file_name, Student *p_source, const unsigned int number_of_students)
{
    FILE *p_file = fopen(file_name, "wb");
    if (!p_file)
    {
        perror("Error opening the file. \n");
        exit(EXIT_FAILURE);
    }

    size_t successfully_written = 0;
    successfully_written = fwrite(&number_of_students, sizeof(number_of_students), 1, p_file);
    if (successfully_written != 1)
    {
        printf("Error writing to the file. \n");
        exit(EXIT_FAILURE);
    }

    unsigned int width = 0, width1 = 0;
    for (unsigned int index = 0; index < number_of_students; ++index)
    {
        width = strlen(p_source[index].last_name) + 1;

        successfully_written = fwrite(&width, sizeof(width), 1, p_file);
        printf("Name: %s Width: %d \n", p_source[index].last_name, width);
        if (successfully_written != 1)
        {
            printf("Error writing to the file. \n");
            exit(EXIT_FAILURE);
        }

        successfully_written = fwrite(p_source[index].last_name, width, 1, p_file);
        if (successfully_written != 1)
        {
            printf("Error writing to the file. \n");
            exit(EXIT_FAILURE);
        }

        width = strlen(p_source[index].first_name) + 1;

        successfully_written = fwrite(&width, sizeof(width), 1, p_file);
        if (successfully_written != 1)
        {
            printf("Error writing to the file. \n");
            exit(EXIT_FAILURE);
        }

        successfully_written = fwrite(p_source[index].first_name, width, 1, p_file);
        if (successfully_written != 1)
        {
            printf("Error writing to the file. \n");
            exit(EXIT_FAILURE);
        }

        successfully_written = fwrite(&p_source[index].grade, sizeof(float), 1, p_file);
        if (successfully_written != 1)
        {
            printf("Error writing to the file. \n");
            exit(EXIT_FAILURE);
        }
    }

    fclose(p_file);
}

下面是函数Read_From_Binary

代码语言:javascript
复制
void Read_From_Binary(const char *file_name, Student *p_destination)
{
    FILE *p_file = fopen(file_name, "rb");
    if (!p_file)
    {
        perror("Error opening file. \n");
        exit(EXIT_FAILURE);
    }

    unsigned int number_of_students = 0;
    size_t successfully_read;
    successfully_read = fread(&number_of_students, sizeof(number_of_students), 1, p_file);
    if (successfully_read != 1)
    {
        printf("Error reading the number of students. \n");
        exit(EXIT_FAILURE);
    }

    unsigned int width = 0;
    for (unsigned int index = 0; index < number_of_students; ++index)
    {
        successfully_read = fread(&width, sizeof(width), 1, p_file);
        if (successfully_read != 1)
        {
            printf("Error reading from the file. \n");
            exit(EXIT_FAILURE);
        }

        p_destination[index].last_name = (char*)malloc(width);
        if (!p_destination[index].last_name)
        {
            printf("Could not allocate memory. \n");
            exit(EXIT_FAILURE);
        }
        successfully_read = fread(p_destination[index].last_name, width, 1, p_file);
        if (successfully_read != 1)
        {
            printf("Error reading from the file. \n");
            exit(EXIT_FAILURE);
        }

        successfully_read = fread(&width, sizeof(width), 1, p_file);
        if (successfully_read != 1)
        {
            printf("Error reading from the file. \n");
            exit(EXIT_FAILURE);
        }

        p_destination[index].first_name = (char*)malloc(width);
        if (!p_destination[index].first_name)
        {
            printf("Could not allocate memory. \n");
            exit(EXIT_FAILURE);
        }
        successfully_read = fread(p_destination[index].first_name, width, 1, p_file);
        if (successfully_read != 1)
        {
            printf("Error reading from the file. \n");
            exit(EXIT_FAILURE);
        }

        successfully_read = fread(&p_destination[index].grade, sizeof(float), 1, p_file);
        if (successfully_read != 1)
        {
            printf("Error reading from the file. \n");
            exit(EXIT_FAILURE);
        }
    }

    fclose(p_file);
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-12-17 23:02:51

我在最近的一个项目中做了a similar job

我自己实现了一个二进制文件格式,它的结构是

代码语言:javascript
复制
MAGIC
number of records
record 1
    (int) length of this record
    data
record 2
    (int) length of this record
    data

因此,您可以将额外的4个字节(或一个整数)放入坑中,以指示要读取的内容的长度,并根据该数字进行读取。

这种实现的优点是:

  • 您不需要另一个缓冲区来先读取,这可能会增加对记录长度的额外限制。
  • 当内容格式更改时,您不必担心读取长度的问题。
  • 由于长度为pre-determined.

,因此不需要将单个字符用作“终止符

票数 1
EN

Stack Overflow用户

发布于 2017-12-17 22:58:24

你需要知道文件的格式。我假设以下情况:

  • 文件以一个包含文件中学生数量的四字节整数开头。
  • 有关每个学生的数据的顺序为:名字、姓氏、年级。
  • 字符串的名字和姓氏以空字节结尾。
  • float.
  • Following是一个4字节的浮点数,4字节的浮点数跟在下一个学生后面(没有记录demarcation).

现在您可以读取数据了。唯一的问题是如何确定字符串的长度,因为您必须为它们分配内存。有两种方法:

  • 使用大小合理的缓冲区(例如buf[256]),并逐个字符地读取,直到看到空字符(您可能希望跳过可能导致缓冲区溢出的字符,因此文件格式规范的另一部分是字符串不能超过255)。使用\0读取并终止缓冲区后,调用strlen,然后使用malloc
  • 分配字符串。记住当前位置,逐个字符读取,计数直到看到\0,分配内存,向后查找并读取字符串。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47856045

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档