【发布时间】:2017-12-17 14:23:55
【问题描述】:
我的结构看起来像这样:
typedef struct Student { //dynamically allocated structure
char *first_name;
char *last_name;
float grade;
}Student;
我想做的是从二进制文件中读取数据并为 first_name 和 last_name 字段动态分配内存。从普通 .txt 文件中读取时,我成功完成了这项任务。代码如下:
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 读取单个数据。 这是我迄今为止尝试过的,但它不起作用:
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 函数如下所示:
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 文件如下所示:
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 文件。我使用以下代码写入二进制文件:
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
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
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);
}
【问题讨论】:
-
我看到一个可能的问题:strlen(buffer) 不是你需要分配的大小,你需要 strlen(buffer)*sizeof(char)
-
@Angen sizeof(char) 在 C 中是 1(按语言规范),所以不是。
-
感谢您的回答,但它也不起作用。
-
fread(buffer, sizeof(char), 1, p_file);第二个参数是一个元素的大小,第三个参数是要读取的元素数,所以你告诉读取一个大小为 char 的元素
-
谢谢,我可以看到错误,但我该如何处理呢?二进制文件中的名称是随机的,我无法预测这些名称的长度。假设我需要将 sizeof(char) 替换为 strlen(last_name) * sizeof(char)。
标签: c