用户自定义数据类型
一、结构体
之前我们学过的数据类型(int、char、float等)是C语言提供的基本数据类型。实际上我们也可以根据自身的需求自定义一些数据类型。这些数据类型称为“构造数据类型”。
在实际生活中,有些数据是有内在关联的。例如一个学生有学号、姓名、性别、成绩等内在关联数据。我们可以将这些内在关联数据组合起来,构成一个新的变量类型,在这个类型中包含学号、姓名、性别、成绩等项,这样使用起来就方便多了。
C语言允许用户自己建立由不同数据组合而成的组合型数据类型,称为“结构体”(struct)。
1、声明一个结构体
声明一个结构体的一般形式为
struct Student
{
int number;
char name[64];
char sex;
int age;
int score;
};
其中,struct是C语言声明结构体类型时的关键字,不可省略。
注意:
例如:
struct Date
{
int year;
int month;
int day;
};
struct Student
{
int num;
char name[64];
char sex;
int age;
struct Date birthday;
int score;
};
练习:声明以下结构体
1)学生成绩单:成员表列包括:学生学号、学生姓名、语文成绩、数学成绩、英语成绩
2)产品生产批号:成员表列包括:产品批次、产品生产日期(年、月、日)、产地
3)货物信息:成员表列包括:货物长、宽、高、重量、颜色、始发地、目的地
答案:
1)
struct Score
{
int number;
char name[64];
int chinese_score;
int math_score;
int english_score;
};
2)
struct Date
{
int year;
int month;
int day;
};
struct Goods
{
int pici;
struct Date shengchanriqi;
char chandi[64];
};
3)
struct Freight
{
int length;
int width;
int height;
int weight;
char color;
char src[64];
char dst[64];
};
int a[10];
条件1、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)。
例如:有以下结构体:
struct A
{
char c;
int i;
char b;
};
对于结构体A来说,若我们适当改变成员顺序,即可减少内存浪费的情况。例如,我们把结构体A改写成:
struct B
{
char c;
char b;
int i;
};
结构体成员未变,只是出现顺序发生改变。这时我们可以发现该结构体占用内存大小为8个字节。相比结构体A,结构体B更加节约内存。
练习:求以下结构体占内存的大小:
//①
struct stu1
{
char c1;
int i;
char c2;
};
//②
struct stu2
{
float f;
char c;
float d;
};
//③
struct stu3
{
short i;
char c1;
char c2;
};
//④
struct stu4
{
short a;
short b;
short c;
};
答案:
①12字节②12字节③4字节④6字节
2、定义结构体类型变量
前面的只是声明了一个结构体类型,即建立了一个模型,它没有定义实际的内容,无具体数据,系统也没有对其分配存储单元。为了能够在程序中使用一个结构体类型的数据,需要定义一个结构体类型变量,并在其中存放数据。定义结构体变量有3种方式。
注意:要区分“声明”与“定义”的区别。声明的结构体只是模板,没有实际数据,没有存储空间,无法直接使用;而定义后的结构体就可以存储数据、有实际存储空间、可以直接使用了。
1)先声明结构体类型,再定义结构体变量
在前面我们已经声明过许多结构体。例如:
struct Student
{
int number;
char name[64];
char sex;
int age;
int score;
};
那么我们就可以直接使用已声明的结构体来定义结构体变量。例如:
struct Student student1,student2;//定义2个结构体Student类型变量student1和student2
注意关键字struct不可省略。
这种定义方式与定义普通变量(例如int a,char c等)是相似的。变量student1和student2的变量类型是struct Student类型。
这种定义方法的一般形式是:
struct 已声明过的结构体名 结构体类型变量名;
2)在声明类型的同时定义变量
这种定义方法的一般形式是:
struct 结构体名
{
成员表列;
}变量名表列;
例如:
struct Student
{
int num;
char name[64];
char sex;
int age;
float score;
}student1,student2;
作用与第一种方法相同,但是在声明了结构体Student之后同时定义了2个struct Student类型的变量student1和student2。
结构体的声明和定义放在一起进行,能直接看到结构体结构,比较直观,在写中小型程序时使用此方法比较方便。但在写大型程序时,往往把所有的类型声明(变量声明、函数声明等)分别放在不同的地方以使程序结构体清楚、便于维护,因此此方法在写大型程序时不常用。
3)不指定结构体名而直接定义结构体类型变量
这种定义方法的一般形式是:
struct
{
成员表列;
}变量名表列;
这种定义方式指定了一个无名的结构体名,它没有名字,显然不能够再使用此结构体去定义其他的结构体类型变量。所以这种方式用的不多。
3、结构体变量的初始化和引用
在定义结构体变量时可以对其初始化。
示例:把一个学生的信息放在一个结构体变量中,然后输出这个学生的信息。
#include<stdio.h>
int main()
{
struct Student
{
int num;
char name[64];
char sex;
int score;
}stu1={10101,"LiLin",'M',95};//定义结构体变量stu1并赋初值
printf("学号:%d\n姓名:%s\n性别:%c\n成绩:%d\n",stu1.num,stu1.name,stu1.sex,stu1.score);
return 0;
}
分析:程序中声明了一个结构体名为Student的结构体类型,在声明的同时定义了结构体变量stu1,在定义变量的同时进行初始化。在输出时,使用符号“.”来引用结构体变量中的成员。
结构体成员运算符:
符号:.
结合性:自左至右
优先级:1级
使用方法:该运算符作用是引用一个结构体变量中的成员变量的值,引用方法为
结构体变量名.成员名
如程序中的stu1.num,即取结构体变量stu1中的成员num的值。
说明:
1.在定义结构体变量时可以对它的成员进行初始化。初始化列表是用花括号括起来的一些常量,这些常量依次赋值给结构体变量中的各个成员。
2.允许对某一成员进行初始化,例如:
struct Student b={.name="Zhang"};
代表将结构体变量b中的name成员进行初始化。注意在成员变量前有成员运算符.
若进行结构体变量部分成员初始化,则其他未被指定的其他成员则会初始化为0(数值型)或'\0'(字符型)或NULL(指针型)。
3.可以引用结构体变量中成员的值,引用方式为
结构体变量名.成员名
例如:
stu1.num=10101;
对于结构体变量中的成员变量可以像普通变量一样进行各种运算。
如:
stu2.score=stu1.score;
sum = stu1.score+stu2.score;
stu1.score++;
4.不能企图使用结构体变量名来达到输出结构体所有成员的值的目的。下面用法不正确:
printf("%s\n",stu1);//错误,企图使用结构体变量名输出所有成员的值
只能对结构体变量中各个成员分别输出
printf("学号:%d\n姓名:%s\n性别:%c\n成绩:%d\n",stu1.num,stu1.name,stu1.sex,stu1.score);//正确
5.如果结构体成员中又包含另一个结构体,则若使用内层结构体成员变量,则需一层一层找到最低一级成员才行。例如:
struct Date
{
int year;
int month;
int day;
};
struct Student
{
int num;
char name[64];
char sex;
int age;
struct Date birthday;
int score;
}student1;
我们会发现birthday也是一个结构体,若给student1变量的成员变量birthday赋值,则需要再次使用成员运算符引用这个结构体内成员。
student.birthday.year=1992;
student.birthday.month=10;
student.birthday.day=10;
6.同类结构体变量可以互相赋值,
例如:
student2=student1;
前提是两个变量必须是同一个结构体类型。
练习1:定义两个学生类型的结构体变量,
分别包括:
学号(int类型)
姓名(字符串类型)
性别(char类型)
成绩(float类型)
通过键盘输入学生1的信息,之后将学生1的信息赋值给学生2,再输出学生2的信息。
答案:
#include<stdio.h>
#include<stdlib.h>
int main()
{
struct Student
{
int num;
char name[64];
char sex;
float score;
}student1,student2;
printf("请输入学号:");
scanf("%d",&student1.num);
printf("请输入姓名:");
scanf("%s",student1.name);//注意数组名即是数组的首地址,不要再加&
getchar();
printf("请输入性别(M/F):");
scanf("%c",&student1.sex);
printf("请输入成绩:");
scanf("%f",&student1.score);
student2=student1;
printf("学号:%d\n姓名:%s\n性别:%c\n成绩:%f\n",student2.num,student2.name,student2.sex,student2.score);
return 0;
}
练习2:在练习1的基础上,由键盘输入学生2的信息,比较两个学生的成绩高低,如果学生1成绩较高,则输出学生1的信息;如果学生2的成绩较高,则输出学生2的信息;如果两学生成绩相等,则将两个学生的信息都输出。
#include<stdio.h>
#include<stdlib.h>
int main()
{
struct Student
{
int num;
char name[64];
char sex;
float score;
}student1,student2;
//输入学生1信息
printf("请输入学号:");
scanf("%d",&student1.num);
printf("请输入姓名:");
scanf("%s",student1.name);
getchar();
printf("请输入性别(M/F):");
scanf("%c",&student1.sex);
printf("请输入成绩:");
scanf("%f",&student1.score);
//输入学生2信息
printf("请输入学号:");
scanf("%d",&student2.num);
printf("请输入姓名:");
scanf("%s",student2.name);
getchar();
printf("请输入性别(M/F):");
scanf("%c",&student2.sex);
printf("请输入成绩:");
scanf("%f",&student2.score);
printf("成绩更高的学生是:\n");
if(student1.score>student2.score)
printf("学号:%d\n姓名:%s\n性别:%c\n成绩:%f\n",student1.num,student1.name,student1.sex,student1.score);
else if(student1.score<student2.score)
printf("学号:%d\n姓名:%s\n性别:%c\n成绩:%f\n",student2.num,student2.name,student2.sex,student2.score);
else
{
printf("学号:%d\n姓名:%s\n性别:%c\n成绩:%f\n",student1.num,student1.name,student1.sex,student1.score);
printf("学号:%d\n姓名:%s\n性别:%c\n成绩:%f\n",student2.num,student2.name,student2.sex,student2.score);
}
return 0;
}
4、使用结构体数组
如果一个类型的结构体有一组数据,则我们可以使用结构体数组来存储数据。例如如果有10个学生的信息需要运算,则我们可以使用一个结构体数组来存储这10个学生的信息。
定义一个结构体数组有2种形式,一般形式是:
1.先声明一个结构体类型,然后再定义结构体数组
struct 结构体名
{
成员表列;
};
struct 结构体名 数组名[数组长度];
例如:
struct Student
{
int num;
char name[64];
char sex;
float score;
};
struct Student stud[10];//定义一个Student类型的数组,该数组有10个元素
2.直接在声明结构体类型时定义结构体数组
struct 结构体名
{
成员表列;
}数组名[数组长度];
例如:
struct Student
{
int num;
char name[64];
char sex;
float score;
}stud[10];
示例:有3个候选人,有10个选民要进行投票,每个选民只能投票1人,要求编一个统计选票的程序,先后输入被选人的名字,最后输出个人选票的结果。
#include<stdio.h>
#include<string.h>
struct Person
{
char name[20];//候选人姓名
int count;//候选人得票数
}leader[3]={"Li",0,"Zhang",0,"Sun",0};//定义结构体数组并初始化
int main()
{
int i,j;
char leader_name[20];
for(i=1;i<=10;i++)
{
printf("请输入Li/Zhang/Sun三人中一人名字:");
scanf("%s",leader_name);
for(j=0;j<3;j++)
{
if(strcmp(leader_name,leader[j].name)==0)
leader[j].count++;
}
}
printf("\n选票结果是:\n");
for(i=0;i<3;i++)
printf("%s:%d\n",leader[i].name,leader[i].count);
return 0;
}
练习:有5个学生的信息如下:
学号 姓名 成绩
10101 Sun 96
10103 Wang 98.5
10110 Li 100
10108 Ling 83.5
10106 Zhang 88
编写程序,分别按照学号顺序和成绩顺序输出学生的信息。
答案:
#include<stdio.h>
#define LEN 5
struct Student
{
int num;
char name[8];
float score;
};
void print_stu(struct Student stu[])
{
int i;
printf("学号\t\t姓名\t\t成绩\n");
for(i=0;i<LEN;i++)
{
printf("%d\t\t%s\t\t%.2f\n",stu[i].num,stu[i].name,stu[i].score);
}
}
int main()
{
int i,j;
struct Student stu[LEN]={
10101,"Sun",96,
10103,"Wang",98.5,
10110,"Li",100,
10108,"Ling",83.5,
10106,"Zhang",88
};
struct Student tmp;
//按学号排列
for(i=0;i<LEN-1;i++)
{
for(j=0;j<LEN-i-1;j++)
{
if(stu[j].num>stu[j+1].num)
{
tmp = stu[j];
stu[j]=stu[j+1];
stu[j+1]=tmp;
}
}
}
printf("按学号排列如下:\n");
print_stu(stu);
//按成绩排列
for(i=0;i<LEN-1;i++)
{
for(j=0;j<LEN-i-1;j++)
{
if(stu[j].score<stu[j+1].score)
{
tmp = stu[j];
stu[j]=stu[j+1];
stu[j+1]=tmp;
}
}
}
printf("按成绩排列如下:\n");
print_stu(stu);
return 0;
}
5、结构体指针
1)指向结构体变量的指针
定义一个结构体指针变量的用法:
struct 结构体类型名 *指针变量名
例如:struct Student *pt;
示例:
#include<stdio.h>
#include<string.h>
int main()
{
struct Student
{
int num;
char name[64];
char sex;
float score;
};
struct Student stu1;
struct Student *pt;
pt=&stu1;//指针pt指向结构体变量stu1
stu1.num=10101;
strcpy(stu1.name,"Li");//注意给字符串类型赋值不能使用赋值运算符=,而要使用strcpy()函数
stu1.sex='M';
stu1.score=90;
printf("%d\t%s\t%c\t%f\n",stu1.num,stu1.name,stu1.sex,stu1.score);//使用直接引用方式访问结构体成员变量
printf("%d\t%s\t%c\t%f\n",(*pt).num,(*pt).name,(*pt).sex,(*pt).score);//使用指针方式访问结构体成员变量
return 0;
}
示例程序的两次输出结果是一样的,也就是说指针pt所指向的结构体变量就是stu1。
在第二个printf()函数中,通过指针访问结构体变量的方法是
(*pt).num;
实际上,C语言提供给我们一种更简便的写法:
pt->num;
其中->是间接访问结构体成员运算符,->符号左边必须是一个指向结构体变量的指针。
如果一个指针pt已经指向了一个结构体变量stu1,则以下三种写法是等价的:
1.stu.成员名
2.(*pt).成员名
3.pt->成员名
示例程序的第二个printf()函数可以写成:
printf("%d\t%s\t%c\t%f\n",pt->num,pt->name,pt->sex,pt->score);//使用指针方式访问结构体成员变量
2)指向结构体数组的指针
同样,我们也可以使用结构体指针来访问结构体数组。
示例:
#include<stdio.h>
struct Student
{
int num;
char name[64];
char sex;
float score;
};
struct Student stu[3]={{10101,"Li",'M',95},{10103,"Liu",'M',88},{10107,"Zhang",'F',99}};//定义结构体数组包含三个元素
int main()
{
struct Student *pt;//定义指向stu[3]的结构体指针
for(pt=stu;pt<stu+3;pt++)
{
printf("%d\t%s\t%c\t%f\n",pt->num,pt->name,pt->sex,pt->score);
}
return 0;
}
在示例程序中,for()循环的第一句
pt=stu;
请注意
(++pt)->num;//先让pt移动到下一个数组元素,然后访问该元素的成员变量num
与
(pt++)->num;//先访问该元素的成员变量num,然后让pt移动到下一个数组元素
的不同。
注意示例程序中,pt的类型是结构体变量类型。所以
是不对的,在编译时编译器会给出warning。
练习1:定义一个日期结构体变量(包括年、月、日),判断该年是不是闰年。要求不使用指针和使用指针两种方法。
练习2:在上一个练习的基础上,定义一个日期结构体变量(包括年、月、日),从键盘输入一个时间(年、月、日),判断该日期是该年的第几天。注意闰年问题。要求不使用指针和使用指针两种方法。
答案:
//练习1答案已在练习2答案中,不再重复写明
1)不使用指针
#include<stdio.h>
struct Date
{
int year;
int month;
int day;
int isLeap;
};
//函数IsLeap,判定一个年份是否是闰年。是闰年返回1,否则返回0
int IsLeap(int input)
{
if(input%4==0)
{
if(input%100!=0)
{
return 1;
}
else if(input%400==0)
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
int main()
{
struct Date date;
int count;
printf("请输入年份:");
scanf("%d",&date.year);
printf("请输入月份:");
scanf("%d",&date.month);
printf("请输入日期:");
scanf("%d",&date.day);
date.isLeap=IsLeap(date.year);
switch(date.month)
{
case 1:count=0;break;
case 2:count=31;break;
case 3:count=59;break;
case 4:count=90;break;
case 5:count=120;break;
case 6:count=151;break;
case 7:count=181;break;
case 8:count=212;break;
case 9:count=243;break;
case 10:count=273;break;
case 11:count=304;break;
case 12:count=334;break;
default:printf("输入错误!\n");exit(0);
}
count += date.day;
if(IsLeap(date.year)==1 && date.month>=3)
count += 1;
printf("该天是第%d天\n",count);
return 0;
}
2)使用指针
#include<stdio.h>
#include<stdlib.h>
struct Date
{
int year;
int month;
int day;
int isLeap;
};
//函数IsLeap,判定一个年份是否是闰年。是闰年返回1,否则返回0
int IsLeap(int input)
{
if(input%4==0)
{
if(input%100!=0)
{
return 1;
}
else if(input%400==0)
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
int main()
{
struct Date *date;
date = (struct Date*)malloc(sizeof(struct Date));
int count;
printf("请输入年份:");
scanf("%d",&date->year);
printf("请输入月份:");
scanf("%d",&date->month);
printf("请输入日期:");
scanf("%d",&date->day);
date->isLeap=IsLeap(date->year);
switch(date->month)
{
case 1:count=0;break;
case 2:count=31;break;
case 3:count=59;break;
case 4:count=90;break;
case 5:count=120;break;
case 6:count=151;break;
case 7:count=181;break;
case 8:count=212;break;
case 9:count=243;break;
case 10:count=273;break;
case 11:count=304;break;
case 12:count=334;break;
default:printf("输入错误!\n");exit(0);
}
count += date->day;
if(IsLeap(date->year)==1 && date->month>=3)
count += 1;
printf("该天是第%d天\n",count);
free(date);
return 0;
}
6、用结构体变量和结构体变量指针作为函数参数
将一个结构体变量的值传递给一个函数,有3种方法:
1.用结构体变量的成员做函数参数。如stu.num,stu.name等做函数的实参。用法和普通变量做实参是一样的,属于“值传递”方式。应当注意实参与形参的类型要一致。
2.用结构变量做实参。这种方式也属于“值传递”的方式,将结构体变量整体传递给函数作为实参。由于这种方式在空间开销上较大,执行效率低,而且传递后无法返回主调函数,因此这种方式基本不用。
示例:有n个结构体变量,内含学生学号、姓名和3门课的成绩。要求输出平均成绩最高的学生的信息(学号、姓名、3门课成绩及平均成绩)
#include<stdio.h>
#define N 3
struct Student
{
int num;
char name[20];
float score[3];
float avg;
};
void input(struct Student stu[])//input函数,输入学生信息
{
int i;
printf("请输入个学生的信息:学号、姓名、3门课的成绩:\n");
for(i=0;i<N;i++)
{
printf("请输入第%d个学生的信息:\n",i+1);
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].avg=(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<N;i++)
{
if(stu[i].avg>stu[m].avg)
m=i;
}
return stu[m];
}
void print(struct Student stud)
{
printf("\n成绩最高的学生是:\n");
printf("学号:%d\n姓名:%s\n成绩:%f\t%f\t%f\n平均成绩:%f\n",stud.num,stud.name,stud.score[0],stud.score[1],stud.score[2],stud.avg);
}
int main()
{
struct Student stu[N],*p=stu;
input(p);
print(max(p));
return 0;
}
练习:有5个成绩的信息需要录入(学号、姓名、性别、成绩)。编写2个函数,input函数用来录入这些信息,output函数用来输出这些信息。最后写一个主函数测试。
答案:
#include<stdio.h>
#define N 5
struct Student
{
int num;
char name[20];
char sex;
int score;
};
void input(struct Student stud[])
{
int i;
for(i=0;i<N;i++)
{
printf("请输入第%d个学生的学号:",i+1);
scanf("%d",&stud[i].num);
printf("请输入第%d个学生的姓名:",i+1);
scanf("%s",stud[i].name);
getchar();
printf("请输入第%d个学生的性别(M男/F女):",i+1);
scanf("%c",&stud[i].sex);
printf("请输入第%d个学生的成绩:",i+1);
scanf("%d",&stud[i].score);
}
}
void output(struct Student stud[])
{
int i;
printf("学号\t姓名\t性别\t成绩\n");
for(i=0;i<N;i++)
{
printf("%d\t%s\t%c\t%d\n",stud[i].num,stud[i].name,stud[i].sex,stud[i].score);
}
}
int main()
{
struct Student stu[N];
struct Student *p;
p = stu;
input(p);
output(p);
return 0;
}
/*******malloc函数与构造数据类型*****************/
1、malloc函数申请数组空间
例如:申请40个字节的空间作为int a[10]的存储内存
//int a[10]//栈区
int *p;
if(NULL==(p = (int*)malloc(sizeof(int)*10)))
{
//错误处理
}
使用该数组:
int i;
for(i=0;i<10;i++)
{
p[i]=i;
}
2、malloc函数申请结构体空间
struct Student
{
int num;
char name[64];
char sex;
float score;
};
//struct Student stu;//栈区
struct Student *pt;
if(NULL==(pt = (struct Student*)malloc(sizeof(struct Student))))
{
//错误处理
}
使用该结构体:
pt->num;
pt->name;
注意:以下用法是错误的
/*****malloc函数与构造数据类型end**************/
二、共用体
定义一个共用体类型变量的一般形式为:
union 共用体名
{
成员表列
}变量表列;
例如:
union Data
{
int i;
char ch;
float f;
}a,b;
可以看到,“共用体”与“结构体”的定义形式相类似,不过二者的含义是不同的。
结构体变量所占内存长度是各成员占的内存长度之和。每个成员分别占有其自己的内存单元。而共用体变量所占的内存长度等于最长的成员长度。
例如:
struct Data
{
int i;
char ch;
float f;
}
占12字节,而
union Data
{
int i;
char ch;
float f;
}
占4字节(float或int的长度)。
三、枚举类型
如果一个变量只有几种可能的值,则可以定义成枚举(enumeration)类型。
例如:对于扑克牌来说,花色(除大小王之外)只有4种:黑桃、红桃、方块、梅花。则我们可以定义花色为枚举类型。
enum Huase{heit,hongt,fangk,meih};
声明枚举类型的一般形式为:
enum 枚举名{枚举元素列表};
对于一周来说,只有7天(星期一~星期日)。则我们可以定义星期为枚举类型。
enum Weekday{sun,mon,tue,wed,thu,fri,sat};
声明了枚举变量后,可以用此类型定义变量。如:
enum Weekday workday,weekend;
workday与weekend被定义为枚举变量,花括号中的sun,mon……称为枚举元素或枚举常量。它们是用户指定的名字。枚举变量workday与weekend只能是枚举常量之一。
workday=sun;//正确
weekend=sunday;//错误,sunday不是枚举常量之一
说明:
1)C编译对枚举类型的枚举元素按常量处理。不能当做变量对它们赋值。例如:
sun=0;mon=1;//错误,不能对枚举常量进行赋值
2)每个枚举常量都代表一个整数,编译器按定义时的顺序默认它们的值是0,1,2……。在上面的定义中,sun的值为0,mon的值为1……。赋值语句
workday=mon;
等价于
workday=1;
当然也可以人为指定枚举常量的数值。例如:
enum Weekday{sun=7,mon=1,tue,wed,thu,fri,sat};
指定sun的值为7,mon的值为1,后续常量依次加1,sat为6。
3)枚举元素可以用来比较判断。例如:
if(workday==mon)
if(workday>sun)
等。比较规则是按其在初始化时指定的整数来比较。
示例:口袋中有红、黄、蓝、白、黑5色小球若干个,每次从口袋拿3个球,问得到3种不同颜色的球的可能取法。
#include<stdio.h>
#include<math.h>
int main()
{
enum Color{red,yellow,blue,white,black};
enum Color i,j,k,pri;
int n,Leap;
n=0;
for(i=red;i<=black;i++)
{
for(j=red;j<=black;j++)
{
if(i!=j)
{
for(k=red;k<=black;k++)
if((k!=i)&&(k!=j))
{
n=n+1;
printf("%d:\n",n);
for(Leap=1;Leap<=3;Leap++)
{
switch(Leap)
{
case 1:pri=i;break;
case 2:pri=j;break;
case 3:pri=k;break;
default:break;
}
switch(pri)
{
case red:printf("%s\n","red");break;
case yellow:printf("%s\n","yellow");break;
case blue:printf("%s\n","blue");break;
case white:printf("%s\n","white");break;
case black:printf("%s\n","black");break;
default:break;
}
}
}
}
}
}
printf("\ntotal:%d\n",n);
return 0;
}
四、用typedef声明新类型名
除了可以直接使用C提供的标准类型名(例如int,char,float等),我们还可以用typedef来指定新的类型名来替代已有的类型名。
有时,对于结构体等构造数据类型来说,有时会出现难以理解、容易写错等情况。C语言中允许设计者使用一个简单的名字来代替复杂的类型形式。例如
typedef struct Datenum
{
int year;
int month;
int day;
}Date;
以上声明了一个新类型名Date,代表上面的一个结构体类型。然后可以使用新的类型名Date去定义变量,如:
Date birthday;
它与
struct Datenum birthday;
等价。
同样也可用于定义结构体指针
typedef struct Datenum
{
int year;
int month;
int day;
}*Point;
则
Point p;
等价于
struct Datenum *p;
typedef声明数组、指针、结构体、共用体、枚举类型等,使得编程更加方便。
注意:typedef与#define虽然在作用上相似,但二者本质不同。#define是在预处理阶段进行宏代替,而typedef则是在编译阶段处理的。
typedef在数据结构里会大量的使用,请同学们在学习时注意其用法。