第八章 結構體和共用體

第一節 結構體變量

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-QWnVF4da-1590563693386)(E:\workspace\TyporaProjects\C筆記\網易-C程序設計第四版\images\第八章\8-1.png)]

  • 什麼是結構體?

    將多種數據類型結合構建在一起的數據類型稱爲結構體類型;需要多個數據類型來表示某一信息時,可以使用結構體。

    例如學生李四和趙六參加比賽需要在網絡上填寫信息包含:存在不同的數據類型

    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;
            ···
    };

    說明:

    1. 創建結構體類型是指創建的數據類型;

    2. 結構體名是指對應創建的數據類型名,例如之前學習的int型、float型,其中int和float是數據類型名;

    3. 成員表列可以包含多個同類型及不同類型的數據,每個成員以;分隔。結構體的花括號{}之後有一個;

    4. 成員也可以是另一個結構體類型。

    代碼示例:

    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;
    };
  • 定義結構體變量

    在沒有定義結構體之前,系統不會分配存儲空間。爲了使用結構體變量,需要在使用之前進行定義。

    1. 先創建結構體類型,再定義。

      在文件的開頭創建好結構體類型,然後在函數中使用定義結構體變量。定義的方法爲:

      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;
      }

      [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-25LXa5Ga-1590563693389)(E:\workspace\TyporaProjects\C筆記\網易-C程序設計第四版\images\第八章\8-2.png)]

    2. 在創建結構體類型的同時進行定義。

      說明:結構體成員表名在結構體內唯一,但可以和其他變量名相同。

      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;
      }
    3. 不指定結構體名而直接定義。

      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;
      }
  • 結構體變量的使用:

    1. 使用結構體變量成員的方法:結構體變量名.成員名
    2. 當成員又是一個結構體時,使用對應結構體的方法:結構體變量名.成員名.成員名
    3. 當在輸入.時,visual C++能自動識別出對應結構體中所包含的成員
    4. 同類的結構體變量可以互相賦值,例如lisi = zhaoliu

第二節 結構體數組

  • 可以定義int、char、float等類型的數組;也可以爲結構體定義數組,表示一次性開闢多個結構體空間。

  • 結構體數組定義的方法:

    1. 創建的結構體類型之後,再定義結構體數組:結構體類型 數組名[數組個數]

      代碼示例:

      #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;
      }
    2. 創建結構體類型的同時定義結構體數組:

      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;

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-XkGfX0Yp-1590563693391)(E:\workspace\TyporaProjects\C筆記\網易-C程序設計第四版\images\第八章\8-3.png)]

  • 指針指向結構體變量的使用

    指向結構體成員的方法:

    (*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];

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-RPmAHn6L-1590563693391)(E:\workspace\TyporaProjects\C筆記\網易-C程序設計第四版\images\第八章\8-3-2.png)]

    代碼示例:

    #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;
    }
  • 結構體與函數傳遞

    1. 結構體中的成員作爲實參傳遞,和變量的使用方法一致;
    2. 結構體變量作爲實參傳遞,由於形參接收實參時,也會在內存中開闢一個行同大小的空間,並且形參內容改變時,對應實參的內容不會被改變,因此這種傳遞方式不僅浪費空間,也不利於操作,一般不使用;
    3. 當結構體指針變量作爲實參傳遞時,將指針地址賦值給形參。

    代碼示例:

    #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、數組、結構體等來創建都是必須在使用之前給出固定的空間長度,但是大部分數據在使用之前是沒有辦法確定的,例如統計每天上網的網名,這一類的人數是一個動態的數據。

  • 如何創建一個按需分配的空間?

    鏈表可以實現存儲空間動態分配的一種結構。它不是數據,而是通過代碼人爲的創建出一種空間動態分配方法。

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-7J4O9WyO-1590563693393)(E:\workspace\TyporaProjects\C筆記\網易-C程序設計第四版\images\第八章\8-4-1.png)]

    NULL表示指針的內容爲空,void表示數據類型爲空。

    1. 由一個“頭指針”變量存放鏈表中的第一個表;
    2. 每一個表包含實際的數據和下一個表的地址;
    3. 每個表的存儲地址都是由系統分配的不連續的存儲空間。

    代碼示例:

    struct test
    {
    	char name[30];
    	int age; 
    	int student_number;
    	struct test *next;			//指向struct test類型數據的指針。
    };
    • 創建一個簡單鏈表

      [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-SlYUtoO8-1590563693395)(E:\workspace\TyporaProjects\C筆記\網易-C程序設計第四版\images\第八章\8-4-2.png)]

      代碼示例:

      #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;
      }
    • 創建動態鏈表

      [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-0Q2D6OVe-1590563693396)(E:\workspace\TyporaProjects\C筆記\網易-C程序設計第四版\images\第八章\8-4-3.png)]

      代碼示例:

      #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;
      }

第五節 共用體

  • 什麼是共用體?

    多種不同的變量共用同一段內存的結構,稱爲共用體的結構。

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2pxyaRcH-1590563693398)(E:\workspace\TyporaProjects\C筆記\網易-C程序設計第四版\images\第八章\8-4-5.png)]

    例如在內存中開闢了4個字節的空間,可以用來存儲int、float、char型數據,構建一種數據類型,使得開闢的空間可以存放幾種不同類型的數據,但在使用的一瞬間只能存放一個數據,而不是同時存放多個數據。

    • 創建共用體類型:

      union 共用體名 {
          類型名 成員表列1;
          類型名 成員表列2;
          	···
          類型名 成員表列n;
      };
    • 定義共用體變量的方法:

      union 共用體名 變量名

      1. 在定義之前已經創建好共用體類型時,結構體變量所佔內存大小是成員中佔內存最大的那個;

      2. 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;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章