首页 / 操作系统 / Linux / C语言指针、链表与文件操作学习
准备开始学习C++,对大一所学的C语言一次练习,正好也是赶上老师布置的任务,用C语言写一个 销售管理系统 ,就尽可能的把所学的都用上,也就是结构,指针,文件操作,还有数据结构,本次加入了链表。用两个函数 Load_LinkList() 和 Save_LinkList() 让链表与文件操作结合,除了打印函数,其他都是在内存中操作链表,这样写更有条理,在创建链表时没有采用书上的用一个中间变量引导,并插入到结点前面,而是直接在链表尾的next申请内存,便于理解,操作也方便。/*首先是文件包含,这里就不使用 ifndef 那样常规写一个头文件*/#include <stdio.h>#include <string.h>#include <windows.h>#include <stdlib.h>#include <conio.h> /*接下来就是结构体*//*每一种商品对应一个结点,用链表连接起来,统一写入文件,或者从文件中读取*/typedef struct commodity{int data; //头结点data统计个数,其余为商品编号char name[20];//名称double price; //价格int count;//数量double sum; //总计,头结点sum为所有商品总计struct commodity *next;} *LinkList, LNode; /*定义全局变量,方便使用*//*链表头指针*/LinkList H = NULL;/*文件指针*/FILE *fp = NULL; /*函数声明*//***************显示函数****************///欢迎界面void welcome();//显示菜单void menu();
//打印表格头void printf_header();
//显示单个结点信息void printf_linklist_info(LinkList pTemp);//延时函数void delay();/***********链表文件操作函数*****************///从文件中读取到链表中void Load_LinkList(LinkList H);//将链表保存到文件中void Save_LinkList(LinkList H);/***************链表函数**********************///建立头结点void Creat_LinkList();//添加结点到链表尾部LinkList Add_LinkList(LinkList H);//输入结点数据void Scanf_LinkList(LinkList pTemp);//找到符合要求的结点的前驱LinkList Find_LinkList_Pos(LinkList H,int index);//找到符合要求的结点的地址LinkList Find_LinkList_Val(LinkList H, char *name);//删除指定结点void Del_LinkList(LinkList H, char *name);//修改结点内容void Modify_LinkList(LinkList H, int index, int data);//顺序输出void Printf_LinkList(LinkList H);//释放内存void Free_LinkList(LinkList H); /*main函数,没什么说的,除了getch函数用的时候会方便一些*/int main(){LinkList pTemp = NULL;char name[20] = {0};system("color A");//welcome();Creat_LinkList();Load_LinkList(H);while(1){system("cls");menu();switch(getch()){case "1":pTemp = Add_LinkList(H);Scanf_LinkList(pTemp);getch();break;case "2":printf_header();Printf_LinkList(H);getch();break;case "3":printf("
输入名称查找:");scanf("%s", name);pTemp = Find_LinkList_Val(H, name);printf_linklist_info(pTemp);getch();break;case "4":printf("
请先输入名称查找:");scanf("%s", name);pTemp = Find_LinkList_Val(H, name);Scanf_LinkList(pTemp);getch();break;case "5":printf("
请先输入名称查找:");scanf("%s", name);Del_LinkList(H, name);getch();break;case "6":Save_LinkList(H);printf("
成功保存%d条信息!
", H->data);getch();break;case "0":printf("
欢迎下次使用!
");exit(0);default :printf("错误输入!");getch();}}return 0;} ////////////////////下面是显示函数实现内容/*欢迎界面,其实不要也可以*/void welcome(){int i;for(i=1 ; i<=100 ; i++){printf("*******************欢迎使用本系统*************************");printf("
");printf(" 加载中");printf("...
");printf("%3d%%
",i);printf("**********************************************************");system("cls");}return ;} /*菜单函数*/void menu(){system("cls");printf("欢迎进入本系统
");printf("
");printf("-------------------------------------------------------------------
");printf("| 1 添加商品|
");printf("| 2 显示商品|
");printf("| 3 查找商品|
");printf("| 4 修改商品|
");printf("| 5 删除商品|
");printf("| 6 保存修改|
");printf("| 0 退出系统|
");printf("-------------------------------------------------------------------
");printf(" 提示:退出前请先保存!");printf("
choose(0-8):");} /*以表格的形式打印所有商品信息*/void printf_header(){system("cls");printf("-------------------------您的所有库存-------------------------------------
");printf("| 编号 |名称 |价格 | 数量 |总计|
");printf("|----------|---------------|---------------|----------------|------------|
");} /*显示单个结点信息*/void printf_linklist_info(LinkList pTemp){if(pTemp == NULL){return ;}printf_header();pTemp->sum = pTemp->price * pTemp->count;printf("|%10d|%15s| %lf|%20d|%lf |
",pTemp->data, pTemp->name, pTemp->price, pTemp->count, pTemp->sum);printf("|----------|---------------|---------------|----------------|------------|
");return ;} /*延时函数,写完了发现我一直用的是getch等待按键*/void delay(){long int i,j;for(i=500000 ; i>0 ; i--){for(j=0 ; j<=2000 ; j++);}} /*创建头结点*/void Creat_LinkList(){H = (LinkList)malloc(sizeof(LNode));if(H){H->next = NULL;H->data = 0;}return ;} /*添加结点,这里是直接用最后一个节点的next申请内存*/LinkList Add_LinkList(LinkList H){LinkList q = H;while(q->next != NULL)q = q->next;q->next = (LinkList)malloc(sizeof(LNode));q->next->sum = 0;q->next->next = NULL;H->data++;return q->next;} /*用于添加结点时输入结点信息,或者修改时输入*/void Scanf_LinkList(LinkList pTemp){if(pTemp == NULL){return ;}printf("
输入编号:");scanf("%d", &pTemp->data);printf("输入名称:");scanf("%s", pTemp->name);printf("输入价格:");scanf("%lf", &pTemp->price);printf("输入数量:");scanf("%d", &pTemp->count);pTemp->sum = pTemp->price * pTemp->count;} /*从文件中读取并加载到链表中,和Save函数一样,是最关键的两个函数*/void Load_LinkList(LinkList H){LinkList p = NULL, pTemp = NULL;pTemp = (LinkList)malloc(sizeof(LNode));pTemp->next = NULL;fp = fopen("D:/a.txt", "rb");while(1){/*这里用一个中间结点,临时储存,fread读一次才能决定是否添加结点,直接用p添加结点会错误,本身就是空文件时会多出一个结点,存的垃圾值,而fread必须有一块内存才能读*/if((fread(pTemp, sizeof(LNode), 1, fp)) != 0){p = Add_LinkList(H);p->data = pTemp->data;strcpy(p->name, pTemp->name);p->price = pTemp->price;p->count = pTemp->count;H->data++;}elsebreak;}free(pTemp);fclose(fp);return ;} /*将链表保存到文件中*/void Save_LinkList(LinkList H){LinkList p = H->next;if(p == NULL){/*这里是清空一下,假如链表中保存的有数据,调用删除完之后,不能用fwrite,只是这种情况下用wb清空文件*/fp = fopen("D:/a.txt", "wb");H->data = 0;fclose(fp);getch();return ;}fp = fopen("D:/a.txt", "wb");while(p != NULL){fwrite(p, sizeof(LNode), 1, fp);p = p->next;}fclose(fp);return ;} ///////////////接下来的函数就是只在内存里面操作链表 /*通过位置查找,返回结点前驱结点地址,计划是有这个查找的,后来写菜单也不想用了,就放这里没动过*/LinkList Find_LinkList_Pos(LinkList H,int index){LinkList p = H;index--;while(index--){p = p->next;}return p;} /*通过字符串匹配查找,返回结点地址*/LinkList Find_LinkList_Val(LinkList H, char *name){LinkList p = H;while(strcmp(p->name, name) != 0&&p->next != NULL){p = p->next;}if(p->next == NULL){printf("没有此商品!");return NULL;getch();}return p;} /*删除一个结点,pre是前驱结点,p是要找的结点*/void Del_LinkList(LinkList H, char *name){int flag = 0;LinkList p = H->next, pre = H;while(p != NULL){if(strcmp(p->name, name) == 0){flag = 1;break;}pre = p;p = p->next;}if(flag == 0){printf("没有此商品!
");return ;}p = pre->next;pre->next = p->next;free(p);return ;} /*修改结点信息,也是也可以实现的,和Find_LinkList_Pos()一样,没有用过*/void Modify_LinkList(LinkList H, int index, int data){LinkList p = Find_LinkList_Pos(H, index+1);if(p)p->data = data;return ;} /*顺序输出,表格没有对太齐,应该用 %xd 这样的,后来也不想改了*/void Printf_LinkList(LinkList H){LinkList p = NULL;p = H->next;if(p == NULL){printf("当前没有任何商品!");getch();return ;}while(p != NULL){p->sum = p->price * p->count;printf("|%10d|%15s| %lf | %15d|%lf |
",p->data, p->name, p->price, p->count, p->sum);printf("-------------------------------------------------------------------------------
");p = p->next;}printf(" %lf
", H->sum);return ;} /*内存总是要释放的*/void Free_LinkList(LinkList H){LinkList pre = NULL, p = H->next;while(pre != NULL){pre = p->next;free(p);p = p->next;}H->next = NULL;return ;}本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-09/134888.htm