C语言入门系列 - 链表
第一节 C 语言基础以及基本数据类型
第二节 C 语言运算符
第三节 C 语言控制语句
第四节 C 语言自定义函数
第五节 C 语言修饰变量的关键字
第六节 C 语言构造数据类型–数组
第七节 C 语言字符串
第八节 C 语言指针
第九节 指针与函数、指针函数、函数指针
第十节 数组与指针、二级指针&NULL&void 指针
第十一节 结构体
第十二节 链表
第十三节 共用体union,枚举enum,宏定义#define,条件编译,const与指针
C语言–图书管理项目
链表理解
数组 — 在定义时候确定好需要几个,需要多少空间。个数动态变化的时候,数组不支持伸缩,因此没有办
法响应动态的数据变化。
链表:所有个体还是一个集合,但是这个集合自由伸缩。
链表 有头有尾 , 有一条线会将所有的 节点 穿起来。
学生成绩的结构体
struct Student
{
float score;
char names[21];
};
struct Student;
节点 – 链表来说 – 用一条线将所有的结构体穿起来。
设计节点:
struct Student
{
float score;
char names[21];
// 结构体指针
struct Student *next;
};
一、定义链表
节点中包含:数据域和指针域,数据域用于存放该节点的数据,指针域用于存放下一个节点的地址。
struct Student s1;
struct Student s2;
struct Student s3;
s1.next = &s2;
s1.score = 650
strcpy(s1.names,"小明");
s2.next = &s3;
s2.score = 720;
strcpy(s2.names,"小丽");
s3.next = NULL;
s3.score = 450;
strcpy(s3.names,"小兰");
struct Student *p;
p = &s1
//找规律,遍历链表总结:
while(p != NULL)
{
printf("%f %s",p->score,p->names);
p = p->next;
}
将申请空间替换成动态申请
struct Student *p = NULL;
int i = 0;
while(i < 3)
{
i++;
struct Student *q1 = (struct Student *)malloc(sizeof(struct Student));
// 数据与赋值
printf("请输入第一个同学的姓名:");
scanf("%s",q1->names);
printf("请输入第一个同学的成绩:");
scanf("%f",&q1->score);
q1->next = NULL;
// 找到链条的末尾
struct Student *temp = p;
if(temp == NULL)
{
p = q1;
continue;
}
while(temp->next != NULL)
{
temp = temp->next;
}
// 节点添加到链条的后面。
// temp 就指向了最后一个节点
temp->next = q1;
}
二、使用步骤
链表,我感觉主要是遍历结点,如查找就是遍历每一个结点,匹配每一个结点信息,查找匹配的结点。
添加节点就是遍历到链表最后一个节点,再添加新节点。
修改节点就是遍历到相应结点修改节点信息。
删除节点就是遍历到相应结点,修改该节点的上一个节点的指向。
下面是关于链表的增删改查的使用代码----C语言图书管理项目
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct book{
char name[41];
char author[21];
int num;
float price;
float hot;
struct book *next;
}book;
int hotRank(book* *h){
book *head = *h;
book *pre,*p,*q;
book *tail = NULL;
book *touZhiZhen = (book* )malloc(sizeof(book));
touZhiZhen->next = *h; //让头节点为空,方便排序后找到头节点
if(head == NULL) return 0;
while(touZhiZhen->next != tail)
{
pre = touZhiZhen; //指向头节点
p = touZhiZhen->next; //头节点
q = p->next; //next
// printf("11111111\n");
while (p->next != tail)
{
if (p->hot < q->hot)//升序排列
{ //交换节点
pre->next = q;
p->next = q->next;
q->next = p;
}else{
p = p->next;
}
q = p->next;
pre = pre->next;
// printf("22222\n");
}
tail = p;//一次循环后,最后一个数已最大,tail前移
}
*h = touZhiZhen->next;
p = *h; //从新指向头节点
printf("书名\t作者\t库存\t价格\t热度\n");
while(p!=NULL){
int l = strlen(p->name);
if(l < 10){
printf("%s\t%s\t%d\t%.2f\t%.2f\n",p->name,p->author,p->num,p->price,p->hot);
}else{
printf("%s %s %d\t%.2f\t%.2f\n",p->name,p->author,p->num,p->price,p->hot);
}
p = p->next;
}
return 1;
}
int borrowBook(book* *h){
printf("请输入要借阅书名:");
char str[35];
scanf("%s",str);
book *p = *h;
while(p != NULL){
if(strcmp(str,p->name) == 0){
p->num = p->num-1;
printf("借阅成功\n\n");
return 1;
}
p = p->next;
}
printf("查找不到该书籍\n\n");
return 0;
}
int returnBook(book* *h){
printf("请输入要归还书名:");
char str[35];
scanf("%s",str);
book *p = *h;
while(p != NULL){
if(strcmp(str,p->name) == 0){
p->num = p->num+1;
printf("归还成功\n\n");
return 1;
}
p = p->next;
}
printf("没有该书籍,归还失败\n\n");
return 0;
}
int initLink(book* *h){
//以读的方式打开文件
FILE *fp = fopen("./book.txt","r");
if(fp == NULL)
{
printf("打开文件失败");
return 0;
}
int count = 0;
char ch;
while((ch = fgetc(fp)) != EOF){
if(ch == '\n'){
count++;
}//判断有多少个行(即多少个结构体)
}
rewind(fp); //将文件指针指向文件头
book *p = *h;
int i;
for(i=0; i<count; i++){
book *node = (book *)malloc(sizeof(book));
fscanf(fp,"%s %s %d %f %f\n",node->name,node->author,&node->num,&node->price,&node->hot);
node->next = NULL;
//把创面新建的节点加入链表
if(p == NULL){
p=node;
*h = node;
continue;
}
p->next = node;
p = node;
}
fscanf(fp,"%s",pwd);
// 关闭
fclose(fp);
}
int save(book* *h){
book *p = *h;
//以写的方式打开文件
FILE *fp = fopen("./book.txt","w");
if(fp == NULL)
{
printf("打开文件失败");
return 0;
}
while(p != NULL){
fprintf(fp,"%s %s %d %.2f %.2f\n",p->name,p->author,p->num,p->price,p->hot);
p = p->next;
}
fprintf(fp,"%s",pwd);
// 关闭
fclose(fp);
}
int searchAll(book* *h){
book* p = *h;
printf("书名\t作者\t库存\t价格\t热度\n");
while(p != NULL){
int l = strlen(p->name);
if(l < 8){
printf("%s\t%s\t%d\t%.2f\t%.2f\n",p->name,p->author,p->num,p->price,p->hot);
}else{
printf("%s %s %d\t%.2f\t%.2f\n",p->name,p->author,p->num,p->price,p->hot);
}
p = p->next;
}
printf("搜索完成\n\n");
return 0;
}
int searchName(book* *h){
printf("请输入要搜索书名:");
char str[35];
scanf("%s",str);
printf("书名\t作者\t库存\t价格\t热度\n");
book* p = *h;
while(p != NULL){
if(strcmp(str,p->name) ==0){
printf("%s\t%s\t%d\t%.2f\t%.2f\n",(p)->name,(p)->author,(p)->num,(p)->price,(p)->hot);
}
(p) = (p)->next;
}
printf("搜索完成\n\n");
return 0;
}
int searchAuthor(book* *h){
printf("请输入要搜索作者:");
char str[35];
scanf("%s",str);
printf("书名\t作者\t库存\t价格\t热度\n");
book* p = *h;
while(p != NULL){
if(strcmp(str,p->author) ==0){
printf("%s\t%s\t%d\t%.2f\t%.2f\n",(p)->name,(p)->author,(p)->num,(p)->price,(p)->hot);
}
(p) = (p)->next;
}
printf("搜索完成\n\n");
return 0;
}
void serch(book* *h){
AA:printf("[1]全部查询 [2]按书名查找 [3]按作者查找 其余数字退出\n");
printf("请输入你的选择:");
short temp;
scanf(" %hd",&temp);
switch(temp){
case 1: searchAll(h); goto AA;
case 2: searchName(h);goto AA;
case 3: searchAuthor(h);goto AA;
default: printf("退出搜索界面\n\n"); break;
}
}
int addbook(book* *h){
book *node = (book *)malloc(sizeof(book));
printf("请输入书名:");
scanf("%s",node->name);
printf("请输入书的作者:");
scanf("%s",node->author);
printf("请输入库存数量:");
scanf("%d",&node->num);
printf("请输入书的价格:");
scanf("%f",&node->price);
printf("请输入书的热度:");
scanf("%f",&node->hot);
node->next = NULL;
book* p = *h;
if(p == NULL){
*h = node;
printf("添加完成\n\n");
return 1;
}
while(p->next != NULL){ //找到链表上最后一个节点
p = p->next;
}
p->next = node; //添加节点
printf("添加完成\n\n");
return 1;
}
void UI(){
printf("===========欢迎进入图书管理系统===========\n");
printf("==========================================\n");
printf("=======[1]检索\t\t[2]借书 还书=======\n");
printf("=======[3]热度排行\t[4]添加新书===========\n");
printf("=======[5]修改密码\t[6]保存数据=======\n");
printf("=======[0]退出程序\n");
printf("==========================================\n");
printf("请输入相应的数字选择:");
}
int main()
{
book *h=NULL;
initLink(&h);
//logon();
while(1){
UI();
int num;
scanf("%d",&num);
switch(num){
case 1:serch(&h);break;
case 2:{
printf("[1]借阅 [2]归还 其余退出\n");
short temp;
scanf("%hd",&temp);
if(temp == 1){
borrowBook(&h);
}else if(temp == 2){
returnBook(&h);
}
break;
}
case 3:hotRank(&h);break;
case 4:addbook(&h); break;
case 5:update();;break;
case 6:save(&h);break;
case 0: return 0;
default: printf("请输入功能对应的数字1~6/n");break;
}
}
return 0;
}
总结
链表就是把结构体串联起来。就是结构体有地址域,上一个结构体的地址域指向下一个结构体,这样通过改变指针的指向就可以改变遍历链表,遍历到相应结点但就可以进行增删改查。