第一節 結構體變量
-
什麼是結構體?
將多種數據類型結合構建在一起的數據類型稱爲
結構體類型
;需要多個數據類型來表示某一信息時,可以使用結構體。例如學生李四和趙六參加比賽需要在網絡上填寫信息包含:存在不同的數據類型
name:lisi, age:23, sex:M, student_number:20193055; name:zhaoliu, age:22, sex:M, student_number:20193091;
代碼示例:
#include <stdio.h> struct test { char name[30]; int age; char sex; int student_number; }; int main() { struct test lisi , zhaoliu; printf("請輸入學生的姓名 年齡 性別 學號:"); scanf("%s %d %c %d",lisi.name,&lisi.age,&lisi.sex,&lisi.student_number); printf("參加比賽的學生有%s\t年齡:%d\t性別:%c\t學號:%d\n",lisi.name,lisi.age,lisi.sex,lisi.student_number); printf("請輸入學生的姓名 年齡 性別 學號:"); scanf("%s %d %c %d",zhaoliu.name,&zhaoliu.age,&zhaoliu.sex,&zhaoliu.student_number); printf("參加比賽的學生有%s\t年齡:%d\t性別:%c\t學號:%d\n",zhaoliu.name,zhaoliu.age,zhaoliu.sex,zhaoliu.student_number); return 0; }
-
創建結構體類型:
結構體類型的創建方法:
struct 結構體名{ 類型名 成員表列1; 類型名 成員表列2; ··· };
說明:
-
創建結構體類型是指創建的數據類型;
-
結構體名是指對應創建的數據類型名,例如之前學習的int型、float型,其中int和float是數據類型名;
-
成員表列可以包含多個同類型及不同類型的數據,每個成員以
;
分隔。結構體的花括號{}
之後有一個;
-
成員也可以是另一個結構體類型。
代碼示例:
struct score { int shuxue; int yuwen; int zhengzhi; char tiyu; }; struct test { char name[30]; int age; char sex; int student_number; struct score gaokao; };
-
-
定義結構體變量
在沒有定義結構體之前,系統不會分配存儲空間。爲了使用結構體變量,需要在使用之前進行定義。
-
先創建結構體類型,再定義。
在文件的開頭創建好結構體類型,然後在函數中使用定義結構體變量。定義的方法爲:
struct 結構體名 結構體變量名 //例如: struct test lisi;
代碼示例:
#include <stdio.h> struct test { char name[30]; int age; char sex; int student_number; }; int main() { struct test lisi , zhaoliu; printf("請輸入學生的姓名 年齡 性別 學號:"); scanf("%s %d %c %d",lisi.name,&lisi.age,&lisi.sex,&lisi.student_number); printf("參加比賽的學生有%s\t年齡:%d\t性別:%c\t學號:%d\n",lisi.name,lisi.age,lisi.sex,lisi.student_number); printf("請輸入學生的姓名 年齡 性別 學號:"); scanf("%s %d %c %d",zhaoliu.name,&zhaoliu.age,&zhaoliu.sex,&zhaoliu.student_number); printf("參加比賽的學生有%s\t年齡:%d\t性別:%c\t學號:%d\n",zhaoliu.name,zhaoliu.age,zhaoliu.sex,zhaoliu.student_number); return 0; }
-
在創建結構體類型的同時進行定義。
說明:結構體成員表名在結構體內唯一,但可以和其他變量名相同。
struct 結構體名 { 類型名 成員表列1 類型名 成員表列2 ··· }變量名錶列;
代碼示例:
#include <stdio.h> int main() { struct test { char name[30]; int age; char sex; int student_number; }lisi,zhaoliu; printf("請輸入學生的姓名 年齡 性別 學號:"); scanf("%s %d %c %d",lisi.name,&lisi.age,&lisi.sex,&lisi.student_number); printf("參加比賽的學生有%s\t年齡:%d\t性別:%c\t學號:%d\n",lisi.name,lisi.age,lisi.sex,lisi.student_number); printf("請輸入學生的姓名 年齡 性別 學號:"); scanf("%s %d %c %d",zhaoliu.name,&zhaoliu.age,&zhaoliu.sex,&zhaoliu.student_number); printf("參加比賽的學生有%s\t年齡:%d\t性別:%c\t學號:%d\n",zhaoliu.name,zhaoliu.age,zhaoliu.sex,zhaoliu.student_number); return 0; }
-
不指定結構體名而直接定義。
struct { 類型名 成員表列1 類型名 成員表列2 ··· }變量名錶列;
代碼示例:
#include <stdio.h> int main() { struct { char name[30]; int age; char sex; int student_number; }lisi,zhaoliu; printf("請輸入學生的姓名 年齡 性別 學號:"); scanf("%s %d %c %d",lisi.name,&lisi.age,&lisi.sex,&lisi.student_number); printf("參加比賽的學生有%s\t年齡:%d\t性別:%c\t學號:%d\n",lisi.name,lisi.age,lisi.sex,lisi.student_number); printf("請輸入學生的姓名 年齡 性別 學號:"); scanf("%s %d %c %d",zhaoliu.name,&zhaoliu.age,&zhaoliu.sex,&zhaoliu.student_number); printf("參加比賽的學生有%s\t年齡:%d\t性別:%c\t學號:%d\n",zhaoliu.name,zhaoliu.age,zhaoliu.sex,zhaoliu.student_number); return 0; }
-
-
結構體變量的使用:
- 使用結構體變量成員的方法:
結構體變量名.成員名
- 當成員又是一個結構體時,使用對應結構體的方法:
結構體變量名.成員名.成員名
- 當在輸入
.
時,visual C++能自動識別出對應結構體中所包含的成員 - 同類的結構體變量可以互相賦值,例如
lisi = zhaoliu
- 使用結構體變量成員的方法:
第二節 結構體數組
-
可以定義int、char、float等類型的數組;也可以爲結構體定義數組,表示一次性開闢多個結構體空間。
-
結構體數組定義的方法:
-
創建的結構體類型之後,再定義結構體數組:
結構體類型 數組名[數組個數]
代碼示例:
#include <stdio.h> struct test { char name[30]; int age; char sex; int student_number; }; int main() { struct test class_five[10]; //定義了一個test類型的結構體數組,數組名爲class_five,包含10個結構體 return 0; }
-
創建結構體類型的同時定義結構體數組:
struct 結構體名 { 類型名 成員表列1 類型名 成員表列2 ··· }變量名錶列;
代碼示例:
#include <stdio.h> int main() { struct test { char name[30]; int age; char sex; int student_number; }class_five[10]; //定義了一個test類型的結構體數組,數組名爲class_five,包含10個結構體 return 0; }
實例:投票系統,爲無憂村選舉1名村長,預備村長有張三、李四、王五,村中一共有10名村民
#include <string.h> #include <stdio.h> int main() { struct piaoshu { char name[3]; int number; }ybcz[3] = {"zs",0,"ls",0,"ww",0}; // ybcz[0].name = "zs",ybcz[0].number =0;ybcz[1].name = "ls",ybcz[0].number =0;ybcz[0].name = "ww",ybcz[0].number =0; int i,j ; char name[3]; for(i = 0;i <10;i++) { printf("請投票:"); scanf("%s",name); for(j = 0 ; j <3; j++) if(strcmp(ybcz[j].name, name) == 0) ybcz[j].number++; } for(i = 0;i<3;i++) printf("村名:%s\t的票數是:%d\n",ybcz[i].name,ybcz[i].number); return 0; }
-
第三節 結構體指針
-
什麼是結構體指針?
一個結構體變量的起始地址就是結構體變量的指針。用一個指針變量存儲結構體指針就是一個結構體指針變量。
struct 結構體名 { 類型名 成員表列1; 類型名 成員表列2; ··· }lisi;
-
指針指向結構體變量的使用
指向結構體成員的方法:
(*p).name (*p).age p -> name p -> age p -> student_number
其中
*p
表達指向對應地址的內容,(*p)
加上括號是由於.
的優先級高於*
。->
表示指向運算符。代碼示例:
#include <string.h> #include <stdio.h> int main() { struct test { char name[30]; int age; char sex; int student_number; }lisi ={"lisi",32,'M',20190305}; struct test *p; p = &lisi; strcpy((*p).name,"caojiu"); (*p).age = 28; printf("姓名:%s\t年齡:%d\t性別%d\t學號:%d\n",p->name, p->age,p->sex,p->student_number); return 0; }
-
指針指向結構體數組
struct test { 類型名 成員表列1; 類型名 成員表列2; ··· }student[3];
代碼示例:
#include <stdio.h> int main() { struct test { char name[30]; int age; char sex; int student_number; }student[3]; struct test *p; for(p = student;p< student+3; p++) { printf("請輸入姓名 年齡 性別 學號:"); scanf("%s %d %c %d",p->name,&(p->age),&(p->sex),&(p->student_number)); } for(p = student;p< student+3;p++) printf("姓名:%s\t年齡:%d\t性別%d\t學號:%d\n",p->name, p->age,p->sex,p->student_number); return 0; }
-
結構體與函數傳遞
- 結構體中的成員作爲實參傳遞,和變量的使用方法一致;
- 結構體變量作爲實參傳遞,由於形參接收實參時,也會在內存中開闢一個行同大小的空間,並且形參內容改變時,對應實參的內容不會被改變,因此這種傳遞方式不僅浪費空間,也不利於操作,一般不使用;
- 當結構體指針變量作爲實參傳遞時,將指針地址賦值給形參。
代碼示例:
#include <string.h> #iunclude <stdio.h> struct test { char name[30]; int age; char sex; int student_number; }; void change_info(char name[30],struct test *q) { printf("修改%s的信息\n",name); printf("修改爲姓名 年齡 性別 學號:"); scanf("%s %d %c %d",q->name,&(q->age),&(q->sex),&(q->student_number)); } int main() { struct test lisi, *p = &lisi; strcpy(lisi.name,"lisi"); change_info(lisi.name,p ); printf("姓名:%s\t年齡:%d\t性別%d\t學號:%d\n",p->name, p->age,p->sex,p->student_number); return 0; }
第四節 按需分配的空間
創建一個數據,在以前使用int、char、數組、結構體等來創建都是必須在使用之前給出固定的空間長度,但是大部分數據在使用之前是沒有辦法確定的,例如統計每天上網的網名,這一類的人數是一個動態的數據。
-
如何創建一個按需分配的空間?
鏈表
可以實現存儲空間動態分配的一種結構。它不是數據,而是通過代碼人爲的創建出一種空間動態分配方法。NULL表示指針的內容爲空,void表示數據類型爲空。
- 由一個“頭指針”變量存放鏈表中的第一個表;
- 每一個表包含實際的數據和下一個表的地址;
- 每個表的存儲地址都是由系統分配的不連續的存儲空間。
代碼示例:
struct test { char name[30]; int age; int student_number; struct test *next; //指向struct test類型數據的指針。 };
-
創建一個簡單鏈表
代碼示例:
#include <stdio.h> #include <string.h> #include <stdlib.h> struct test { char name[30]; int age; int student_number; struct test *next; //指向struct test類型數據的指針。 }; int main() { struct test a,b,c, *head,*p; strcpy(a.name,"zhangsan"); //給各個結構體賦值 a.age = 16; a.student_number = 1001; strcpy(b.name,"lisi"); b.age = 19; b.student_number = 1102; strcpy(c.name,"wangwu"); c.age = 18; c.student_number = 1009; head =&a; //把3個結構體構建成鏈表 a.next = &b; b.next = &c; c.next = NULL; p = head; while(p!= NULL) //輸出鏈表內容 { printf("%d\n",p); printf("姓名:%s\t年齡:%d\t學號:%d\n",p->name,p->age,p->student_number); p = p->next; } return 0; }
-
創建動態鏈表
代碼示例:
#include <stdio.h> #include <string.h> #include <stdlib.h> struct test { char name[30]; int age; int student_number; struct test *next; //指向struct test類型數據的指針。 }; int main() { struct test *head, *p1,*p2; int n = 0; p1 = p2 = malloc(sizeof(struct test)); //添加第一個表的內容 printf("請輸入姓名 年齡 學號:"); scanf("%s %d %d",p1->name,&p1->age,&p1->student_number); head = NULL; while(p1->student_number > 0) { n = n+1; // n =3 if(n == 1) head = p1; //創建鏈表 else p2->next = p1; p2 = p1; p1 = malloc(sizeof(struct test)); //循環添加表的內容 printf("請輸入姓名 年齡 學號:"); scanf("%s %d %d",p1->name,&p1->age,&p1->student_number); } p2->next = NULL; p1 = head; while(p1 != NULL) //檢查鏈表是否有內容,如果有內容就打印輸出 { printf("姓名:%s\t年齡:%d\t學號:%d\n",p1->name,p1->age,p1->student_number); p1 = p1->next; } return 0; }
第五節 共用體
-
什麼是共用體?
多種不同的變量共用同一段內存的結構,稱爲共用體的結構。
例如在內存中開闢了4個字節的空間,可以用來存儲int、float、char型數據,構建一種數據類型,使得開闢的空間可以存放幾種不同類型的數據,但在使用的一瞬間只能存放一個數據,而不是同時存放多個數據。
-
創建共用體類型:
union 共用體名 { 類型名 成員表列1; 類型名 成員表列2; ··· 類型名 成員表列n; };
-
定義共用體變量的方法:
union 共用體名 變量名
-
在定義之前已經創建好共用體類型時,結構體變量所佔內存大小是成員中佔內存最大的那個;
-
union 共用體名 { 類型名 成員表列1; 類型名 成員表列2; ··· 類型名 成員表列n; }
代碼示例:
#include <stdio.h> union info { int a; char b; float c; }; int main() { union info x; //佔內存4字節 x.a = 100; printf("%d\t%c\t%f\n",x.a,x.b,x.c); return 0; }
-
-
共用體變量的使用方法:
注:使用共用體之前需要定義。
例如:定義了共同體變量x
x.a //引用共用體變量中的整型變量a x.b //引用共用體變量中的字符變量b x.c //引用共用體變量中的浮點型變量c
說明:
1. 共用體初始化時,只能存儲一個數據,不能同時存儲多個數據; 2. 對共用體變量非同時的進行多次賦值在,則共用體變量中的數據是最近一次賦值的數據; 3. 共用體的成員都使用相同的地址; 4. 同類型的共用體變量可以相互賦值 `y = x;`
代碼示例:
#include <stdio.h> int main() { union info { int a; char b; float c; }x={100}; x.c = 3.14f; x.b = 'y'; //ASCII碼後部分是成員c遺留的 printf("%d\t%c\t%f\n",x.a,x.b,x.c); printf("%d\t%d\t%d\n",&x.a,&x.b,&x.c); return 0; }
實例:填寫公司員工信息
#include <stdio.h> struct info //一般配合struct,上節課的鏈表一般在處理大型數據的時候使用 { char name[20]; int age; char work; union { int gzsc; char xueli[10]; }fen; }; int main() { struct info a[2]; int i; for(i = 0; i <2; ++i) { printf("請填寫入職信息:姓名 年齡 職務[c表示程序員,s表示設計師]\n"); scanf("%s %d %c",a[i].name,&a[i].age,&a[i].work); if(a[i].work == 's') { printf("請輸入您工作時長:"); scanf("%d",&a[i].fen.gzsc); } else { printf("請輸入您的學歷:"); scanf("%s",a[i].fen.xueli); } } for(i = 0; i <2 ; ++i) { if(a[i].work == 's') printf("姓名:%s\t年齡%d\t職務:%c\t工作時長:%d\n",a[i].name,a[i].age,a[i].work,a[i].fen.gzsc); else printf("姓名:%s\t年齡%d\t職務:%c\t學歷:%s\n",a[i].name,a[i].age,a[i].work,a[i].fen.xueli); } return 0; }
-
第六節 枚舉
如果一個變量只有幾種可能的值,則可以使用枚舉
的方法定義數據類型。
-
什麼是枚舉
枚舉是將一個變量所有可能的值一一列舉出來,對應的值只能是列舉出來的值中的一個,例如猜丁殼的遊戲裏面,只有石頭剪刀布這三種。
-
如何構建枚舉類型
enum 枚舉類型名 { 值1, 值2, ···, 值n } //enum cdk{shitou, jiandao, bu}
-
定義枚舉變量
enum cdk a, b //其中a和b分別爲cdk類型的數據,且a,b的值只能是shitou, jiandao, bu
說明:枚舉元素(shitou, jiandao, bu)都代表一個整數,元素值的默認順序爲0,1,2,3, ···,也可以人爲修改元素值。
第七節 替換類型名
可以使用typedef
將已有的類型名進行替換。
-
typedef
替換類型名的方式:按定義變量的方式,將變量名替換爲需要的類型名,並在最開頭寫上typedef
。typedef int ii[100]; //int a[100];創建一個類型代表數組 typedef char cc[30]; //char s[30]; typedef char *zhi; //char *p; ii a; cc s; zhi p;