6.2.2 结构体的引用

对于结构体成员的引用,从前面的代码也可以看出,其一般形式为:


结构体变量名.结构体成员名


如果定义的是结构体数组,那么就把数组中的每个元素作为一个结构体变量来引用结构体成员,其一般形式为:


结构体变量名[下标].结构体成员名


对于结构体数组的引用,在第1章讲解结构体时已经给出了相应的代码,在此重点介绍结构体指针的使用。先来看下面的一段代码。


include<stdio.h>

include<string.h>

struct stu{

char name[10];

char num[10];

double score;

char sex[4];

int age;

};

void main()

{

struct stu per,*p_per;

strcpy(per.name,"小明");

strcpy(per.num,"21009012");

strcpy(per.sex,"男");

per.score=456.9;

per.age=22;

p_per=&per;

printf("通过结构体变量per引用结构体成员\n");

printf("name:%s\tnum:%s\tscore:%lf\tsex:%s\tage:%d\n",per.name,per.num,per.score,per.sex,per.age);

printf("\n通过结构体指针p_per引用结构体成员方法一\n");

printf("name:%s\tnum:%s\tscore:%lf\tsex:%s\tage:%d\n",(p_per).name,(p_per).num,(p_per).score,(p_per).sex,(*p_per).age);

printf("\n通过结构体指针p_per引用结构体成员方法二\n");

printf("name:%s\tnum:%s\tscore:%lf\tsex:%s\tage:%d\n",p_per->name,p_per->num,p_per->score,p_per->sex,p_per->age);

return;

}


运行结果:


通过结构体变量per引用结构体成员

name:小明num:21009012 score:456.900000 sex:男age:22

通过结构体指针p_per引用结构体成员方法一

name:小明num:21009012 score:456.900000 sex:男age:22

通过结构体指针p_per引用结构体成员方法二

name:小明num:21009012 score:456.900000 sex:男age:22


在上面的代码中,通过指针引用得到的结果和直接采用结构体变量引用得到的结果完全相同,这说明可以通过指针引用来替代结构体变量对结构体成员的引用。下面介绍指针引用的两种方法。

方法一:


(*结构体指针变量名).结构体成员名


采用该方法时要注意其中的括号不能省略,因为“”的优先级低于“.”的优先级。如果没有加括号,以上面的代码为例,在此介绍一种错误情况,“error C2228:left of'.name'must have class/struct/union type”,其余的错误与此类似。出现这种错误是因为使用p_per引用结构体成员时出错了。p_per并不能够引用结构体成员,它本身并不是一种结构体类型,只是一个保存结构体变量地址的变量,要想通过它来引用结构体成员,必须使用括号先将p_per和号结合,表示一种结构体类型,等价于p_per所指向的结构体变量,进而成功引用结构体成员。

方法二:


结构体指针变量名->结构体成员名


采用这种方式时不需要再使用*和指针名结合的方式来引用结构体成员,只需要通过指针名直接引用结构体成员即可。需要注意的是,在使用这种方法引用结构体成员的时候,结构体类型的指针必须已经指向保存的结构体类型的变量。接下来看看直接定义的结构体类型的指针变量如何使用。


include<stdio.h>

include<string.h>

include<stdlib.h>

struct stu{

char name[10];

char num[10];

double score;

char sex[4];

int age;

};

void main()

{

struct stup_per1=(struct stu)malloc(sizeof(struct stu));

strcpy((*p_per1).name,"夏美芳");

strcpy((p_per1).num,"21009012");strcpy((p_per1).sex,"女");

(*p_per1).score=456.9;

(*p_per1).age=22;

printf("name:%s\tnum:%s\tscore:%.2lf\tsex:%s\tage:%d\n",p_per1->name,p_per1->num,p_per1->score,p_per1->sex,p_per1->age);

struct stup_per2=(struct stu)malloc(sizeof(struct stu));

strcpy(p_per2->name,"艾美丽");

strcpy(p_per2->num,"21009011");

strcpy(p_per2->sex,"女");

p_per2->score=568.4;

p_per2->age=20;

printf("name:%s\tnum:%s\tscore:%.2lf\tsex:%s\tage:%d\n",(p_per2).name,(p_per2).num,(p_per2).score,(p_per2).sex,(*p_per2).age);

return;

}


运行结果:


name:夏美芳num:21009012 score:456.90 sex:女age:22

name:艾美丽num:21009011 score:568.40 sex:女age:20


在上面的代码中,定义了结构体类型的指针变量p_per1和p_per2,采用了两种引用方法对其进行初始化,同时使用了两种方法进行打印输出。在此分别采用不同的引用方法来对结构体的的指针变量进行初始化和引用,主要是为了说明指针变量可以采用两种方法中的任何一种进行引用。需要留意的是,讲解指针时也特别强调过,没有分配内存的指针变量指向的是不可使用的内存区域,所以如果要对指针变量进行初始化,必须先在内存单元中为其分配一块可用的内存区域。

接下来我们再来看看一个综合性的使用,这段代码实现对已经初始化了的结构体数组按照学生的总分进行排名,分数由高到低。


include<stdio.h>

include<stdlib.h>

define N 4

struct stu{

char*name;

char*num;

double score;

char*sex;

int age;

}per[N]={

{"张欣欣","210025",345.23,"女",20},

{"范德萨","210026",386.56,"男",22},

{"王大鹏","210027",312.45,"男",19},

{"郭丽丽","210028",364.25,"女",24}

};

void sort(struct stu*p_per,int n)

{

int i,j,k;

struct stu temp;

for(i=0;i<n-1;i++)

{

k=i;

for(j=i+1;j<n;j++)

{

if(p_per[j].score>p_per[k].score)

k=j;

}

if(k!=i)

{

temp=p_per[i];

p_per[i]=p_per[k];

p_per[k]=temp;

}

}

return;

}

void print(struct stu*p_per,int n)

{

int i;

for(i=0;i<n;i++)

{

printf("name:%s\tnum:%s\tscore:%.2lf\tsex:%s\tage:%d\n",pper->name,p

per->num,p_per->score,p_per->sex,p_per->age);

p_per++;

}

return;

}

void main()

{

sort(per,N);

print(per,N);

return;

}


运行结果:


name:范德萨num:210026 score:386.56 sex:男age:22

name:郭丽丽num:210028 score:364.25 sex:女age:24

name:张欣欣num:210025 score:345.23 sex:女age:20

name:王大鹏num:210027 score:312.45 sex:男age:19


对比上面的初始化顺序和打印出来的结果可知,我们成功地实现了代码的功能,下面对其中的重点进行分析。在对结构体数组进行初始化的时候,是按照声明的先后顺序进行的,所以此时要注意结构体成员的先后顺序;在接下来对结构体数组进行排序的时候,传递的是结构体数组的首地址,然后在sort()函数中对其进行排序,由于采用的是传址方式,因此在sort()函数中对结构体指针p_per所指向的空间进行的交换操作就是在起始部分对结构体数组per所做的操作;接下来通过print()函数来打印此时结构体数组中的信息,得到的是经过排序后的数组,而不再是之前初始化的数组。