C语言指针和链表的体会

一、指向结构体变量的指针变量

指向结构体变量的指针变量的定义形式与一般指针变量的定义形式相同,只是将其指向类型定义为结构体类型即可。例如:
        struct person
            { charname[20];
             char sex;
             int age;
             float height;
            };
       struct person *p;
则指针变量p,它可以指向struct person类型的结构体变量。

将一个指针变量指向一个结构体变量后,可以利用指向该结构体的的指针变量引用成员,如:
        (* 指针变量名).成员名
以上形式也常写成:
        指针变量名->成员名
其中,->为指向运算符,它是由符号“-”和“>”两部分构成的。指向运算符的优先级和成员运算符相同,也是最高一级。

二、指向结构体数组的指针变量

指针变量可以指向整型、字符型、浮点型等基本类型数组。同样,指针变量也可以指向结构体类型的数组。

程序L13_2.C功能:使用指向结构体数组的指针变量。

#include <stdio.h>
void main()
{ struct person
{ char name[20];
char sex;
int age;
float height;
}per[3]={{ "Li Ping", ‘M ‘,20,175},
{"Wang Ling", ‘F ‘,19,162.5},
{"Zhao Hui", ‘M ‘,20,178}};
struct person *p;
for (p=per;p<per+3;p++)
printf("%–18s%3c%4d%7.1f\n ", p->name, p->sex, p->age, p->height);
}

三、 结构体数据作函数参数

不仅结构体变量的成员可以作函数参数,结构体变量以及指向结构体变量的指针都可以作函数参数。

一、结构体变量的成员作函数参数

结构体变量的成员作实参与简单变量、数组元素等作实参是一样的。

二、结构体变量作函数参数

C允许将整个结构体变量作为函数参数传递。传递的是结构体变量全部成员的值,将实参中成员的值赋给对应的形参成员。

用结构体变量作实参时,由于要为形参结构体变量分配存储空间,还要一一对应传递各成员的值,这样会增加处理的时间同时也浪费了内存空间,从而影响程序的运行效率。

三、指向结构体的指针作函数参数

使用指向结构体的指针作函数实参,形参也必须是一个指向相同结构体类型的指针变量,其它使用方法不变。

四、链表的概念

链表是动态数据结构中最基本的形式,它的规模大小可以根据需要进行动态变化,达到合理地使用存储空间。

链表有一个“头指针”变量,用来指向链表的第一个元素。链表中的每个元素都称为“结点”,结点包含两部分内容:一是实际的数据信息;二是下一结点的指针,。链表的最后一个元素置为“NULL”(空地址),标志链表结束。

一个结点可以用一个结构体类型来描述。结构体中包含若干成员,用来表示结点的数据信息。此外必须有一个成员是与结点类型一致的指针,用来指向后续结点。例如,一个链表的结点可以定义为以下的结构体类型:
        struct node
            { int data1;
             float data2;
             struct node *next;
            };
其中,成员next是指向结点的指针变量,它指向next所在的struct node结构体类型数据。

C系统的库函数中提供了动态申请和释放内存存储单元的函数。

(1)malloc函数

malloc函数的原型为:
        void *malloc(unsigned int size)

函数的功能是:在动态存储区域中分配一个size字节的连续空间。函数的返回值为指针,它的值是所分配的存储区域的起始地址。如没有足够的存储空间分配,则返回0(记为NULL)值。

(2)calloc函数

calloc函数的原型为:
        void *calloc(unsigned int n,unsigned int size)

函数的功能是:在动态存储区域中分配n个为size字节的连续空间,并将该存储空间自动置初值0。函数的返回值为指针,它的值是所分配的存储区域的起始地址。如分配不成功,则返回0值。

(3)free函数

free函数的原型为:
        void free(void *ptr)

函数的功能是:释放由ptr所指向的存储空间。ptr的值必须是malloc或calloc函数返回的地址。此函数无返回值。

五、链表的相关操作

一、建立链表

建立链表就是从无到有逐渐增加链表结点的过程,即输入结点数据,并建立前后链接的关系。

下面是建立链表的函数creat() :

struct node *create( )
{ struct node *head, *tail, *p;
int x;
head=tail=NULL;
printf("\n请输入一个整数:");
scanf("%d",&x);
while(x!=0)
{ p=(struct node *)malloc(sizeof(struct node));
p->data=x;
p->next=NULL;
if (head= = NULL)
head=tail=p;
else
{ tail->next=p;
tail=p;
}
printf("请输入一个整数:");
scanf("%d",&x);
}
return (head);
}

