为什么我以2进制形式写入,然后用2进制读出来就是乱码了?
完整代码:
Library.h:
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#define MAX 50
#include<stdio.h>
#include<stdlib.h>
#include<String.h>
#include<time.h>
typedef struct//定义书结构体
{
char name[MAX];//书名
char number[MAX];//书的编号
double price;//书的价格
int num;//书的数量
}Book;
typedef struct//定义学生账号结构体
{
int account;//账号
char password[MAX];//密码
char name[MAX];//姓名
char student_number[MAX];//学号
int num;//借书数量
Book book[10];//借的书,并且最多只能借10本
}Student;
typedef struct Node//定义书链表
{
Book data;
struct Node* next;
}LinkList_book;
typedef struct Node1//定义学生账户链表
{
Student data;
struct Node1* next;
}LinkList_student;
//全局变量
//LinkList_book* L_book;//书链表
//LinkList_student* L_student;//学生账户链表
void CreateList_book();
void CreateList_student();
void welcome();
void Librarian();
void User();
void insert_book(char name[], char book_number[], double price, int num);
void insert_student(char password[], char name[], char student_number[],int &account);
LinkList_student* Find_student(int account);
LinkList_book* Find_book(char name[]);
void DispBook(LinkList_book* book);//单本
void Disp_Book();//所有
void Delete_book(char name[]);
void Delete_student(char name[]);
void Sort_book();
void saveInfoToFile_book(const char* FileName);
void saveInfoToFile_student(const char* FileName);
void readInfoToFile_book(const char* FileName);
void readInfoToFile_student(const char* FileName);
Library.cpp:
#include"Library.h"
extern LinkList_book* L_book;
extern LinkList_student* L_student;
void welcome()
{
printf("------ 图书管理系统 -----------\n");
printf("****** 1.管理员身份 **********\n");
printf("****** 2.用户身份 **********\n");
printf("****** 0.退出程序 **********\n");
printf("---------------------------------\n");
}
//创建链表
void CreateList_book()
{
L_book = (LinkList_book*)malloc(sizeof(LinkList_book));
L_book->next = NULL;
}
void CreateList_student()
{
L_student = (LinkList_student*)malloc(sizeof(LinkList_student));
L_student->next = NULL;
}
//链表的插入
void insert_book(char name[], char book_number[], double price, int num)
{
LinkList_book* p = NULL;
p = (LinkList_book*)malloc(sizeof(LinkList_book));
//Book book = { name, book_number, price, num};//?
Book book;
strcpy(book.name, name);
strcpy(book.number, book_number);
book.price = price;
book.num = num;
p->data = book;
LinkList_book* q = NULL;
q = L_book;
while (q->next != NULL)
{
q = q->next;
}
p->next = q->next;
q->next = p;
}
void insert_student( char password[], char name[], char student_number[],int &account)
{
LinkList_student* p = NULL;
p = (LinkList_student*)malloc(sizeof(LinkList_student));
//account = rand();//随机分配一个账户
while(1)
{
account = rand();
if (Find_student(account) == NULL)
{
break;
}
}
//Student student = { temp_account, password, name, student_number, 0 };//?
Student student;
student.account = account;
strcpy(student.password, password);
strcpy(student.name, name);
strcpy(student.student_number, student_number);
student.num = 0;
p->data = student;
LinkList_student* q = NULL;
q = L_student;
while (q->next != NULL)
{
q = q->next;
}
p->next = q->next;
q->next = p;
}
//根据账号查找
LinkList_student* Find_student(int account)
{
LinkList_student* p = NULL;
p = L_student->next;
while (p != NULL)
{
if (p->data.account == account)
{
break;
}
p = p->next;
}
return p;
}
//根据图书名字查找
LinkList_book* Find_book(char name[])
{
LinkList_book* p = NULL;
p = L_book->next;
while (p != NULL)
{
if (!strcmp(p->data.name, name))
{
break;
}
p = p->next;
}
return p;
}
//打印单本书
void DispBook(LinkList_book* book)
{
printf("书名\t编号\t价格\t数量\n");
printf("%s\t%s\t%f\t%d\n", book->data.name, book->data.number, book->data.price, book->data.num);
}
//打印所有图书
void Disp_Book()
{
LinkList_book* temp_book = L_book->next;
while (temp_book != NULL)
{
DispBook(temp_book);
temp_book = temp_book->next;
}
}
//删除书
void Delete_book(char name[])
{
LinkList_book* p = NULL, *q = NULL;
p = L_book;
q = p->next;
while (q != NULL)
{
if (strcmp(q->data.name, name) == 0)
{
p->next = q->next;
free(q);
break;
}
p = p->next;
q = p->next;
}
}
//删除学生账号
void Delete_student(char name[])
{
LinkList_student* p = NULL, * q;
q = p = L_student->next;
while (p != NULL)
{
if (!strcmp(p->data.name, name))
{
q = q->next;
break;
}
p = p->next;
q = q->next;
}
p->next = q->next;
free(q);
}
//按照价格图书排序
void Sort_book()
{
LinkList_book* temp_book = L_book;//复制单链表
LinkList_book* p = NULL, * q = NULL, *r = NULL;//使用两个指针
r = temp_book;
while (p != NULL && q != NULL)
{
p = r->next;
q = p->next;
if (p->data.price > q->data.price)
{
p->next = q->next;
q->next = p;
r->next = q;
}
r = p;
DispBook(r);
}
}
//文件写操作
void saveInfoToFile_book(const char* FileName)//书
{
FILE* pf = fopen(FileName, "w");
LinkList_book* pMove = L_book;
while (pMove != NULL)
{
fwrite(&pMove, sizeof(Book), 1, pf);
pMove = pMove->next;
}
fclose(pf);
pf = NULL;
}
void saveInfoToFile_student(const char* FileName)
{
FILE* pf = fopen(FileName, "w");
LinkList_student* pMove = L_student;
while (pMove != NULL)
{
fwrite(&pMove, sizeof(Student), 1, pf);
pMove = pMove->next;
}
fclose(pf);
pf = NULL;
}
//文件读操作
void readInfoToFile_book(const char* FileName)
{
FILE* pf = fopen(FileName, "r");
if (pf == NULL)
{
pf = fopen(FileName, "w+");
}
LinkList_book* pMove = NULL;
while (fread(&pMove, sizeof(Book), 1, pf) != 0)
{
pMove = (LinkList_book*)malloc(sizeof(LinkList_book));
insert_book(pMove->data.name, pMove->data.number, pMove->data.price, pMove->data.num);
}
}
void readInfoToFile_student(const char* FileName)
{
FILE* pf = fopen(FileName, "r");
if (pf == NULL)
{
pf = fopen(FileName, "w+");
}
LinkList_student* pMove = NULL;
while (fread(&pMove, sizeof(Book), 1, pf) != 0)
{
pMove = (LinkList_student*)malloc(sizeof(LinkList_student));
insert_student(pMove->data.password, pMove->data.name, pMove->data.student_number, pMove->data.account);
}
}
UserList.cpp:
#include"Library.h"
extern LinkList_book* L_book;
extern LinkList_student* L_student;
void UserMenu()//用户菜单
{
printf("------ 用户界面 ----------\n");
printf("****** 1.登录 **********\n");
printf("****** 2.注册 *******\n");
printf("****** 0.返回上一层 **********\n");
printf("---------------------------------\n");
}
void UserMenu2()
{
printf("------ 用户使用界面 ---------\n");
printf("****** 1.查找图书 **********\n");
printf("****** 2.查看已存图书 *******\n");
printf("****** 3.借阅图书 *******\n");
printf("****** 4.归还图书 *******\n");
printf("****** 5.按照价格图书排序*******\n");
printf("****** 0.返回上一层 **********\n");
printf("---------------------------------\n");
}
void Register(LinkList_student* student)
{
int input;
char temp_name[MAX];
LinkList_book* temp_book;
do
{
UserMenu2();
printf("请输入0-5:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("--------【查找图书】---------\n");
printf("请输入需要查找的图书名:>");
scanf("%s", temp_name);
temp_book = Find_book(temp_name);
if (temp_book != NULL)
{
DispBook(temp_book);
}
else
{
printf("没有找到该图书\n");
}
break;
case 2:
printf("--------【查看已存图书】---------\n");
Disp_Book();
break;
case 3:
printf("--------【借阅图书】---------\n");
printf("请输入要借阅图书的名字:>");
scanf("%s", temp_name);
temp_book = Find_book( temp_name);
if (temp_book != NULL)
{
student->data.book[student->data.num++] = temp_book->data;//学生借的书本数量+1
temp_book->data.num--;//图书馆里书本数量少1
}
else
{
printf("该图书尚且还未注册\n");
}
saveInfoToFile_book("book.txt");
break;
case 4:
printf("--------【归还图书】---------\n");
printf("请输入要归还图书的名字:>");
scanf("%s", temp_name);
temp_book = Find_book(temp_name);
if (temp_book != NULL)
{
student->data.num--;
Delete_book(temp_name);
}
else
{
printf("您还未借过该本书\n");
}
saveInfoToFile_book("book.txt");
break;
case 5:
printf("--------【按照价格图书排序】---------\n");
Sort_book();
break;
case 0:
printf("-----------返回上一层------------\n");
input = 0;
break;
default:
printf("输入有误,请输入0-5间的数字\n");
break;
}
} while (input);
}
void User()
{
int input;
int account;
do
{
UserMenu();
printf("请输入0-2:>");
scanf("%d", &input);
switch (input)
{
{
case 1://登录
LinkList_student * temp = NULL;//
int account;//储存用户的账号
char password[MAX];//储存用户的密码
printf("--------【登录界面】---------\n");
printf("请输入账号和密码:\n");
printf("账号:>");
scanf("%d", &account);
temp = Find_student(account);
if (temp == NULL)//未找到该账户
{
char ret = 0;
printf("该用户不存在,是否注册,不注册则返回上一层:y/n:>");
scanf(" %c", &ret);/////////////////////////////////////////
if (ret == 'n')
{
break;
}
printf("\n");
}
else//找到了
{
while (1)
{
printf("密码:>");
scanf("%s", password);
if (!strcmp(password, temp->data.password))
{
printf("============登录成功==============\n");
Register(temp);
break;
}
else
{
printf("\n密码错误,请重新输入:>\n");
}
}
break;
}
}
case 2:
printf("--------【注册界面】---------\n");
char temp_password[MAX];
printf("请设置密码:>");
scanf("%s", temp_password);
char temp_name[MAX];
printf("\n请输入姓名:>");
scanf("%s", temp_name);
char temp_student_number[MAX];
printf("\n请输入学号:>");
scanf("%s", temp_student_number);
insert_student(temp_password, temp_name, temp_student_number, account);
printf("\n注册成功,你的账号为:%d\n", account);
saveInfoToFile_student("student.txt");
break;
case 0:
printf("-----------返回上一层------------\n");
input = 0;
break;
default:
printf("输入有误,请输入0-2间的数字\n");
break;
}
} while (input);
}
Libralian.cpp
#include"Library.h"
extern LinkList_book* L_book;
extern LinkList_student* L_student;
void LibrarianMenu()//管理员菜单
{
printf("------- 管理员界面 ---------\n");
printf("****** 1.注册新图书 **********\n");
printf("****** 2.查看已存图书 *******\n");
printf("****** 3.修改已有图书 *******\n");
printf("****** 4.注销现存图书 *******\n");
printf("****** 0.返回上一层 *********\n");
printf("---------------------------------\n");
}
void Librarian()
{
int input = 0;
do
{
LibrarianMenu();
printf("请输出0-4:>");
scanf("%d", &input);
LinkList_book* temp_book = NULL;//临时书本
char temp_name[MAX];//临时书本名
char temp_number[MAX];//临时书本编号
double temp_price;//临时书本价格
int temp_num;//临时书本数量
int temp;//临时选项
switch (input)
{
case 1:
printf("--------【注册新图书】---------\n");
printf("书名:>");
scanf("%s", temp_name);
printf("\n编号:>");
scanf("%s", temp_number);
printf("\n价格:>");
scanf("%lf", &temp_price);
printf("\n数量:>");
scanf("%d", &temp_num);
printf("\n");
insert_book(temp_name, temp_number, temp_price, temp_num);
saveInfoToFile_book("book.txt");
break;
case 2:
printf("--------【查看已存图书】---------\n");
Disp_Book();
break;
case 3:
printf("--------【修改已有图书】---------\n");
printf("请输入需要修改书本的名字:>");
scanf("%s", temp_name);
printf("\n");
temp_book = Find_book(temp_name);
if (temp_book == NULL)
{
printf("该图书尚未注册\n");
}
else
{
printf("-----------------------\n");
printf("********1.书名*********\n");
printf("********2.编号*********\n");
printf("********3.价格*********\n");
printf("********4.数量*********\n");
printf("请选择需要修改的选项:>");
scanf("%d", &temp);
switch (temp)
{
case 1:
printf("修改后的书名:>");
scanf("%s", temp_name);
strcpy(temp_book->data.name, temp_name);
break;
case 2:
printf("修改后的编号:>");
scanf("%s", temp_number);
strcpy(temp_book->data.number, temp_number);
break;
case 3:
printf("修改后的价格:>");
scanf("%lf", &temp_price);
temp_book->data.price = temp_price;
break;
case 4:
printf("修改后的数量:>");
scanf("%lf", &temp_num);
temp_book->data.num = temp_num;
break;
}
}
saveInfoToFile_book("book.txt");
break;
case 4:
printf("--------【注销现存图书】---------\n");
printf("请输入要删除的书名:>");
scanf("%s", temp_name);
Delete_book(temp_name);
printf("-----删除成功%s-----\n", temp_name);
saveInfoToFile_book("book.txt");
break;
case 0:
printf("-----------返回上一层------------\n");
input = 0;
break;
default:
printf("输入有误,请输入0-4间的数字\n");
break;
}
} while (input);
}
test.cpp:
#include"Library.h"
LinkList_book* L_book;
LinkList_student* L_student;
int main()
{
CreateList_book();
CreateList_student();
readInfoToFile_book("book.txt");
readInfoToFile_student("student.txt");
srand((unsigned int)time(NULL));
int input = 0;// 控制用户的输入的变量
do
{
welcome();//进入菜单
printf("请选择0-2:>");
scanf("%d", &input);//用户选择
switch(input)
{
case 1://选择管理员
Librarian();//进入管理员界面
break;
case 2://选择用户
User();//进入用户界面
break;
case 0:
printf("退出程序\n");
break;
default:
printf("输入有误,请输入0-2间的数字\n");
break;
}
//system("cls");
} while (input);//输入为0自动退出
return 0;
}
Library.cpp: 修改如下,改动处见注释,供参考:
#include"Library.h"
extern LinkList_book* L_book;
extern LinkList_student* L_student;
void welcome()
{
printf("------ 图书管理系统 -----------\n");
printf("****** 1.管理员身份 **********\n");
printf("****** 2.用户身份 **********\n");
printf("****** 0.退出程序 **********\n");
printf("---------------------------------\n");
}
//创建链表
void CreateList_book()
{
L_book = (LinkList_book*)malloc(sizeof(LinkList_book));
L_book->next = NULL;
}
void CreateList_student()
{
L_student = (LinkList_student*)malloc(sizeof(LinkList_student));
L_student->next = NULL;
}
//链表的插入
void insert_book(char name[], char book_number[], double price, int num)
{
LinkList_book* p = NULL;
p = (LinkList_book*)malloc(sizeof(LinkList_book));
p->next = NULL;
//Book book = { name, book_number, price, num};// 修改
//Book book;
strcpy(p->data.name,name); //strcpy(book.name, name);
strcpy(p->data.number,book_number); //strcpy(book.number, book_number);
p->data.price = price; //book.price = price;
p->data.num = num; //book.num = num;
//p->data = book;
LinkList_book* q = NULL;
q = L_book;
while (q->next != NULL)
{
q = q->next;
}
p->next = q->next;
q->next = p;
}
//根据账号查找
LinkList_student* Find_student(int account)
{
LinkList_student* p = NULL;
p = L_student->next;
while (p != NULL)
{
if (p->data.account == account)
{
break;
}
p = p->next;
}
return p;
}
void insert_student( char password[], char name[], char student_number[],int &account)
{
LinkList_student* p = NULL;
p = (LinkList_student*)malloc(sizeof(LinkList_student));
p->next = NULL;
while(1) //account = rand();//随机分配一个账户
{
account = rand();
if (Find_student(account) == NULL)
{
break;
}
}
//Student student = { temp_account, password, name, student_number, 0 };// 修改
//Student student;
p->data.account = account; //student.account = account;
strcpy(p->data.password, password); //strcpy(student.password, password);
strcpy(p->data.name, name); //strcpy(student.name, name);
strcpy(p->data.student_number, student_number);//strcpy(student.student_number, student_number);
p->data.num = 0; //student.num = 0;
//p->data = student;
LinkList_student* q = NULL;
q = L_student;
while (q->next != NULL)
{
q = q->next;
}
p->next = q->next;
q->next = p;
}
//根据图书名字查找
LinkList_book* Find_book(char name[])
{
LinkList_book* p = NULL;
p = L_book->next;
while (p != NULL)
{
if (!strcmp(p->data.name, name))
{
break;
}
p = p->next;
}
return p;
}
//打印单本书
void DispBook(LinkList_book* book)
{
printf("书名\t编号\t价格\t数量\n");
printf("%s\t%s\t%f\t%d\n", book->data.name, book->data.number, book->data.price, book->data.num);
}
//打印所有图书
void Disp_Book()
{
LinkList_book* temp_book = L_book->next;
while (temp_book != NULL)
{
DispBook(temp_book);
temp_book = temp_book->next;
}
}
//删除书
void Delete_book(char name[])
{
LinkList_book* p = NULL, *q = NULL;
p = L_book;
q = p->next;
while (q != NULL)
{
if (strcmp(q->data.name, name) == 0)
{
p->next = q->next;
free(q);
break;
}
p = p->next;
q = p->next;
}
}
//删除学生账号
void Delete_student(char name[])
{
LinkList_student* p = NULL, * q;
q = p = L_student->next;
while (p != NULL)
{
if (!strcmp(p->data.name, name))
{
q = q->next;
break;
}
p = p->next;
q = q->next;
}
p->next = q->next;
free(q);
}
//按照价格图书排序
void Sort_book()
{
LinkList_book* temp_book = L_book;//复制单链表
LinkList_book* p = NULL, * q = NULL, *r = NULL;//使用两个指针
r = temp_book;
while (p != NULL && q != NULL)
{
p = r->next;
q = p->next;
if (p->data.price > q->data.price)
{
p->next = q->next;
q->next = p;
r->next = q;
}
r = p;
DispBook(r);
}
}
//文件写操作
void saveInfoToFile_book(const char* FileName)//书
{
FILE* pf = fopen(FileName, "w");
LinkList_book* pMove = L_book;
while (pMove != NULL)
{
fwrite(&pMove->data, sizeof(Book), 1, pf); //修改
//fwrite(&pMove, sizeof(Book), 1, pf);
pMove = pMove->next;
}
fclose(pf);
pf = NULL;
}
void saveInfoToFile_student(const char* FileName)
{
FILE* pf = fopen(FileName, "w");
LinkList_student* pMove = L_student;
while (pMove != NULL)
{
fwrite(&pMove->data, sizeof(Student), 1, pf); // 修改
// fwrite(&pMove, sizeof(Student), 1, pf);
pMove = pMove->next;
}
fclose(pf);
pf = NULL;
}
//文件读操作
void readInfoToFile_book(const char* FileName)
{
FILE* pf = fopen(FileName, "r");
if (pf == NULL)
{
pf = fopen(FileName, "w+");
}
//LinkList_book* pMove = NULL;
Book book; // 修改
while (1) // 修改
{
if (fread(&book, sizeof(Book), 1, pf) != 1) break; // 修改
insert_book(book.name, book.number, book.price, book.num); // 修改
}
fclose(pf);
}
void readInfoToFile_student(const char* FileName)
{
FILE* pf = fopen(FileName, "r");
if (pf == NULL)
{
pf = fopen(FileName, "w+");
}
//LinkList_student* pMove = NULL;
Student stu; // 修改
while (1) // 修改
{
if (fread(&stu, sizeof(Student), 1, pf) != 1) break; //sizeof(Book) 修改
insert_student(stu.password, stu.name, stu.student_number, stu.account); // 修改
}
fclose(pf);
}
不知道你这个问题是否已经解决, 如果还没有解决的话:答案:
在使用写入二进制文件时,我们需要注意以下两点:
写入时需要考虑写入的数据类型和数据长度,将数据以固定的大小写入文件中,读取的时候需要按照固定的大小读取。
在读取时需要考虑读取的数据类型和数据长度是否与写入时一致,否则将可能读取到错误的数据,导致乱码的情况出现。
根据以上两点,我们可以修改代码为:
// 写入二进制文件
std::ofstream out("myfile.bin", std::ios::binary);
int a = 123;
out.write(reinterpret_cast<char*>(&a), sizeof(int));
out.close();
// 读取二进制文件
std::ifstream in("myfile.bin", std::ios::binary);
int b;
in.read(reinterpret_cast<char*>(&b), sizeof(int));
in.close();
std::cout << b << std::endl;
在写入和读取时,我们使用了reinterpret_cast显式转换指针类型,将指针类型从int转变成char类型,这是为了保证写入和读取的数据长度一致,从而避免出现乱码的情况。
如果还存在乱码的问题,可以尝试使用Windows下提供的二进制编辑器HexEdit查看二进制文件的内容,以确定问题出现的位置。