您的当前位置:首页正文

08——结构体共用体枚举

2024-11-10 来源:个人技术集锦

用户自定义数据类型

一、结构体

之前我们学过的数据类型(int、char、float等)是C语言提供的基本数据类型。实际上我们也可以根据自身的需求自定义一些数据类型。这些数据类型称为“构造数据类型”。

在实际生活中,有些数据是有内在关联的。例如一个学生有学号、姓名、性别、成绩等内在关联数据。我们可以将这些内在关联数据组合起来,构成一个新的变量类型,在这个类型中包含学号、姓名、性别、成绩等项,这样使用起来就方便多了。

C语言允许用户自己建立由不同数据组合而成的组合型数据类型,称为“结构体”(struct)。

1、声明一个结构体

声明一个结构体的一般形式为

struct Student

{

int number;

char name[64];

char sex;

int age;

int score;

};

其中,struct是C语言声明结构体类型时的关键字,不可省略。

注意:

  • 1)结构体、共用体和枚举类型一般首字母大写,以表示与系统提供的类型名和自定义的变量名区分开。
  • 2)花括号内是该结构体所包含的子项,称为结构体的成员(member)。成员表列(member list)又称为“域表”(field list),每一个成员是结构体的一个域。
  • 3)成员可以是另一个结构体类型。

例如:

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];

  • char,1字节对齐
  • short,2字节对齐
  • int,4字节对齐
  • float,4字节对齐
  • double,4字节对齐(32位系统) 或 8字节对齐(64位系统)

条件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;

注意:以下用法是错误的

  • struct Student *pt;//pt未指向有效的内存地址
  • pt->num=10101;//试图访问野指针,错误

/*****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在数据结构里会大量的使用,请同学们在学习时注意其用法。

Top