二、在链表中插入结点

插入结点的操作有以下几种情况:

(1)链表是空链表,插入的结点作为链表的第一个结点。
(2)链表非空,结点插入到链表的第一个结点前,使插入的结点成为链表第一个结点。
(3)链表非空,结点插入到链表的末尾,使插入的结点成为链表最后一个结点。
(4)链表非空,结点插入到链表中间某个结点之后。

下面函数insert (struct node *head, int value)的作用是在已知头结点head链表中按照从小到大的顺序插入数据value。

struct node *insert(struct node *head, intvalue )
{
struct node *new, *p, *q;
new=(struct node *)malloc(sizeof(struct node));
new->data=value;
p=head;
if(head= =NULL) /*链表是空链表*/
{ head=new; 
new->next=NULL; 
}
else
{ while((p->next !=NULL) &&(p->data<value)) /*寻找插入位置*/
{ q=p; p=p->next; }
if(p->data>=value)
{ if(head= =p) /*链表非空,插入到第一个结点前*/
{ new->next=head;
head=new;
}
else /*链表非空,插入到链表中间*/
{ q->next=new;
new->next=p;
}
}
else /*链表非空,插入到链表末尾*/
{ p->next=new;
new->next=NULL;
}
}
return(head);
}

三、删除链表中的结点

从链表中删除结点,是指把该结点从链表中分离出来,即改变链表的链接关系。从链表中删除的结点有两种处理情况:一是调用函数free()来释放该结点所占的存储空间,将它从内存中删除;二是将该结点插入到其它链表中等待处理。

下面函数delete(struct node *head, int value)的作用是在已知头结点head链表中查找一个数据value,并从链表中删除。

struct node *delete(struct node *head, intvalue )
{ struct node *p, *q;
p=head;
if(head= =NULL) /*链表是空链表*/
{ printf("这是一个空链表!\n"); return(head); }
while((p->next !=NULL) &&(p->data!=value)) /*寻找删除结点位置*/
{ q=p; p=p->next; }
if(value= = p->data)
{ if(head= =p) head=p->next; /*删除链表第一个结点*/
else q->next=p->next; /*删除链表结点*/
free(p);
}
else
printf("此链表没有数据%d!\n",value); /*链表中无此结点*/
return(head);
}

六、程序改进

增加了学生作弊次数统计

#include"stdio.h"

#include"stdlib.h"

#include"string.h"

#include"conio.h"

#define PAGE 3

#define MAX 1000

#define N 5

int k=0;

/*结构体类型*/

typedef struct

{   int num;/*学号*/

char name[20];/*姓名*/

char sex[5];/*性别*/

int age;/*年龄*/

int zuobi;/*作弊次数*/

char studentclass[20];/*班级*/

int score;/*成绩*/

}STUDENTS;

int read_file(STUDENTS stu[])

{ FILE *fp;

int i=0;

if((fp=fopen("stu.txt","rt"))==NULL)

{printf("\n\n*****库存文件不存在!请创");

return 0;

}

while(feof(fp)!=1)

{

fread(&stu[i],sizeof(STUDENTS),1,fp);

if(stu[i].num==0)

break;

else

i++;

}

fclose(fp);

return i;

}

void save_file(STUDENTS stu[],int sum)

{FILE*fp;

int i;

if((fp=fopen("stu.txt","wb"))==NULL)

{printf("写文件错误!\n");

return;

}

for(i=0;i<sum;i++)

if(fwrite(&stu[i],sizeof(STUDENTS),1,fp)!=1)

printf("写文件错误!\n");

fclose(fp);

}

/*创建学生信息*/

int input(STUDENTS stu[])

{  int i,x;

for(i=0;i<1000;i++)

{

system("cls");

printf("\n\n                 录入学生信息  (最多%d个)\n",MAX);

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

printf("\n                     第%d个学生",k+1);

printf("\n 请输入学生的学号:");

scanf("%d",&stu[k].num);

printf("\n 请输入学生的姓名:");

scanf("%s",stu[k].name);

printf("\n 请输入学生的性别:");

scanf("%s",stu[k].sex);

printf("\n 请输入学生的年龄:");

scanf("%d",&stu[k].age);

printf("\n 请输入学生的作弊次数:");

scanf("%d",&stu[k].zuobi);

printf("\n 请输入学生的班级:");

scanf("%s",stu[k].studentclass);

printf("\n 请输入学生的成绩:");

scanf("%d",&stu[k++].score);

printf("\n 请按1键返回菜单或按0键继续创建");

scanf("%d",&x);

if(x)

break;

}

return k;

}

