1. 程式人生 > >C程式設計--結構體(結構體和函式之間的引數使用)

C程式設計--結構體(結構體和函式之間的引數使用)

結構體型別(掌握點):

  • 建立結構體型別
  • 定義結構體型別變數
  • 初始化結構體和引用結構體變數(3種方法,見下)
  • 使用結構體陣列
  • 結構體指標(重要)
    1. 指向結構體變數的指標
    2. 指向結構體陣列的指標

程式碼案例

#include<stdio.h>
#include<string.h>

//定義結構體

struct Student{
	long num;//學號為整型
	char name[20];//姓名為字串
	char sex;//性別為字元型
	int age;//年齡為整型
	float
score;//成績為實型 char addr[30];//地址為字串 }; //注意最後有一個分號 int main(){ //1.指向結構體變數的指標 struct Student stu; struct Student *p; p=&stu; stu.num=10101; //對結構體的變數成員賦值 strcpy(stu.name,"Micheal");//注意:不能寫成stu.name="Micheal"; 使用標頭檔案#include<string.h> stu.sex='M'; stu.score=89.5; //輸出結構體(3種方式) printf("(num)%ld (name)%s (sex)%c (score)%5.1f \n"
, stu.num,stu.name,stu.sex,stu.score); printf("(num)%ld (name)%s (sex)%c (score)%5.1f \n" , (*p).num,(*p).name,(*p).sex,(*p).score); printf("(num)%ld (name)%s (sex)%c (score)%5.1f \n\n" , p->num,p->name,p->sex,p->score); //2.指向結構體陣列的指標 struct Student stu1[3]={{1101,"Martin",'M',23,87.6f
,"China"},{1102,"Tom",'M',16,92.3f,"America"},{1103,"Susan",'F',35,78.4f,"India"}}; struct Student *p1; for(p1=stu1;p1<stu1+3;p1++){//注意使用方法 printf("(num)%ld (name)%s (sex)%c (score)%5.1f \n" , p1->num,p1->name,p1->sex,p1->score); } }
程式碼說明:
  1. (*p).num 表示p指向的結構體變數中的成員num。注意: *p 兩側的括號不能省,因為成員運算子 “ . ” 優先於“ * ”運算子,*p.num 就等價於 *(p.num);
  2. 如果p指向一個結構體變數stu,以下3種用法等價:
    ① stu.成員名(如:stu.num);
    ② (*p).成員名(如:(*p).num);
    ③ p->成員名(如:p->num);
  3. 對結構體成員變數:char name[20]; 的操作
    ①如果需要輸入結構體變數的值的時候,請注意:
    對stu.name的輸入方式為:scanf("%s",stu.name);//而不是scanf("%s",&stu.name);
    原因:name是陣列名,本身就代表地址;
    ②如果要對結構體成員變數賦值時,請注意:
    對stu.name的賦值方式為:strcpy(stu.name,“Micheal”);//而不是 stu.name = “Micheal”;且注意新增標頭檔案 #include<string.h>
執行結果

在這裡插入圖片描述

結構體和函式之間的引數使用(重點+難點)

  1. 結構體變數成員 作實參(例如:stu[1].num):屬於“值傳遞”方式,注意實參和形參的型別保持一致。
  2. 結構體變數作實參(例如:stu):屬於“值傳遞”方式,形參必須是與實參同類型的結構體變數。
    缺點:①這種傳遞方式在空間和時間上開銷比較大;②在被呼叫函式期間改變了形參,並不能改變主函式中的實參值。
  3. 指向結構體變數(或陣列元素)的指標作實參,將結構體變數(或陣列元素)的地址傳給形參。
案例

有n個結構體變數,內含學生學號、姓名和3門課程的成績。要求輸出平均成績最高的學生資訊(包括學號、姓名、3門課成績和平均成績)。

程式實現
#include<stdio.h>
#include<string.h>
#define N 3

//定義結構體
struct Student{
	long num;//學號為整型
	char name[20];//姓名為字串
	float score[3];//成績為實型
	float  aver;//平均成績
};	//注意最後有一個分號

int main(){
	//函式宣告
	void input(struct Student stu[]);//輸入資訊
	struct Student max(struct Student stu[]);//尋找平均成績最高
	void print(struct Student stu);//輸出資訊

	struct Student stu[N];//定義結構體陣列
	struct Student *p=stu;//定義結構體指標

	struct Student max_stu;//定義結構體變數
	input(p);
	max_stu=max(p);
	print(max_stu);

	return 0;
}

void input(struct Student stu[]){
	int i;
	printf("請輸入各學生的資訊(學號、姓名、三門課成績):\n");
	for(i=0;i<N;i++){
		scanf("%ld %s",&stu[i].num,stu[i].name);//注意不能寫成&stu[i].name,因為name是陣列名,本身就代表地址
		for(int j=0;j<3;j++){//依次輸入3門課的成績
			scanf("%f",&stu[i].score[j]);
		}
		stu[i].aver = ( stu[i].score[0] + stu[i].score[1] + stu[i].score[2] )/3;//求平均值
	}
}

struct Student max(struct Student stu[]){
	int i,m=0;//m用來存放成績最高的學生在陣列中的序號
	for(i=1;i<N;i++){
		if(stu[i].aver>stu[m].aver){
			m=i;
		}
	}
	return stu[m];
}

void print(struct Student stu){
	printf("\n最高學生的成績為:\n");
	printf("學號:%ld ,姓名:%s ,三門課成績:%5.1f、%5.1f、%5.1f ,平均成績:%6.2f \n",
		stu.num,stu.name,stu.score[0],stu.score[1],stu.score[2],stu.aver);
}

程式碼說明:

以上三個函式的呼叫情況各不相同:

  • 呼叫 input 函式時,實參是指標變數p,形參是結構體陣列,傳遞的是結構體元素的地址,函式無返回值。
  • 呼叫 max 函式時,實參是指標變數p,形參是結構體陣列,傳遞的是結構體元素的地址,函式的返回值是結構體型別資料。
  • 呼叫 print 函式時,實參是結構體變數(結構體陣列元素),形參是結構體變數,傳遞的是結構體變數中各成員的值(“值傳遞”),函式無返回值。
執行結果:

在這裡插入圖片描述

案例2

有n個學生,每個學生的資料包括學號、姓名、3門課的成績,從鍵盤上輸入n個學生資料,要求輸出3門課的總平均成績,以及最高分的學生的資料(包括學號、姓名、3門課程成績、平均分數)。

程式實現
#include<stdio.h>

#define N 3

struct Student{
	long id;
	char name[10];
	float score[3];
	float aver;
};

void input(struct Student stu[]);
void func(struct Student stu[],float (*p)[2]);

int main(){
	struct Student stu[N];
	struct Student *p=stu;
	float lessons[3][2];//二維陣列{{該門課程的平均成績,最高分學生的序號},{},{}}
	input(p);
	func(p,lessons);
	for(int i=0;i<3;i++){
		printf("第%d門課程的平均分為:%8.3f ,最高分的學生資料為:\n",i+1,lessons[i][0]);
		struct Student max_stu=stu[(int)lessons[i][1]];
		printf("學號:%ld ,姓名:%s ,三門課的成績:%5.2f、%5.2f、%5.2f ,平均分:%f \n\n",
			max_stu.id,max_stu.name,max_stu.score[0],max_stu.score[1],max_stu.score[2],max_stu.aver);
	}
	return 0;
}

void input(struct Student stu[]){
	int i;
	printf("請輸入學生資訊(學號、姓名、3門課的成績):\n");
	for(i=0;i<N;i++){
		scanf("%ld %s",&stu[i].id,stu[i].name);
		for(int j=0;j<3;j++)
			scanf("%f",&stu[i].score[j]);
		stu[i].aver=(stu[i].score[0]+stu[i].score[1]+stu[i].score[2])/3;
	}
}

void func(struct Student stu[],float (*p)[2]){
	int i,j,max_student;//max_student用來存放成績最高的學生在陣列中的序號
	for(i=0;i<3;i++){//3門課程
		max_student=0;

		*(*(p+i)+0)=0;//注意:初始化語句不能少;否則結果出於意料(本人在程式設計時,因為這個錯誤,耗了很久)

		for(j=0;j<N;j++){//N個學生
			*(*(p+i)+0)+=stu[j].score[i];//累加所有學生的該課程成績
			if(stu[j].score[i]>stu[max_student].score[i])
				max_student=j;
		}
		*(*(p+i)+0)/=N;
		*(*(p+i)+1)=(float)max_student;
	}
}
程式碼說明:
  • 第46行程式碼: *( *(p+i)+0)=0; 的初始化語句不能少,否則結果可能會出乎意料。
執行結果:

在這裡插入圖片描述