#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string.h>//字符串调用 //3.数据的设计? //3.1程序用什么东西处理数据---->容器--->链表 //3.2数据的结构 ---->图书信息 struct bookInfo //结构体 bookInfo { char name[20]; //书名 字符串数组 double price; //价格 int num; //书本数量 }; struct Node //结构体 定义链表节点 { struct bookInfo data; //结构体 bookInfo 定义数据 struct Node* next; //创建指针 }; struct Node* list = NULL; //将结构体指针node指向空地址(这是初始化过程,避免之后的错误访问) //创建表头:表头就是一个结构体变量 struct Node* createHead() { //动态申请内存 , 分配空间 struct Node* headNode = (struct Node*)malloc(sizeof(struct Node)); //变量的基本规则,使用前必须初始化 headNode->next = NULL; return headNode; } //创建节点:为插入做准备,传参 struct bookInfo 类型数据 data //把用户的数据变为结构体变量 struct Node* createNode(struct bookInfo data) { //创建书本数据节点 动态申请内存 , 分配空间 struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); newNode->data = data; newNode->next = NULL; return newNode; } //插入:只需要一种插入方式 头插法 void insertNodeByHead(struct Node* headNode, struct bookInfo data) { struct Node* newNode = createNode(data); //创建一个欣的数据节点 newNode->next = headNode->next; //插入头部 headNode->next = newNode; } //插入:只需要一种插入方式 尾插法 void insertNodeByTail(struct Node* headNode, struct bookInfo data) { struct Node* pMove = headNode; while (pMove->next != NULL) //遍历到最后的位置 { pMove = pMove->next; } struct Node* newNode = createNode(data); pMove->next = newNode; } //删除方法,查找到对应元素后删除 void deleteNodeByName(struct Node* headNode, char* bookName) //链表名称(头部),书本名 { struct Node* posLeftNode = headNode; //定义一个前指针 struct Node* posNode = headNode->next; //定义一个后指针 //strcmp用于对两组字符串进行比较的函数, //它的返回值是int类型 //字符串2〉字符串2,返回值〉0 true //字符串1〈=字符串2,返回值〈=0 false while (posNode != NULL && strcmp(posNode->data.name, bookName)) //查找指针不为空,并且数据一致 . { posLeftNode = posNode; posNode = posLeftNode->next; } //讨论查询结果 if (posNode == NULL) //没查到 { return; } else //查到了 { printf("删除成功\n"); posLeftNode->next = posNode->next; free(posNode); posNode = NULL; } } //查找 struct Node* searchByName(struct Node* headNode, char* bookName) { struct Node* posNode = headNode->next; while (posNode != NULL && strcmp(posNode->data.name, bookName)) { posNode = posNode->next; } return posNode; } //打印链表,从第二节点开始打印 头节点无数据 void printList(struct Node* headNode) { struct Node* pMove = headNode->next; printf("书名\t价格\t数量\n"); while (pMove != NULL) { printf("%s\t %.1f\t%d\n", pMove->data.name, pMove->data.price, pMove->data.num); pMove = pMove->next; } } //文件操作 //写操作 void saveInfoToFile(const char* filename, struct Node* headNode) { FILE* fp = fopen(filename, "w"); //打开文本filename , w = 写模式 数据流 struct Node* pMove = headNode->next; //第二节点 while (pMove != NULL) { // \t 横向跳到下一制表符位置 \r 回车 \n 回车换行 %.1f 保留一位小数 // fp 文本 , "%s \t %.1f \t %d \n"输出格式 , pMove->data.name, pMove->data.price, pMove->data.num 数据 fprintf(fp, "%s \t %.1f \t %d \n", pMove->data.name, pMove->data.price, pMove->data.num); pMove = pMove->next; } fclose(fp); //关闭数据流 } //文件读操作 void readInfoFromFile(const char* fileName, struct Node* headNode) { FILE* fp = fopen(fileName, "r"); if (fp == NULL) { //不存在就创建出来这个文件 fp = fopen(fileName, "w+"); } struct bookInfo tempData; //fscanf 读取文件 while (fscanf(fp, "%s\t%lf\t%d\n", tempData.name, &tempData.price, &tempData.num) != EOF)// EOF 文本结束 { insertNodeByHead(list, tempData);//调用头插法创建链表 } fclose(fp); } //实现排序冒泡(大数在尾部) void bubbleSortList(struct Node* headNode) { struct Node* end = NULL; struct Node* p = headNode->next; // 外层循环指针 struct Node* q = headNode->next; // 内层循环指针 while (p != end ) { for (q; q->next != NULL; q = q->next) { if (q->data.price > q->next->data.price)//最大值后移 { //交换值 struct bookInfo tempData = q->data; q->data = q->next->data; q->next->data = tempData; end = q; } } } } //1.写界面--->菜单--->模块 void makeMenu() { printf("------------------------------------\n"); printf(" xxoo图书管理系统\n"); printf("\t0.退出系统\n"); printf("\t1.登记书籍\n"); printf("\t2.浏览书籍\n"); printf("\t3.借阅书籍\n"); printf("\t4.归还书籍\n"); printf("\t5.书籍排序\n"); printf("\t6.删除书籍\n"); printf("\t7.查找书籍\n"); printf("------------------------------------\n"); printf("请输入(0~7):"); } //2.做交互 void keyDown() { int userkey = 0; struct bookInfo tempBook; // 产生一个临时变量存储书籍信息 struct Node* result = NULL; scanf("%d", &userkey);//输入 switch (userkey) { case 0: printf("【 退出 】\n"); printf("退出成功\n"); system("pause"); //system(“pause”) 是调用DOS系统的暂停命令 pause 来暂停程序执行,按任意一个键后将继续执行。 exit(0); //退出 break; case 1: printf("【 登记 】\n"); printf("请输入书籍信息(name,price,num):"); scanf("%s %lf %d", tempBook.name, &tempBook.price, &tempBook.num); insertNodeByHead(list, tempBook);//调用插入 saveInfoToFile("bookinfo.txt", list);//调用写操作 break; case 2: printf("【 浏览 】\n"); printList(list); break; case 3: printf("【 借阅 】\n"); //书籍存在可以借阅,书籍的数量-1,不存在借阅失败 printf("请输入借阅的书名:"); scanf("%s", tempBook.name); result = searchByName(list, tempBook.name); //调用查找 if (result == NULL) { printf("没有相关书籍无法借阅!\n"); } else { if (result->data.num > 0) { result->data.num--; printf("借阅成功!\n"); } else { printf("当前书籍无库存,借阅失败!\n"); } } break; case 4: printf("【 归还 】\n"); // 当前书籍的数量+1 printf("请输入归还的书名:"); scanf("%s", tempBook.name); result = searchByName(list, tempBook.name);//调用查找 if (result == NULL) { printf("该书来源非法!\n"); } else { result->data.num++; printf("书籍归还成功!\n"); } break; case 5: printf("【 排序 】\n"); bubbleSortList(list); break; case 6: printf("【 删除 】\n"); printf("请输入删除书名:"); scanf("%s", tempBook.name); deleteNodeByName(list, tempBook.name); //删除对应书 saveInfoToFile("bookinfo.txt", list); //写入文本 break; case 7: printf("【 查找 】\n"); printf("请输入要查询的书名:"); scanf("%s", tempBook.name); result = searchByName(list, tempBook.name); if (result == NULL) { printf("无找到相关的信息!\n"); } else { printf("书名\t价格\t数量\n"); printf("%s\t%.1f\t%d\n", result->data.name, result->data.price, result->data.num); } break; default: printf("【 error 】\n"); break; } } int main() { list = createHead(); readInfoFromFile("bookinfo.txt", list); while (1) { makeMenu(); keyDown(); system("pause"); system("cls"); } system("pause"); return 0; }
c++ 链表的操作(文件)
于 2022-02-16 15:26:56 首次发布