/*删除学生信息*/

void deletel(STUDENTS stu[])

{ system("cls");

char Stuname2[20];

int i,j;

printf("请输入学生姓名:");

scanf("%s",Stuname2);

printf("\n");

for(i=0;i<k;i++)

if(strcmp(stu[i].name,Stuname2)==0)

for(j=0;j<20;j++)

stu[i].name[j]=stu[i+1].name[j];

k--;

printf("删除成功\n");

printf("按任意键加回车返回主菜单!");

scanf("%d",&i);

getchar();

}

/*打印学生信息*/

void output(STUDENTS stu[])

{  system("cls");

int i;

for(i=0;i<k;i++)

printf("学号:%d,姓名:%s,性别:%s,年龄:%s,作弊次数:%d,班级:%s,成绩: %d\n",stu[i].num,stu[i].name,

stu[i].sex,stu[i].age,stu[i].zuobi,stu[i].studentclass,stu[i].score);

printf("按任意键加回车返回主菜单!");

scanf("%d",&i);

getchar();

}

/*查询学生信息*/

void inquire(STUDENTS stu[])

{ int i;

int num;

system("cls");

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

scanf("%d",&num);

for(i=0;i<k;i++)

if(num==stu[i].num)

printf("\n\n\n学号:%d,姓名:%s,性别:%s,年龄:%s,作弊次数:%d,班级:%s,成绩: %d\n",stu[i].num,stu[i].name,

stu[i].sex,stu[i].age,stu[i].zuobi,stu[i].studentclass,stu[i].score);

printf("按任意键加回车返回主菜单!");

scanf("%d",&i);

getchar();

}

/*修改学生信息*/

void change(STUDENTS stu[])

{  int num,i,choice;

system("cls");

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

scanf("%d",&num);

for(i=0;i<k;i++)

{ if(num==stu[i].num)

printf("\n学号:%d,姓名:%s,性别:%s,年龄:%s,作弊次数:%d,班级:%s,成绩: %d\n",stu[i].num,stu[i].name,

stu[i].sex,stu[i].age,stu[i].studentclass,stu[i].score);

printf("\n\n\n     ********请输入您想要修改的数据********\n\n");

printf("                1. 学号\n\n");

printf("                2. 姓名\n\n");

printf("                3. 性别\n\n");

printf("                4. 年龄\n\n");

printf("                5. 年龄\n\n");

printf("                6. 班级\n\n");

printf("                7. 成绩\n\n");

printf("                 请选择(1-7):");

scanf("%d",&choice);

switch(choice)

{case 1:{

printf("\n   请输入你改的新学号");

scanf("%d",&stu[i].num);

break;

}

case 2:{

printf("\n   请输入你改的新姓名");

scanf("%s",stu[i].name);

break;

}

case 3:{

printf("\n   请输入你改的新性别");

scanf("%s",stu[i].sex);

break;

}

case 4:{

printf("\n   请输入你改的新年龄");

scanf("%d",&stu[i].age);

break;

}

case 5:{

printf("\n   请输入你改的新作弊次数");

scanf("%d",&stu[i].zuobi);

break;

}

case 6:{

printf("\n   请输入你改的新班级");

scanf("%s",stu[i].studentclass);

break;

}

case 7:{

printf("\n   请输入你改的新成绩");

scanf("%d",&stu[i].score);

break;

}

}

printf("学号:%d,姓名:%s,性别:%s,年龄:%s,作弊次数:%d,班级:%s,成绩: %d\n",stu[i].num,stu[i].name,

stu[i].sex,stu[i].age,stu[i].zuobi,stu[i].studentclass,stu[i].score);

printf("按任意键加回车返回主菜单!");

scanf("%d",&i);

break;

}

}

/*学生成绩信息排名*/

void sort(STUDENTS stu[])

{  int i,j,n=1,x;

system("cls");

int t;

for(i=0;i<k-1;i++)

for(j=i+1;j<k;j++)

if(stu[i].score<stu[j].score)

{ t=stu[i].score;

stu[i].score=stu[j].score;

stu[j].score=t;

t=stu[i].num;

stu[i].num=stu[j].num;

stu[j].num=t;

}

for(i=0;i<k;i++)

printf("排名    学号    成绩\n %d       %d       %d\n",n++,stu[i].num,stu[i].score);

printf("按任意键加回车返回主菜单!");

scanf("%d",&x);

getchar();

}

