一、建立結構體
用戶自己建立由不同類型數據組成的組合型的數據結構,它稱為結構體。
struct Student
{ int num; //學號char name[20]; //名字為字符串char sex; //性別int age; //年紀float score; //分數char addr[30]; 地址為字符串
}; //注意最后有分號
可以看到先是指定一個結構體類型? struct Student (struct 是聲明, 結構體類型時候必須壓迫使用的關鍵字,不能省略!!!!),它向編譯系統聲明:這是一個“結構體類型”,它包括num,name,sex,age,score,addr等不同類型成員。
所以一般形式為:
struct 結構體名
{
?成員列表
} ;? ? ? ? ? ? //別忘了分號
花括號里的成員列表:? 類型名? 成員名;
二、定義一個結構體變量
開頭聲明的Student 結構體,可以用它來定義變量。?
1.先聲明結構體,再定義變量。
例如:? struct Student? student1 , student2;
這樣student1和student2就具有和Student類型的結構了。
2.在聲明類型的同時定義變量
struct Student
{ int num; //學號char name[20]; //名字為字符串char sex; //性別int age; //年紀float score; //分數char addr[30]; 地址為字符串
}student1,student2;
引用結構體變量:?student1.age=23;
三、結構體數組
例題:有三個候選人,每個選民只能投票一個人,要求編寫一個統計選票程序,先輸入被選人的名字,最后輸出各人得票結果。
#include <stdio.h>
#include <string.h>struct Person{ // 聲明結構體類型char name[20]; //候選人姓名int count; //候選人得票數
}leader[3] = {"Li",0,"Zhang",0,"Sun",0}; //定義結構體數組并且初始化int main(){int i,j;char leader_name[20]; //定義字符數組for(i=1;i<=10;i++){scanf("%s",leader_name); //輸入所選的候選人姓名for(j=0;j<3;j++){if(strcmp(leader_name,leader[j].name)==0)leader[j].count++;} //strcmp 是比較字符串的意思,字符串不相等則輸出0}printf("\nResult:\n");for(i=0;i<3;i++)printf("%5s:%d\n",leader[i].name,leader[i].count);return 0;
}
結果:
Li
Zhang
Sun
Zhang
Li
Zhang
Sun
Zhang
Li
ZhangResult:Li:3
Zhang:5Sun:2
?首先定義了一個全局的結構體數組leader,它有三個元素,每個元素包含兩個成員name和count。
再定義數組時使之初始化,將“Li”賦給leader[0].name , 0賦給leader[0].count,"Zhang"賦給leader[1].name , 0賦給leader[1].count。......這三個候選人的票數全部先置0。
所以定義結構體數組的一般形式為:
struct 結構體名{
成員列表
}數組名[數組長度]//還可以:結構體類型 數組名[數組長度];struct Person leader[3];
四、結構體指針
1.指向結構體變量的指針
例題:通過指向結構體變量的指針變量輸出結構體變量中成員的信息。
#include <stdio.h>
#include <string.h>int main(){struct Student{long num;char name[20];char sex;float score;}; struct Student stu_1; //定義struct Student類型變量stu_1 struct Student *p; //定義指向struct Student類型數據的指針變量p p = &stu_1; //p指向stu_1 stu_1.num = 10101; //對結構體變量的成員賦值 strcpy(stu_1.name,"Li Lin"); //用字符串賦值函數給stu_1.name賦值 stu_1.sex= 'M';stu_1.score = 89.5;printf("No.:%ld\nname:%s\nsex:%c\nscore:%5.1f\n",stu_1.num,stu_1.name,stu_1.sex,stu_1.score) ;printf("\nNo.:%ld\nname:%s\nsex:%c\nscore:%5.1f\n",(*p).num,(*p).name,(*p).sex,(*p).score) ;return 0;
}
結果:
No.:10101
name:Li Lin
sex:M
score: 89.5No.:10101
name:Li Lin
sex:M
score: 89.5
分析:將結構體變量stu_1的起始地址賦給指針變量p,也就是使p指向stu_1,然后對stu_1的各個成員賦值。
??:為了方便,(*p).num? 可以用p->num 代替
2.指向結構體數組的指針
例題:有三個學生的信息,放在結構體數組里,要求輸出全部學生的信息。
#include <stdio.h>struct Student{int num;char name[20];char sex;int age;
};
struct Student stu[3]={
{10101,"Li Lin",'M',18},{10102,"Zhang Fang",'M',19},{10104,"Wang Min",'F',20}
};
int main(){
struct Student *p;
printf(" No. Name sex age\n");
for(p=stu;p<stu+3;p++)printf("%5d %-20s %2c %4d\n",p->num,p->name,p->sex,p->age) ;return 0;
}
結果:
No. Name sex age
10101 Li Lin M 18
10102 Zhang Fang M 19
10104 Wang Min F 20
分析:在for循環里面,首先條件是先讓p=stu,也就是stu中序號為0的元素的起始地址,第一次循環輸出stu[0]的各個成員的置。然后執行p++,使p自加1。此時p的值就等于stu+1。指向了stu[1]了。
五、用指針處理鏈表
1.什么是鏈表?
一種線性數據結構,它由一系列節點(Node)組成,這些節點通過指針(或引用)連接成一個鏈條。與數組不同,鏈表的節點在內存中不需要連續存儲,數據的邏輯順序通過節點之間的指針來維持。
鏈表有一個”頭指針“變量,圖中是head表示,它存放著一個地址,該地址指向一個元素。鏈表中每個元素稱為”節點“。可以看到head指向第一個元素,第一個元素有指向第二個元素......直到最后一個元素,該元素不在指向其它元素,它稱為”表尾“,它的地址部分放一個“NULL”,表示空地址,鏈表到此結束。
節點至少包含兩部分:
數據域:存儲具體的數據值(如整數、字符串等)。
指針域:存儲下一個節點的內存地址(或引用),用于連接節點。
??:鏈表中各個元素的地址可以不連續,要找到某個元素,必須找到上一個元素,根據它提供的下一個元素地址才能找到下一個元素。如果不提供“頭指針”則整個鏈表都無法訪問。鏈表如同一條鐵鏈一樣。一環扣一環,中間無法斷開。
打個比方:幼兒園老師帶領孩子出來散步,老師牽著第一個孩子的手,第一個孩子牽著第二個孩子的手,......,最后一個孩子有一只手是空的,他是鏈尾。
2.建立簡單的靜態鏈表
例題:建立一個簡單的靜態鏈表,它由3個學生數據的節點組成,要求輸出個節點中的數據
#include <stdio.h>// 定義學生結構體
struct Student {int num; // 學號float score; // 分數struct Student *next; // 指向下一個節點的指針
};int main() {// 定義三個學生節點并初始化數據struct Student s1 = {101, 85.5, NULL};struct Student s2 = {102, 90.0, NULL};struct Student s3 = {103, 78.2, NULL};// 建立鏈表連接關系s1.next = &s2;s2.next = &s3;s3.next = NULL; // 尾節點指針置為NULL// 定義指針指向頭節點struct Student *ptr = &s1;// 使用do-while循環遍歷鏈表并輸出數據do {printf("學號: %d, 分數: %.1f\n", ptr->num, ptr->score);ptr = ptr->next; // 移動到下一個節點} while (ptr != NULL); // 當指針不為NULL時繼續循環return 0;
}
輸出結果:
學號: 101, 分數: 85.5
學號: 102, 分數: 90.0
學號: 103, 分數: 78.2
所有節點都是在程序中定義的,不是臨時開辟的,也不能用完之后釋放,這種鏈表稱為“靜態鏈表”