用户自己建立数据类型
一、定义和使用结构体变量
1、自己建立结构体类型
2、定义结构体类型变量
<1>先声明结构体类型,再定义该类型的变量
<2>在声明类型的同时定义变量
<3>不指定类型名而直接定义结构体类型变量
3、结构体变量的初始化和引用
二、使用结构体数组
1、定义结构体数组
2、结构体数组的应用举例
三、结构体指针
1、指向结构体变量的指针
2、指向结构体数组的指针
3、用结构体变量和结构体变量的指针作函数参数
一、定义和使用结构体变量
1、自己建立结构体类型
问题定义:
有时需要将不同类型的数据组合成一个有机的整体,以便于引用。
一个学生有学号/姓名/性别/年龄/地址等属性
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
num name sex age score addr
10001 Li Fun M 18 87.5 Beijing
C语言允许用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体。
自己建立一个结构体类型。
struct Student { int num; //学号为整型 char name[20]; //姓名为字符串 char sex; //性别为字符型 int age; //年龄为整型 float score; //成绩为实型 char addr[30]; //地址为字符串 }; //注意最后有一个分号
2、定义结构体类型变量
<1>先声明结构体类型,再定义该类型的变量
例如:struct Student--结构体类型名 student1,student2;--结构体变量名
student1 10001 Zhang Xin M 19 90.5 Shanghai
student2 10002 Wang Li F 20 98 Beijing
<2>在声明类型的同时定义变量
例如:
struct Student { int num; char name[20]; char sex; int age; float score; char addr[30]; }student1,student2;
ruct 结构体名
{
成员表列
} 变量名表列;
<3>不指定类型名而直接定义结构体类型变量
其一般形式为
struct
{
成员表列
} 变量名表列;
说明:
(1)结构体类型与结构体变量是不同的概念,不要混淆。只能对变量赋值、存取或运算,而不能对一个类型赋值、存取或运算。在编译时,对类型是不分配空间的,只对变量分配空间。
(2)结构体类型中的成员名可以与程序中的变量名相同,但二者不代表同一对象。
例如,程序中可以另外定义一个变量num,它与struct Student中的num是两回事,互不干扰。
(3)对结构体变量中的成员(即“域”),可以单独使用,它的作用与地位相当于普通变量。
3、结构体变量的初始化和引用
例:把一个学生的信息(包括学号、姓名、性别、住址)放在一个结构体变量中,然后输出这个学生的信息。
#include<stdio.h> int main() { struct Student //声明结构体类型struct Student { long int num; char name[20]; char sex; char addr[20]; }a={10101,"Li Lin",'M',"123 Beijing Road"}; //定义结构体变量a并初始化 printf("NO.:%ld\nname:%s\nsex:%c\naddress:%s\n",a.num,a.name,a.sex,a.addr); return 0; }
在定义了结构体变量以后,当然可以引用这个变量。但应遵守以下规则:
(1)不能将一个结构体变量作为一个整体进行输入和输出。
例如:已定义student1和student2为结构体变量并且它们已有值。
printf("%d,%s,%c,%d,%f\n",student1); //err
(2)引用结构体变量中成员的方式为
结构体变量名.成员名
(3)如果成员本身又属一个结构体类型,则要用若干个成员运算符,一级一级地找到最低一级的成员。只能对最低级的成员进行赋值或存取以及运算。如果在结构体struct Student类型的成员中包含另一个结构体struct date类型的成员birthday,则引用成员的方式为
student1.num (结构体变量student1中的成员num)
student1.birthday.month (结构体变量student1中的成员birthday中的成员month)
不能用student1.birthday来访问student1变量中的成员birthday,因为birthday本身也是一个结构体成员。
(4)对结构体变量的成员可以像普通变量一样进行各种运算(根据其类型决定可以进行的运算)。例如:
student2.score=student1.score; (赋值运算)
sum=student1.score+student2.score; (加法运算)
student1.age++; (自加运算)
"."运算符的优先级最高,因此student1.age++是对(student1.age)进行自加运算,而不是先对age进行自加运算。
(5)同类的结构体变量可以互相赋值
student1=student2; //假设student1和student2已定义为同类型的结构体变量
(6)可以引用结构体变量成员的地址,也可以引用结构体变量的地址。例如:
scanf("%d",&student1,num); //输入student1,num的值
printf("%o",&student1); //输出结构体变量student1的起始地址
但不能用以下语句整体读入结构体变量,例如:
scanf("%d,%s,%c,%d,%f,%s\n",&stuent1);//err
结构体变量的地址主要用作函数参数,传递结构体变量的地址。
二、使用结构体数组
1、定义结构体数组
例:有3个候选人,每个选民只能投票选一人,要求编一个统计投票的程序,先后输入被选人的名字,最后输出各人得票结果。
解题思路:
(1)设一个结构体数组,数组中包含3个元素
(2)每个元素中的信息应包括候选人的姓名(字符型)和得票数(整型)
(3)输入被选人的姓名,然后与数组元素中的“姓名”成员比较,如果相同,就给这个元素中的“得票数”成员的值加1
(4)输出所有元素的信息
#include<stdio.h> #include<string.h> struct Person //声明结构体类型struct Person { char name[20]; //候选人姓名 int count; //候选人得票数 }leader[3]={"Li",0,"Zhang",0,"Sun",0}; //定义结构体数组并初始化 int main() { int i=0; int j=0; char leader_name[20]; for(i=1;i<=10;i++) { scanf("%s",leader_name); //输入所选的候选人姓名 for(j=0;j<3;j++) { if(strcmp(leader_name,leader[j].name)==0) leader[j].count++; } } printf("\nResult:\n"); for(i=0;i<3;i++) { printf("%5s:%d\n",leadder[i].name,leader[i].count); } return 0; }
说明:
(1)定义结构体数组一般形式是
<1>struct 结构体名
{
成员表列
} 数组名[数组长度];
<2>先声明一个结构体类型(如struct Person),然后再用此类型定义结构体数组:
结构体类型 数组名[数组长度];
如:
struct Person leader[3]; //leader是结构体数组名
(2)对结构体数组初始化的形式是在定义数组的后面加上:
={初值表列};
如:
struct Person leader[3]={"Li",0,"Zhang",0,"Sun",0};
2、结构体数组的应用举例
例:有n个学生的信息(包括学号、姓名、成绩),要求按照成绩的高低顺序输出各学生的信息。
#include<stdio.h> struct Student { int num; char name[20]; float score; }; int main() { struct Student stu[5]={{10101,"Zhang",78},{10103,"Wang",98.5},{10106,"Li",86}, {10108,"Ling",73.5},(10110,"Sun",100}}; //定义结构体数组并初始化 struct Student tmp; //定义结构体变量tmp,用作交换时的临时变量 const int n=5; //定义常变量n int i=0; int j=0; int k; printf("The order is:\n"); for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) { if(stu[j].score>stu[k].score) //进行成绩的比较 { k=j; } tmp=stu[k]; stu[k]=stu[i]; stu[i]=tmp; } } for(i=0;i<n;i++) { printf("%6d %8s %6.2f\n",stu[i].num,stu[i].name,stu[i].score); } printf("\n"); return 0; }
三、结构体指针
1、指向结构体变量的指针
指向结构体对象的指针变量既可以指向结构体变量,也可以指向结构体数组中的元素。指针变量的基类型必须与结构体变量的类型相同。
为了使用方便和直观,C语言允许把(*p).num用p->num代替,"->"表示一个箭头,p->num表示p所指向的结构体变量中的num成员。同样,(*p).name等价于p->name。”->"称为指向运算符。
如果p指向一个结构体变量stu,以下三种用法等价:
(1) stu.成员名(如stu,num);
(2)(*p).成员名(如(*p).num);
(3)p->成员名(如p->num)。
2、指向结构体数组的指针
3、用结构体变量和结构体变量的指针作函数参数
将一个结构体变量的值传递给另一个函数,有三种方法:
(1)用结构体变量的成员作参数。
(2)用结构体变量作实参。
(3)用指向结构体变量(或数组元素)的指针作实参,将结构体变量(或数组元素)的地址传给形参。