void pagedis()

{

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

printf("                   *                                *\n");

printf("                   *                                *\n");

printf("                   *                                *\n");

printf("                   *     欢迎进入学生信息管理系统   *\n");

printf("                   *                                *\n");

printf("                   *                                *\n");

printf("                   *                                *\n");

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

}

void check()

{

char userName[5];/*用户名*/

char userPWD[5];/*密码*/

int i,sum;

system("color 4E");

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

{

/*用户名和密码均为abcde;*/

printf("   用户名和密码均为abcde\n\n");

printf("\n       请输入您的用户名:");

gets(userName);

printf("\n       请输入您的密码:");

gets(userPWD);

if ((strcmp(userName,"abcde")==0) && (strcmp(userPWD,"abcde")==0))/*验证用户名和密码*/

{

printf("用户名和密码正确,显示主菜单");

return;

}

else

{

if (i < 3)

{

printf("用户名或密码错误,提示用户重新输入");

printf("用户名或密码错误,请重新输入!");

}

else

{

printf("连续3次输错用户名或密码,退出系统。");

printf("您已连续3次将用户名或密码输错,系统将退出!");

exit(1);

}

}

}

}

void menu()

{

STUDENTS stu[20];

int choice,k,sum;

sum=read_file(stu);

if(sum==0)

{  printf("首先录入基本库存信息!按回车后进入*****\n");

getch();

sum=input(stu);

}

do

{  system("cls");

printf("\n\n\n               ********学生信息管理系统********\n\n");

printf("                      1. 创建学生信息\n\n");

printf("                      2. 打印学生信息\n\n");

printf("                      3. 查询学生信息\n\n");

printf("                      4. 修改学生信息\n\n");

printf("                      5. 删除学生信息\n\n");

printf("                      6. 学生成绩信息排名\n\n");

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

printf("                       请选择(0-6):");

scanf("%d",&choice);

switch(choice)

{

case 1: k=input(stu); break;/*创建学生信息*/

case 2: output( stu) ; break;/*打印学生信息*/

case 3: inquire(stu); break;/*查询学生信息*/

case 4: change(stu); break;/*修改学生信息*/

case 5: deletel(stu); break;/*删除学生信息*/

case 6: sort(stu); break;/*学生成绩信息排名*/

case 0: break;

}

}while(choice!=0);

save_file(stu,sum);

}

int main()

{

int i,sum;

pagedis();

check();

menu();

}

七、心得体会

在整个课程设计和实验写作过程中,我改变了以前以前书写代码的一些习惯,让自己所开发的软件能更多的贴切生活,自己从网上查阅资料和搜集相关资料,不仅增强了自学能力同时还增强了动手能力,是我学习方法上的一个较大的突破。在以往的学习过程式中,我们会记住很多的理论知识,但是通过课程设计,我们学会了怎么处理理论和实践相结合的问题。

本系统的使用则更为人性化、简单化,只要操作人员能掌握基本的Windows系统操作、学会上网,就可以轻松掌握该系统的使用方法。所有的数据服务均在服务器上完成。只要服务器不出问题,所有数据和操作的安全性、可靠性是令人满意的。该系统的实施和推广有望大大降低当前许多学校教务管理的繁杂任务,提高工作效率。

当然,学生信息管理系统是一个比较庞大的系统,如果要实现整个学校的事务纯粹自动化管理,所牵涉的模块还有太多太多,我在本系统里面,只是实现了许多的基本功能,还有许多的管理功能,如:图书馆的借阅管理和学生的学籍等信息进行挂钩、教师的信息还应牵涉到级别薪酬的考核等功能,都是在本次开发中还未能实现的功能,只能在后续的开发中逐步实现。

时间: 2024-10-14 07:20:42

C语言指针和链表的体会的相关文章

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

1:指针是一个地址,指向的是个类型: 我们知道,c语言中的类型有int,char,bool(这个不常用),一般我们使用int,char就可以满足一般的类型需求的,如果对于变量的长度过大,就是用long ,float,double,关于各个类型使用的的长度问题,可以使用sizeof(int)或者sizeof(long)来查看各个类型,在系统中的小. 2:指针指向的是地址,地址指向的是内容: 我们需要一个变量,来存储地址,这个变量的值是地址,但是我们可以通过修改变量的值,来不断的改变地址,但是,我们

就C语言的指针、链表的原理和各类操作撰写一篇技术博客,说说自己学习C语言指针和链表的体会

