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系統操作、學會上網,就可以輕松掌握該系統的使用方法。所有的數據服務均在服務器上完成。只要服務器不出問題,所有數據和操作的安全性、可靠性是令人滿意的。該系統的實施和推廣有望大大降低當前許多學校教務管理的繁雜任務,提高工作效率。
? ? 當然,學生信息管理系統是一個比較龐大的系統,如果要實現整個學校的事務純粹自動化管理,所牽涉的模塊還有太多太多,我在本系統里面,只是實現了許多的基本功能,還有許多的管理功能,如:圖書館的借閱管理和學生的學籍等信息進行掛鉤、教師的信息還應牽涉到級別薪酬的考核等功能,都是在本次開發中還未能實現的功能,只能在后續的開發中逐步實現。
?
轉載于:https://blog.51cto.com/11639639/1788853
總結
以上是生活随笔為你收集整理的C语言指针和链表的体会的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 11.使用ForwardAction实现
- 下一篇: MEF学习1