千家信息网

学习C语言指针和链表的体会

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,一。指针原理指针是一个存储计算机内存地址的变量。从指针指向的内存读取数据称作指针的取值。指针可以指向某些具体类型的变量地址,例如int、long和double。指针也可以是void类型、NULL指针和
千家信息网最后更新 2026年11月01日学习C语言指针和链表的体会

一。指针原理

指针是一个存储计算机内存地址的变量。从指针指向的内存读取数据称作指针的取值。指针可以指向某些具体类型的变量地址,例如int、long和double。指针也可以是void类型、NULL指针和未初始化指针。

二。链表原理

链表由n个节点离散分配,每个节点通过指针连接。每一个节点由一个前驱节点和一个后驱节点,首节点没有前驱节点,尾节点没有后驱节点。链表既然由很多个节点,节点由两个部分组成,一是数据域,用来存放有效数据;二是指针域,用来指向下一个节点;首先应该构造出节点,然后再把所有的节点连起来,就构成了链表。

#include

int main()

{

int*ptr; // 声明一个int指针

int val =1; // 声明一个int值

ptr =&val; // 为指针分配一个int值的引用

int deref = *ptr; // 对指针进行取值,打印存储在指针地址中的内容

printf("deref地址=%ld,值=%d\n",ptr, deref);

第2行,我们通过*操作符声明了一个int指针。接着我们声明了一个int变量并赋值为1。然后我们用int变量的地址初始化我们的int指针。接下来对int指针取值,用变量的内存地址初始化int指针。最终,我们打印输出变量值,内容为1。

第6行的&val是一个引用。在val变量声明并初始化内存之后,通过在变量名之前使用地址操作符&我们可以直接引用变量的内存地址。

第8行,我们再一次使用*操作符来对该指针取值,可直接获得指针指向的内存地址中的数据。由于指针声明的类型是int,所以取到的值是指针指向的内存地址存储的int值。

这里可以把指针、引用和值的关系类比为信封、邮箱地址和房子。一个指针就好像是一个信封,我们可以在上面填写邮寄地址。一个引用(地址)就像是一个邮件地址,它是实际的地址。取值就像是地址对应的房子。我们可以把信封上的地址擦掉,写上另外一个我们想要的地址,但这个行为对房子没有任何影响。

三。体会

我们未学习链表的时候,如果要存储数量比较多的同类型或同结构的数据的时候,总是使用一个数组。比如说我们要存储一个班级学生的某科分数,总是定义一个float型数组但是,在使用数组的时候,总有一个问题困扰着我们:数组应该有多大?
在很多的情况下,你并不能确定要使用多大的数组,比如上例,你可能并不知道该班级的学生的人数,那么你就要把数组定义得足够大。这样,你的程序在运行时就申请了固定大小的你认为足够大的内存空间。即使你知道该班级的学生数,但是如果因为某种特殊原因人数有增加或者减少,你又必须重新去修改程序,扩大数组的存储范围。这种分配固定大小的内存分配方法称之为静态内存分配。但是这种内存分配的方法存在比较严重的缺陷,特别是处理某些问题时:在大多数情况下会浪费大量的内存空间,在少数情况下,当你定义的数组不够大时,可能引起下标越界错误,甚至导致严重后果。

通过这次的学习我明白了怎么去学指针和链表的原理,有了新的认识





附件:学生信息管理系统

/*

*学生信息管理程序,

*管理学生的个人信息及各科成绩;

*/

#include

#include

#include

#include

typedef struct Node Node;

//定义成绩信息节点

//分别为语文、数学、英语和总成绩;


struct Score

{

int chinese,math,english,sum;

};

//定义学生信息节点

//分别为姓名、班级、学号、成绩和指向下一个节点的指针

//定义了4个全局变量,头节点,和临时节点变量;


struct Node

{

char name[20],classs[20],number[20];

struct Score score;

struct Node* next;

}*head,*u,*p,*q;

//定义多个学生的学生个数及各科平均成绩优秀率及格率;

int n,C,M,E,Cj,Cy,Mj,My,Ej,Ey;

char num[20];

//进入菜单函数

void Welcome()

{

printf("\t\t # # # # # # # # # # # # # # # # #\n");

printf("\t\t # 欢迎您使用学生成绩管理系统 #\n");

printf("\t\t # #\n");

printf("\t\t # 1.读取文件 #\n");

printf("\t\t # #\n");

printf("\t\t # 2.保存文件 #\n");

printf("\t\t # #\n");

printf("\t\t # 3.添加学生成绩 #\n");

printf("\t\t # #\n");

printf("\t\t # 4.修改学生成绩 #\n");

printf("\t\t # #\n");

printf("\t\t # 5.删除学生成绩 #\n");

printf("\t\t # #\n");

printf("\t\t # 6.查询个人成绩 #\n");

printf("\t\t # #\n");

printf("\t\t # 7.查询本班成绩 #\n");

printf("\t\t # #\n");

printf("\t\t # 8.查询全校成绩 #\n");

printf("\t\t # #\n");

printf("\t\t # 9.退出管理系统 #\n");

printf("\t\t # #\n");

printf("\t\t # # # # # # # # # # # # # # # # #\n\n");

printf("\t\t 请输入指令:(1-9) ");

}

//构造节点函数

Node* new_node(Node* uu)

{

uu = (Node*)malloc(sizeof(Node));

uu->next = NULL;

return uu;

}

//添加学生信息

void Add()

{

//新建一个节点;

u = new_node(u);

printf("\n请输入您要加入的学生的信息:\n");

printf("\n姓名: ");

scanf("%s",u->name);

printf("\n班级: ");

scanf("%s",u->classs);

printf("\n学号: ");

scanf("%s",u->number);

printf("\n语文、数学、英语成绩: ");

scanf("%d%d%d",&u->score.chinese,&u->score.math,&u->score.english);

//计算总成绩;

u->score.sum = u->score.chinese + u->score.math + u->score.english;

//采用头插法将新节点的尾指针指向第二个节点(掰开)

u->next = head->next;

//将新节点放在头节点后面;

head->next = u;

printf("\n--->添加成功!\n");

}

//根据学号修改信息

//和查找函数一样,依次从第二个节点开始遍历,如果找到这更新

void Mod()

{

n = 0;

printf("\n请输入您要修改的学号: ");

scanf("%s",num);

for(u = head; u != NULL;u = u->next)

{

if(strcmp(u->number,num) == 0)

{

n = 1;

printf("\n请输入新的语文、数学、英语成绩: ");

scanf("%d%d%d",&u->score.chinese,&u->score.math,&u->score.english);

u->score.sum = u->score.chinese + u->score.math + u->score.english;

printf("\n--->修改成功!\n");

break;

}

}

if(!n)

printf("\n--->没有这个学生的信息!\n");

}

//根据学号删除学生信息,

//从头节点开始遍历,如果找到这删除此节点;

void Del()

{

n = 0;

printf("\n请输入您要删除的学生的学号: ");

scanf("%s",num);

for(u = head; u != NULL;u = u->next)

{

if(strcmp(u->number,num) == 0)

{

n = 1;

p->next = u->next;

free(u);

printf("\n--->删除成功!\n");

break;

}

p = u;

}

if(!n)

printf("\n--->没有这个学生的信息!\n");

}

void Sort()

{

int i,j;

//记录学生总数;

n = 0;

for(u = head->next; u != NULL;u = u->next)

n++;

//采用冒泡法对各个节点按班级升序和总成绩降序排列

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

{

u = head;

for(j=0;j

{

p = u->next;

q = p->next;

if(strcmp(p->classs,q->classs) > 0 || strcmp(p->classs,q->classs) == 0 && p->score.sum < q->score.sum)

{

u->next = q;

p->next = q->next;

q->next = p;

}

u = u->next;

}

}

}

//按学号查找某一学生成绩;

void Que_One()

{

//标志变量,记录是否查找成功;

n = 0;

printf("\n请输入您要查询的学生的学号: ");

scanf("%s",num);

//从第二个节点开始遍历,直到最后一个节点为止;

for(u = head->next; u != NULL;u = u->next)

{

//如果当前节点学号与要查找学号一致这输出此学生信息;

if(strcmp(u->number,num) == 0)

{

n = 1;

printf("\n");

puts("班级 姓名 语文 数学 英语 总成绩");

printf("%-11s%-15s",u->classs,u->name);

printf("%-6d%-6d%-6d%-6d\n",u->score.chinese,u->score.math,u->score.english,u->score.sum);

break;

}

}

if(!n)

printf("\n--->没有这个学生的信息!\n");

}

void Analyze_Sco(Node *uu)

{

//对查找到的节点进行求各科平均成绩

//求优秀率及格率;

C += uu->score.chinese;

M += uu->score.math;

E += uu->score.english;

if(uu->score.chinese >= 60)

Cj++;

if(uu->score.chinese >= 90)

Cy++;

if(uu->score.math >= 60)

Mj++;

if(uu->score.math >= 90)

My++;

if(uu->score.english >= 60)

Ej++;

if(uu->score.english >= 90)

Ey++;

}

//打印各科平均成绩及格率优秀率



void Print_Sco()

{

printf("语文平均成绩: %-6.2f, 及格率: %%%-6.2f , 优秀率: %%%-6.2f.\n\n",(float)C/n,(float)100*Cj/n,(float)100*Cy/n);

printf("数学平均成绩: %-6.2f, 及格率: %%%-6.2f , 优秀率: %%%-6.2f.\n\n",(float)M/n,(float)100*Mj/n,(float)100*My/n);

printf("英语平均成绩: %-6.2f, 及格率: %%%-6.2f , 优秀率: %%%-6.2f.\n\n",(float)E/n,(float)100*Ej/n,(float)100*Ey/n);

}

//查找某一班级所以学生的信息;

void Que_Cla()

{

//对链表节点排序;

Sort();

n = C = M = E = Cj = Cy = Mj = My = Ej = Ey = 0;

printf("\n请输入您要查询的班级: ");

scanf("%s",num);

printf("\n");

for(u = head->next; u != NULL;u = u->next)

{

//不是该班的学生则跳过;

if(strcmp(u->classs,num))

continue;

//如果是第一个学生则打印头信息

if(!n)

puts("学号 姓名 语文 数学 英语 总成绩");

n++;

printf("%-11s%-15s",u->number,u->name);

printf("%-6d%-6d%-6d%-d\n",u->score.chinese,u->score.math,u->score.english,u->score.sum);

Analyze_Sco(u);

}

if(!n)

{

printf("没有这个班级的学生信息!\n");

return ;

}

//打印该班级学生的各个成绩的特征值;

printf("\n该班共有学生 %d 人.\n\n",n);

Print_Sco();

}

//打印全校所以学生的信息

//具体情况同打印班级学生信息;

void Que_All()

{

Sort();

n = C = M = E = Cj = Cy = Mj = My = Ej = Ey = 0;

printf("\n");

if(head->next == NULL)

{

printf("--->没有学生信息!\n");

return ;

}

puts("班级 学号 姓名 语文 数学 英语 总成绩");

for(u = head->next; u != NULL;u = u->next)

{

n++;

printf("%-12s%-12s%-15s",u->classs,u->number,u->name);

printf("%-6d%-6d%-6d%-d\n",u->score.chinese,u->score.math,u->score.english,u->score.sum);

Analyze_Sco(u);

}

printf("\n全校共有学生 %d 人.\n\n",n);

Print_Sco();

}

//保存文件;

void Save()

{

char c;

printf("\n确认保存?(Y/N): ");

scanf("%*c%c",&c);

if(c == 'N')

return ;

FILE *fp;

if((fp=fopen("C:\\data.txt","w"))==NULL)

{

printf("\n--->无法打开文件\n");

return ;

}

//写入数据表头信息;

fputs("班级 学号 姓名 语文 数学 英语 总成绩",fp);

if(head->next != NULL)

fputs("\n",fp);

//从头节点开始依次写入文件;

for(u = head->next; u != NULL;u = u->next)

{

fprintf(fp,"%-11s%-11s%-15s",u->classs,u->number,u->name);

fprintf(fp,"%-6d%-6d%-6d%-d",u->score.chinese,u->score.math,u->score.english,u->score.sum);

if(u->next != NULL)

fprintf(fp,"\n");

}

fclose(fp);

printf("\n--->成绩成功存入C:\\\\data.txt中\n");

}

//读取文件;

void Open()

{

printf("\n请把数据放到目录C:\\\\data.txt中,按任意键确认.\n");

getch();

FILE *fp;

//从c盘根目录下读取文件;

if((fp=fopen("C:\\data.txt","r"))==NULL)

{

printf("\n--->没有找到文件!\n");

return ;

}

char tmp[100];

//读取65个菜单头字符存入tem字符数组中;

fgets(tmp,66,fp);


//读到文件结尾处跳出循环;

while(!feof(fp))

{

u = new_node(u);

fscanf(fp,"%s%s%s",u->classs,u->number,u->name);

fscanf(fp,"%d%d%d%d",&u->score.chinese,&u->score.math,&u->score.english,&u->score.sum);

//头插法建立链表;

u->next = head->next;

head->next = u;

}

printf("\n--->成绩读入成功!\n");

fclose(fp);

}

//退出程序

void Exi()

{

char c;

printf("\n确定退出?(Y/N): ");

scanf("%*c%c",&c);

if(c == 'N')

return ;

//打印结束语;

system("cls");

printf("\n\n");

printf("\t\t\t %c %c %c %c %c %c %c %c %c\n",4,4,4,4,4,4,4,4,4);

printf("\t\t\t %c 谢谢使用 %c\n",4,4);

printf("\t\t\t %c %c %c %c %c %c %c %c %c\n",4,4,4,4,4,4,4,4,4);

printf("\t\t\t Thank you!\n\n\n");

exit(0);

}

int main()

{

//存储指令的变量

int orz;

//设置系统文本颜色

system("color 0B");

//新建一个学生信息头节点;

head = new_node(head);

while(1)

{

//显示菜单、

Welcome();

//接收用户命令、

scanf("%d",&orz);

//调用系统函数清屏;

system("cls");

switch(orz)

{

//根据指令进入相应菜单选项

case 1:Open();break;

case 2:Save();break;

case 3:Add();break;

case 4:Mod();break;

case 5:Del();break;

case 6:Que_One();break;

case 7:Que_Cla();break;

case 8:Que_All();break;

case 9:Exi();break;

default :printf("\n--->无效的指令!\n");

}

printf("\n");

//执行系统函数

system("pause");

system("cls");

}

return 0;

}


节点 学生 指针 成绩 信息 地址 学号 内存 变量 班级 数组 文件 数学 语文 英语 总成 总成绩 指向 数据 存储 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技名片 互联网科技的发展 融势互联网科技 深圳期待互联网科技 汉立互联网科技有限公司联系电话 云创客互联网科技公司 济南华为互联网科技产业总部基地 承德科技产业互联网发展 武汉健翔互联网络科技有限公司 互联网科技与大数据专业 坤平互联网科技 威龙国际互联网科技公司 富国互联网科技002692 互联网安防科技感 半导体行业属于互联网高科技类吗 福仕德教育科技互联网 米泉互联网科技专业怎么样 科技互联网公司两年变化 青岛易易互联网科技 陕西彩京云互联网科技有限公司 西安纸贵互联网科技有限公司 互联网核心科技是什么 金融科技与互联网金融 青岛互联网科技公司 互联网科技英文 湖南诚度互联网科技有限公司 互联网科技项目计划书材料类 搜狐科技互联网 开一家科技互联网公司需要多少钱 亚光科技低轨卫星互联网
0