C程式設計--結構體(結構體和函式之間的引數使用)
阿新 • • 發佈:2018-12-05
結構體型別(掌握點):
- 建立結構體型別
- 定義結構體型別變數
- 初始化結構體和引用結構體變數(3種方法,見下)
- 使用結構體陣列
- 結構體指標(重要)
- 指向結構體變數的指標
- 指向結構體陣列的指標
程式碼案例
#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);
}
}
程式碼說明:
- (*p).num 表示p指向的結構體變數中的成員num。注意: *p 兩側的括號不能省,因為成員運算子 “ . ” 優先於“ * ”運算子,*p.num 就等價於 *(p.num);
- 如果p指向一個結構體變數stu,以下3種用法等價:
① stu.成員名(如:stu.num);
② (*p).成員名(如:(*p).num);
③ p->成員名(如:p->num); - 對結構體成員變數: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>
執行結果
結構體和函式之間的引數使用(重點+難點)
- 用結構體變數成員 作實參(例如:stu[1].num):屬於“值傳遞”方式,注意實參和形參的型別保持一致。
- 用結構體變數作實參(例如:stu):屬於“值傳遞”方式,形參必須是與實參同類型的結構體變數。
缺點:①這種傳遞方式在空間和時間上開銷比較大;②在被呼叫函式期間改變了形參,並不能改變主函式中的實參值。 - 用指向結構體變數(或陣列元素)的指標作實參,將結構體變數(或陣列元素)的地址傳給形參。
案例
有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; 的初始化語句不能少,否則結果可能會出乎意料。