c语言链表指针,C语言指针、链表与文件操作详解

用两个函数 Load_LinkList() 和 Save_LinkList() 让链表与文件操作结合,除了打印函数,其他都是在内存中操作链表,这样写更有条理,在创建链表时没有采用书上的用一个中间变量引导,并插入到结点前面,而是直接在链表尾的next申请内存,便于理解,操作也方便。

/*首先是文件包含,这里就不使用 ifndef 那样常规写一个头文件*/

#include

#include

#include

#include

#include

/*接下来就是结构体*/

/*每一种商品对应一个结点,用链表连接起来,统一写入文件,或者从文件中读取*/

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("\n输入名称查找:");

scanf("%s", name);

pTemp = Find_LinkList_Val(H, name);

printf_linklist_info(pTemp);

getch();

break;

case '4':

printf("\n请先输入名称查找:");

scanf("%s", name);

pTemp = Find_LinkList_Val(H, name);

Scanf_LinkList(pTemp);

getch();

break;

case '5':

printf("\n请先输入名称查找:");

scanf("%s", name);

Del_LinkList(H, name);

getch();

break;

case '6':

Save_LinkList(H);

printf("\n成功保存%d条信息!\n", H->data);

getch();

break;

case '0':

printf("\n欢迎下次使用!\n");

exit(0);

default :

printf("错误输入!");

getch();

}

}

return 0;

}

下面是显示函数实现内容

/*欢迎界面,其实不要也可以*/

void welcome()

{

int i;

for(i=1 ; i<=100 ; i++)

{

printf("*******************欢迎使用本系统*************************");

printf("\n\n\n\n\n\n\n");

printf(" 加载中");

printf("...\n");

printf(" %3d%%\n",i);

printf("**********************************************************");

system("cls");

}

return ;

}

/*菜单函数*/

void menu()

{

system("cls");

printf(" 欢迎进入本系统 \n");

printf("\n");

printf("-------------------------------------------------------------------\n");

printf("| 1 添加商品 |\n");

printf("| 2 显示商品 |\n");

printf("| 3 查找商品 |\n");

printf("| 4 修改商品 |\n");

printf("| 5 删除商品 |\n");

printf("| 6 保存修改 |\n");

printf("| 0 退出系统 |\n");

printf("-------------------------------------------------------------------\n");

printf(" 提示:退出前请先保存!");

printf("\nchoose(0-8):");

}

/*以表格的形式打印所有商品信息*/

void printf_header()

{

system("cls");

printf("-------------------------您的所有库存-------------------------------------\n");

printf("| 编号 | 名称 | 价格 | 数量 | 总计 |\n");

printf("|----------|---------------|---------------|----------------|------------|\n");

}

/*显示单个结点信息*/

void printf_linklist_info(LinkList pTemp)

{

if(pTemp == NULL)

{

return ;

}

printf_header();

pTemp->sum = pTemp->price * pTemp->count;

printf("|%10d|%15s| %lf |%20d| %lf |\n",pTemp->data, pTemp->name, pTemp->price, pTemp->count, pTemp->sum);

printf("|----------|---------------|---------------|----------------|------------|\n");

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("\n输入编号:");

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++;

}

else

break;

}

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("没有此商品!\n");

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 |\n",p->data, p->name, p->price, p->count, p->sum);

printf("-------------------------------------------------------------------------------\n");

p = p->next;

}

printf(" %lf\n", 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 ;

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值