一.指向结构体变量的指针变量 指向结构体变量的指针变量的定义形式与一般指针变量的定义形式相同,只是将其指向类型定义为结构体类型即可.例如:        struct person            { charname[20];             char sex;             int age;             float height;            };       struct person *p;则指针变量p,它可以指向struct person类

C语言课程设计第三节课:指针和链表使用 &#160; &nbsp; 150809205

一.学习体会 C语言的难点就是指针,学习的时候感觉指针的难点在于与其相关的技术和方法很多,所以学习              的时候并不能像前边一样一个知识点一道题就明白了. 二.以下是我对指针原理的理解 指针通常指向一片储存空间,而开辟的储存空间地址为指针的量 1.指针与数组 数组开辟的是一段连续的内存空间,而指针则是单一特定内存地址,因此两者不可互相转换. 数组变量可以赋值给指针(即将数组第一个变量的地址赋予指针). 2.动态内存分配与静态内存分配 (1)动态内存分配 根据程序的需要开辟空间

C语言的指针、链表的原理及学生管理系统

指针原理: 指针就是指向一个特定内存地址的一个变量.简化了的内存空间模型是按照从0到某一个数(比如1048575=1M-1)的一维线性空间,其中的每一个数对应一个存储单元,即1个字节.指针有两个属性:指向性和偏移性.指向性指的是指针一定要有一个确定的指向,偏移性则是体现指针重要应用的方面,即指针可以按程序员的要求向前或向后偏移. 指针的应用往往与数组联系在一起,为了方便说明问题,不妨从数组开始解释指针的偏移.数组就是许多的变量,它的一个重要特征就是在内存空间中连续地存放,而且是按下标顺序存放.比

关于C语言的指针、链表的原理和各类操作

今天课上我们老师为我们讲述了c语言的指针.链表的原理以及各类操作. 一.指针 1.指针 指针是一个存储计算机内存地址的变量.从指针指向的内存读取数据称作指针的取值.指针可以指向某些具体类型的变量地址,例如int.long和double.指针也可以是void类型.NULL指针和未初始化指针.指针是一个存储计算机内存地址的变量.从指针指向的内存读取数据称作指针的取值.指针可以指向某些具体类型的变量地址,例如int.long和double.指针也可以是void类型.NULL指针和未初始化指针. 2.数

彭界博-个指针与链表

1.指针与数组 指针通常指向一片储存空间,而开辟的储存空间地址为指针的量:数组开辟的是一段连续的内存空间,而指针则是单一特定内存地址,因此两者不可互相转换. 数组变量可以赋值给指针(即将数组第一个变量的地址赋予指针). 2.动态内存分配与静态内存分配 (1)动态内存分配 根据程序的需要开辟空间,不需要预先分配,智能自动,可以根据需要增大或减小. (2)静态内存分配 即预先分配好储存空间,缺点显而易见,需要预先知道数据的大小,修改数据的时候需要更改已经分配好的储存空间,浪费内存等. (3)函数 v

指针、链表的原理和各类操作相关心得以及学生信息管理系统

伴随着学期末的到来,C语言程序设计这门课也接近尾声.经过前两次的教学,我们对C语言也有了深刻的了解,学习的内容也不断的加深.这次我们就学习了C语言程序设计里应用最广泛,也是最难学习的知识--链表和指针的应用. 关于指针和链表这两个的应用和上次的管理系统有着直接的关系,没有添加链表和指针的管理系统无法做到精确的查找.数据存储方面也显得不方便.所以指针和链表的作用能够直接指向你所需要的数据地址,使程序更加完善.这次我就利用指针的应用制作了一个管理员工工资等信息的程序. §1 指向结构体变量的指针变量

使用C语言描述静态链表和动态链表

静态链表和动态链表是线性表链式存储结构的两种不同的表示方式. 静态链表的初始长度一般是固定的,在做插入和删除操作时不需要移动元素,仅需修改指针,故仍具有链式存储结构的主要优点. 动态链表是相对于静态链表而言的,一般地,在描述线性表的链式存储结构时如果没有特别说明即默认描述的是动态链表. 下面给出它们的简单实现,关于线性表更为详尽的C语言的实现,可以参考 http://www.cnblogs.com/choon/p/3876606.html 静态链表 #define _CRT_SECURE_NO_

数据结构C语言实现——线性链表

declaration.h #ifndef DECLARATION_H_INCLUDED #define DECLARATION_H_INCLUDED #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 #define ElemType int typedef ElemType* Triplet; typedef int Status; type