結構體是我們自己定義的一種新的數據類型, 同樣可以有結構數組和結構指針。
1.結構體數組
具有相同結構體類型的變量構成的數組,稱爲結構體數組。與普通數值型數組的不同之處在於每個數組元素都是一個結構體變量,它們都分別包含各個成員項。
- 定義結構體數組一般形式是
struct 結構體名
{
成員列表
}數組名[數組長度];
或者:
先聲明一個結構體類型,然後再定義結構體數組
結構體類型 數組名[數組長度];
對結構體數組初始化的形式是在定義數組的後面加上:={初始表列};
如:
struct student S1[3]={"Li",0,"Zhang",2"Sun",3};
結構體數組的應用舉例
輸入三個學生的個人信息 包含學號 姓名和三門學科的成績
輸出平均成績最高的學生的學號 姓名 各科成績以及平均成績
#include<stdio.h>
struct Student
{int num;
char name[20];
float score[3];
float aver;
};
void input(struct Student stu[])
{
//input函數形參爲結構體數組,實參爲結構體指針。
int i;
printf("請依次輸入學生編號,姓名,三個科目成績:\n");
for (i=0;i<3;i++)
{
scanf("%d %s %f %f %f",&stu[i].num, &stu[i].name, &stu[i].score[0], &stu[i].score[1], &stu[i].score[2]);
stu[i].aver = (stu[i].score[0]+stu[i].score[1]+stu[i].score[2])/3.0;
}
}
struct Student max(struct Student stu[])
{
//max函數形參爲結構體數組,實參爲結構體指針。
int i,m=0;
for (i = 0;i<3;i++)
{
if(stu[i].aver>stu[m].aver) m = i;
}
return stu[m];
}
void print(struct Student stud)
{
//print函數形參是結構體變量,實參是結構體變量(是結構體數組元素)。
printf("成績最高的學生:\n");
printf("學號:%d\n 姓名:%s\n 三門成績:%5.1f,%5.1f,%5.1f\n 平均成績:%6.2f\n",stud.num,stud.name,stud.score[0],stud.score[1],stud.score[2],stud.aver);
getchar();
}
int main()
{
struct Student stu[3];
struct Student *p=stu;//定義結構體指針p,並初始化它讓他指向結構體數組stu的首地址。
input(p);//輸入序號,姓名,成績等數據,存入結構體數組中
print(max(p));//比較平均成績,得到平均成績最大的那個數組
getchar();
getchar();
//有些編譯器在執行完程序後會自動關閉輸出界面,俗稱“閃退”,加上getchar();意思是等待用戶從鍵盤輸入
//一個按鍵,這樣可以解決閃退問題。
return 0;
}
運行結果
2.結構體指針
所謂結構體指針就是指向結構體變量的指針,表示的是這個結構體變量佔內存中的起始位置,
如果把一個結構體變量的起始地址存放在一個指針變量中,那麼,這個指針變量就指向該結構體變量。
定義結構體變量的指針:
//假設已有一個結構體名爲Student
struct Student *pStruct
// 結構體類型 * 指針名;
demo:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*1.使用->引用結構體成員 */
int main ()
{
struct Student
{
long num;
char name[20];
char sex;
float score;
};//student={"Girl",2017,'w',2};
struct Student stu;//定義struct Student類型的變量stu
struct Student *pStruct;//定義指向struct Student類型數據的指針變量pStruct
pStruct = &stu; //pStruct指向stu
stu.num=10101;
strcpy(stu.name,"fan");//對結構體變量的成員賦值
stu.sex='M';
stu.score=88;
printf("-----------the sudent's information----------\n");
printf("NO.:%ld\nname:%s\nsex%c\nscore:%5.1f\n",stu.num,stu.name,stu.sex,stu.score);
printf("\nNO.:%ld\nname:%s\nsex%c\nscore:%5.1f\n",(*pStruct).num,(*pStruct).name,(*pStruct).sex,(*pStruct).score);
printf("\nNO.:%ld\nname:%s\nsex%c\nscore:%5.1f\n",pStruct->num,pStruct->name,pStruct->sex,pStruct->score);
return 0;
}
(*pStruct).num中的(*pStruct)表示,*pStruct指向結構體變量,(*pStruct).num表示pStruct指向結構體變量中的成員num,注意括號不能省略,因爲成員運算符“.”優先於“*”運算符。爲了直觀和使用方便,C語言允許把(*pStruct).num用pStruct->num來代替,上面的三種表達方式等價。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Student //聲明結構體類型Student
{
int num;
char name[20];
char sex;
int age;
};
struct Student stu[5]=
{
{10101,"Zhou ping",'M',15},//定義結構體數組並初始化
{10102,"Zhang ping",'M',15},
{10103,"Liou fang",'F',16},
{10104,"Cheng ling",'F',17},
{10105,"Wang ming",'M',15}
};
int main()
{
struct Student *ps;//定義指向struct Student結構體類型數據的指針變量
printf("No\tName\t\t\tSex\tage\t\n");
for(ps=stu;ps<stu+5;ps++)
printf("%d\t%s\t\t%c\t%d\t\n",ps->num,ps->name,ps->sex,ps->age);
return 0;
}
如果ps的初始值是stu,即指向stu的第一個元素,ps加1後就指向下一個元素。(++ps)->num和(ps++)->是不一樣的
在程序中,定義了Student結構類型的外部數組stu並作了初始化賦值。在main函數內定義ps爲指向Student類型的指針。在循環語句for的表達式1中,ps被賦予stu的首地址,然後循環5次,輸出stu數組中各成員值。
應該注意的是,一個結構指針變量雖然可以用來訪問結構變量或結構數組元素的成員,但是,不能使它指向一個成員。也就是說不允許取一個成員的地址來賦予它。因此,下面的賦值是錯誤的。
ps=&stu[1].sex;
而只能是:
ps=stu;(賦予數組首地址)
或者是:
ps=&stu[0];(賦予0號元素首地址)