22-结构类型

本文详细介绍了C语言中的枚举(enum)和结构体(struct)的使用,包括枚举的声明、枚举量的指定、结构体的声明与初始化、结构成员的访问以及结构在函数中的应用。枚举提供了为常量赋予名称的便利,而结构体则允许组合不同类型的变量。此外,还讨论了结构体数组、结构指针以及结构在函数参数传递中的应用。通过示例代码,展示了如何操作和使用枚举和结构体。
摘要由CSDN通过智能技术生成

枚举

枚举

  • 枚举是一种用户自定义的数据类型,它用关键字enum,以如下语法来声明:
    enum枚举类型的名字{名字0,名字1,…,名字n};
  • 枚举类型名字通常并不真的被使用,要用的是在大括号里的名字,因为它们就是常量符号,它们的类型是int,值则依次从0到n。
    如:enum colors{red,yellow,green};
  • 创建了三个常量,red的值是0,yellow是1,green是2
  • 当需要一些可以排列起来的常量值时,定义枚举的意义就是给了这些常量名字
  • 枚举量可以作为值
  • 枚举类型可以跟上enum作为类型
  • 但实际上,是以整数来做内部计算和外部输入输出的
    eg:
#include <stdio.h>
enum color { red, yellow,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);
}

自动计数的枚举

#include <stdio.h>
enum COLOR {RED,YELLOw,GREEN,NumCOLORS};     //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= "unknown";
	}
	printf("你喜欢的颜色是%s\n", colorName) ;
	
	return 0;
}

这样需要遍历所有的枚举量或者需要建立一个用枚举量做下标的数组的时候就很方便了。

枚举量

  • 声明枚举量的时候可以指定值
  • enum COLOR{RED = 1,YELLOW , GREEN = 5};
#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);  //5
	return 0;
}

枚举只是int

  • 即使给枚举类型的变量赋的不存在的整数值,也没有任何waring或error
#include <stdio.h>
enum COLOR {RED=1,YELLOw,GREEN=5,NumCOLORS};
int main(int argc, char const *argv[])
{
	enum COLOR color = 0;
	printf( "code for GREEN is %d\n",GREEN);
	printf("and color is %d\n", color) ;
	return 0;
}

  • 虽然枚举类型可以当作类型使用,但实际上很少用
  • 如果有意义上排列的名字,用枚举比const int方便
  • 枚举比宏(macro)好,因为枚举有int类型

结构

结构

  • 声明结构类型
#include <stdio.h>
struct date {
	int month;
	int day;
	int year;
};
int main(int argc, char const *argv[ ])
{
	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;
}

  • 和本地变量一样,在函数内部声明的结构类型只能在结构内部使用
  • 所以通常在函数外部声明结构类型,这样就可以被多个函数使用。

声明结构的形式

  • struct point {
    int x;
    int y;
    }
    struct point p1,p2;
    p1,p2都是point里面x和y的值

  • struct {
    int x;
    int y;
    }p1,p2;
    p1,p2都是一种无名结构,里面有x和y

  • 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;          结构变量
	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;
}


结构的初始化

#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 thismonth = {.month=7, .year=2014};  //第二种,day没有赋值,自动补零
	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
    p1.x
    p1.y

结构运算

  • 要访问整个结构,直接用结构变量的名字
  • 对于整个结构,可以做赋值、取地址,也可以传递给函数
    eg: p1 = (struct point){5,10} //相当于p1.x = 5; p1.y = 10;
    p1 = p2; //相当于p1.x=p2.x ; p1.y=p2.y;
    而数组不能这样做

结构指针

和函数不同的是,结构变量的名字并不是结构变量的地址,必须使用&运算符
eg; struct date *pDate = &today

结构与函数

结构作为函数参数
int number (struct date b)

  • 整个结构可以作为参数的值传入函数
  • 这时候是在函数内新建一个结构变量,并复制调用者结构的值
  • 也可以返回一个整个结构
  • 这与数组完全不同
    eg:明天是几年几月几号
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 != numberOfDays (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.ln",
tomorrow.year, tomorrow.month, tomorrow.day);
	return 0;
}

int numberOfDays(struct date d)
{
	int days;
	const int daysPerMonth[12] = {312831303130313130313031};
	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一个结构
  • 如果我们打算写一个函数来读入结构
    错误例子:
#include <stdio.h>
struct point {
	int x;
	int y;
};
void getStruct(struct point);
void output(struct point);
void main( ) {
	struct point y = {0,0};
	getStruct(y);
	output(y);
}
void getStruct(struct point p) {  //该函数中p与main函数中y是不同的,在函数读入的p的数值之后,没有任何东西回到main所以y还是{0,0}
	scanf("%d",&p.x);
	scanf("%d",&p.y);
	printf("%d, %d",p.x, p.y);
}
void output(struct point p) {
	printf("%d,%d", p.x, p.y);
}
  • 这个输入函数中,创建了一个临时的结构变量,然后把这个结构返回给调用者
    正确例子:
    请添加图片描述请添加图片描述

结构指针作为参数

下面用一个例子来理解:

struct pointx getStruct(struct point*);
void output(struct point);
void print(const struct point *p);
int main(int argc, char const *argv[])
{
	struct point y = {00};
	getStruct(&y );
	output(y ) ;
	output(*getStruct(&y ) ) ; //将返回的结构指针取值
	print(getStruct(&y) ) ;
}
struct point* getStruct(struct point *p)  //传入结构指针
{
	scanf ( "%d", &p->x);  //指针p指的x的值,&则取这个值(x)的地址
	scanf ( "%d",&p->y );
	printf ( "%d,%d" ,p->x, p->y );
	return p;   //返回指针
}
void output(struct point p){   //传入结构值
	printf( "%d,%d",p.x, p.y);
}
void print(const struct point *p){
	printf("%d,%d",p->x,p->y); //p所指的x的值
}

指向结构的指针

struct date {
	int month;
	int day;
	int year;
}myday;
struct date *p = &myday;
(*p ).month = 12;
p->month = 12;

用->表示指针所指的结构变量中的成员

结构数组

struct date dates[100];
struct date dates[] = {{4,5,2005},{2,4,2005}};

eg:下一秒是什么

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

结构中的结构

请添加图片描述
请添加图片描述

结构中的结构数组

请添加图片描述

联合

自定义数据类型

  • c语言提供了一种叫做typedef的功能来声明一个已有的数据类型和新名字。比如:
    typedef int Length;
    使得Length成为int类型的别名
  • 这样,length这个名字就可以代替int出现在变量定义和参数声明的地方了
    Length a,b,len;
    Length number[10];

Typedef

  • 声明新类型的名字
  • 新的名字是某种类型的别名
  • 改善了程序的可读性
    请添加图片描述
    typedef char* string[10];
    string 是10个字符串的数组的类型

联合union

  • 储存:所有成员共享一个空间
    同一时间只有一个成员是有效的
    union的大小是其最大的成员
  • 初始化:对第一个成员做初始化
#include <stdio.h>
typedef union {
	int i;
	char ch[sizeof(int)];
}CHI;

int main(int 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;
}

输出:D2040000

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值