第三周:结构类型
1.枚举
常量符号化
--用符号而不是具体的数字来表示程序中的数字
--应用枚举的方式来定义独立的const变量
#include<stdio.h>
enum COLOR{RED,YELLOW,GREEN}
int main(int argc,char const *argv[]){
int color=-1;
char *colorName=NULL;
printf("输入你喜欢的颜色的代码:");
scanf("%d",&color);
switch(color)
{
case RED:colorName="red";break;
case YELLOW:colorName="yellow";break;
case GREEN:colorName="green";break;
default:colorName="unknow";break;
}
printf("你喜欢的颜色是%s\n",colorName);
return 0;
}
-枚举是一种用户定义的数据类型,它用关键字enum以如下语句来进行声明。
enum 枚举类型名字{名字1,……,名字n};
-枚举类型名字通常并不是真的使用,要用的是大括号里的名字,因为它们就是常量符号,他们的类型是int。值依次为0到n。
enum colors{red,yellow,green}
--通过枚举就创建出了三个常量,red的值是0,yellow是1,green是2.
--当需要一些可以排列起来的常量值时,定义枚举的意义就是给了这些常量值名字。
#include<stdio.h>
enum color{red,yelor,green};
void f(enum color c);
int main(void)
{
enum color t=red;
scanf("%d",&t);
f(t);
return 0;
}
void f(enum color c)
{
printf("%d\n",c);
}
枚举量可以作为值;
枚举类型可以跟上enum作为类型;
但是实际上是以整数来做内部计算和外部输入输出的。
举例:
自动计数的枚举
#include<stdio.h>
enum COLOR{RED,YELLOW,GREEN,NumCOLORS};
int main(int argc,char const *argv[])
{
int color=-1;
char *ColorNames[NumCOLORS]={"red","yellow","green",};
char *colorName=NULL;
printf("输入你喜欢的颜色的代码:");
scanf("%d",&color);
if(color>=0&&color<NumCOLORS){
colorName=ColorNames[color];
}else{
colorName="unknow";
}
printf("你喜欢的颜色是%s\n",colorName);
return 0;
}
–用以上方式需要遍历所有的枚举量或者需要建立一个用枚举量做下标的数组的时候就很方便
-声明枚举量的时候可以指定值
--enum COLOR{RED=1,YELLOW,GREEN=5,NumCOLORS};
#include<stdio.h>
enum COLOR{RED=1,YELLOW,GREEN=5,NumCOLORS};
int main(int argc,char const *argv[]){
printf("code for GREEN is %d\n",GREEN);
return 0;
}
-即使给枚举类型的变量赋不存在的整数值也没有任何的warning或error
2.结构
声明结构类型
#include<stdio.h>
int main(int argc,char const *argv[])
{
struct date{
int month;
int day;
int year;
};
struct date today;
today.month=07;
today.day=31;
today.year=2014;
printf("Today's date is %i-%i-%i.\n",today.year,today.month,today.day);
return 0;
}
–和本地变量一样,在函数内部声明的结构类型只能在函数内部使用
–所以通常在函数外部声明结构类型,这样就可以被多个函数使用
声明结构的形式1:
struct point{
int x;
int y;
};
struct point p1,p2;
p1和p2都是point里面有x和y的值
声明结构的形式2:
struct{
int x;
int y;
}p1,p2;
p1和p2都是一种无名结构,里面有x和y
声明结构的形式3:
struct point{
int x;
int y;
}p1,p2;
p1和p2都是point里面有x和y的值
结构的初始化:
#include<stdio.h>
struct date{
int month;
int day;
int year;
};
int main(int argc,char const *argv[])
{
struct date today={07,31,2014 };
struct date thismontn={.month=7,.year=2014};
printf("Today's date is %i-%i-%i.\n",today.year,today.month,today.day);
printf("This month is %i-%i-%i.\n",thismonth.year,thismonth.month,thismonth.day);
return 0;
}
结构成员:
-结构和数组有点像
-数组用[]运算符和下标访问其成员
-结构用.运算符和名字访问其成员
--today.day
--student.firstName
--pl.x
--pl.y
结构运算:
-要访问整个结构,直接用结构变量的名字
-对于整个结构,可以做赋值、取地址、也可以传递给函数参数
--pl=(struct point){5,10};//相当于pl.x=5;pl.y=10;
--p1=p2;//相当于p1.x=p2.x;p1.y=p2.y
结构指针:
-和数组不同,结构变量的名字并不是结构变量的地址,必须使用&运算符
-struct date *pDate = &today
结构作为函数参数:
int number0fDays(struct date d)
-整个结构可以作为参数的值传入函数
-这时候是在函数内新建一个结构变量,并复制调用者的结构的值
-也可以返回一个结构
-这与数组完全不同
#include<stdio.h>
#include<stdbool.h>
struct date{
int month;
int day;
int year;
};
bool isLeap(struct date d);//判断是否为闰年
int numberofDays(struct date d);
int main(int argc,char const *argv[])
{
struct date today,tomorrow;
printf("Enter today's date(mm dd yyyy):");
scanf("%i %i %i",&today.month,&today.day,&today.year);
if(today.day!=number0fDays(today)){
tomorrow.day=today.day+1;
tomorrow.month=today.month;
tomorrow.year=today.year;
}else if(today.month==12){
tomorrow.day=1;
tomorrow.month=1;
tomorrow.year=today.year+1;
}else{
tomorrow.day=1;
tomorrow.month=today.month+1;
tomorrow.year=today.year;
}
printf("Tomorrow's date is %i-%i-%i.\n",tomorrow.year,tomorrow.month,tomorrow.day) ;
return 0;
}
//该函数是用于判断今天是不是一个月的最后一天
int numberofDays(struct date d)
{
int days;
const int daysPerMonth[12]={31,28,31,30,31,30,31,31,30,31,30,31};
if(d.month ==2&&isLeap(d)){
days=29;
}else{
days=daysPerMonth[d.month-1];
}
return days;
}
//该函数用于判断本本年是否为闰年
bool isLeap(struct date d){
bool leap=false;
if((d.year%4==0&&d.year%100!=0)||d.year%400==0){
leap=true;
}
return leap;
}
输入结构:
-没有直接的方式可以一次scanf一个结构
-如果打算写一个函数来读入——>
-但是读入的结构如何送回来呢/
-记住C在函数调用的时候是传值的
--所以函数中的p与main中的y是不同的
--在函数读入了p的数值后,没有任何东西回到main,所以y还是{0,0}
#include<stdio.h>
struct point{
int x;
int y;
};
void getStruct(struct point);
void output(struct point);
void main(){
struct poiny y={0,0};
getStruct(y);
output(y);
}
void output(struct point p){
printf("%d,%d",p.x,p.y);
}
指向结构的指针
struct date{
int month;
int day;
int year;
}my day;
struct date *p=myday;
(*p).month=12;
p->month=12;
用–>表示指针所指的结构变量中的成员
结构数组
struct date dates[100];
struct date dates[]={
{4,5,2005},{2,4,2005}
};
例子:
#include<stdio.h>
struct time{
int hour;
int minutes;
int seconds;
};
struct time timeUpdate(struct time now);
int main(void)
{
struct time testTimes[5]={
{11,59,59},{12,0,0},{1,29,59},{23,59,59},{19,12,27}
};
int i;
for(i=0;i<5;++i){
printf("Time is %.2i:%.2i:%.2i",testTimes[i].hour,testTimes[i].minutes,testTimes[i].seconds);
testTimes[i] = timeUpdate(testTimes[i]);
printf("...one second later it's %.2i:%.2i:%.2i\n",testTimes[i].hour,testTimes[i].minutes,testTimes[i].seconds);
}
return 0;
}
struct time timeUpdate(struct time now){
++now.seconds;
if(now.seconds == 60){
now.seconds = 0;
++now.minutes;
if(now.minutes == 60){
now.minutes = 0;
++now.hour;
if(now.hour ==24){
now.hour = 0;
}
}
}
}
嵌套的结构
struct point{
int x;
int y;
};
struct rectangle{
struct point pt1;
struct point pt2;
};
如果有变量
struct rectangle r;
就可以有:
r.ptl.x、r.ptl.y
r.pt2.x和r.pt2.y
如果有变量定义:
struct rectangle r,*rp;
rp=&r;
那么下面的四种形式是等价的:
r.ptl.x
rp->ptl.x
(r.ptl).x
但是没有rp->ptl->x(因为ptl不是指针)
结构中的结构的数组
#include<stdio.h>
struct point{
int x;
int y;
};
struct rectangle{
struct point p1;
struct point p2;
};
void printRect(struct rectangle r){
printf("<%d,%d"> to <%d,%d>\n,r.p1.x,r.p1.y,r.p2.x,r.p2.y);
}
int main(int argc,char const *argv[]){
int i;
struct rectangle rects[] = {{{1,2},{3,4}},{{5,6},{7,8}}};
for(i=0;i<2;i++){
printRect(rects[i]);
}
}
3.联合
自定义数据类型(typedef)
C语言提供了一个叫做typedef的功能来声明一个已有的数据类型的新名字,比如:
typedef int Length;
使得Length成为int类型的别名。这样,Length这个名字就可以替代int出现在变量定义和参数声明的地方了;
Length a,b,len;
Length numbers[10];
声明新的类型的名字
-新的名字是某种类型的别名
-改善了程序的可读性
typedef long int64_t;
typedef struct ADate{
int month;
int day;
int year;
}Date;
int64_t i=100000000000;
Date d={9,1,2005};
-存储
–所有的成员共享一个空间
–同一时间只有一个成员是有效的
–union的大小是其最大的成员
-初始化
–对第一个成员做初始化
union的作用
#include<stdio.h>
typedef union{
int i;
char ch[sizeof(int)];
}CHI;
int main(innt argc,char const *argv[]){
CHI chi;
int i;
chi.i = 1234;
for(i=0;i<sizeof(int);i++){
printf("%02hhX",chi.ch[i]);
}
printf("\n");
return 0;
}