C语言学习笔记(七)结构类型

一、枚举

(1)常量符号化

  • 用符号而不是具体的数字来表示程序中的数字
const int red=0;
const int yellow=1;
const int green=2;

(2)枚举

  • 用枚举而不是定义独立的const int变量
  • 枚举是一种用户定义的数据类型,它用关键字enum以如下语法来声明:
//声明
enum 枚举类型名字(名字0...,名字n)//定义
enum COLOR{RED,YELLOW,GREEN};
  • 枚举类型名字通常并不真的使用,要用的是在大括号里的名字,因为它们就是常量符号,它们的类型是int,值则一次从0到n。
  • 上面定义COLOR创建了三个常量:red的值是0,yellow是1,而green是2。
  • 当需要一些可以排列起来的常量值时,定义枚举的意义就是给这些常量值名字。
#include<stdio.h>
enum color{red,yellow,green};
void f(enum color c);
int main(int argc,char const *argv[])
{
	enum color t=red;
	scanf("%d",&t);
	f(t);
	return 0;
}
void f(enum color c)
{
	printf("%d\n",c);
}
  • 枚举量可以作为值
  • 枚举类型可以跟上enum作为类型
  • 但是实际上拾遗整数来作内部计算和外部输入输出的
  • 套路:自动计数的枚举
//这样需要遍历所有的枚举变量或者需要建立一个用枚举量做下标的数组的时候就很方便了 
enum color={red,yellow,green.NumColors};
  • 枚举量
    • 声明枚举量的时候可以指定值
enum color{red=1,yellow,green=5};
  • 枚举只是int
    • 即使给枚举类型的变量赋不存在的整数值也没有任何warning或error
  • 枚举
    • 虽然枚举类型可以当做类型使用,但是实际上很少用
    • 如果有意义上排比的名字,用枚举比const int方便
    • 枚举比宏(macro)好,因为枚举有int类型

二、结构

(1)结构类型

1.1 声明结构类型

#include<stdio.h>
int main(int argc,char const *argv[])
{
	struct date{
		int month;
		int day;
		int year;
	};
	struct date today;
	today.month=04;
	today.day=24;
	today.year=2020;
	printf("Today's data is %i-%i-%i.\n",today.year,today.month,today.day);
	return 0;
}

1.2 在函数内/外?

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

1.3 声明结构的形式

//形式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 的值

1.4 结构的初始化

#include<stdio.h>
struct date{
		int month;
		int day;
		int year;
};
int main(int argc,char const *argv[])
{
	struct date today={04,24,2020};
	struct date thismonth={.month=4,.year=2020};
	printf("Today's data 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;
}

1.5 结构成员

  • 结构和数组有点像
  • 数组用[]运算符和下标访问其成员
    • a[0]=10;
  • 结构用.运算符和名字访问其成员
    • today.day
    • student.firstName

1.6 结构运算

  • 要访问整个结构,直接用结构变量的名字
  • 对于整个结构,可以做赋值、取地址,也可以传递给函数参数
    • p1 = (struct point){5,10};
    • p1=p2;
#include<stdio.h>
struct date{
		int month;
		int day;
		int year;
};
int main(int argc,char const *argv[])
{
	struct date today;
	today=(struct date){04,24,2020};
	struct date day;
	day=today;
	day.year=2019;
	printf("Today's data is %i-%i-%i.\n",today.year,today.month,today.day);
	printf("The day's date is %i-%i-%i.\n",day.year,day.month,day.day);
	return 0;
}

1.7 结构指针

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

(2)结构与函数

2.1 结构作为函数参数

int numbeOfDays(struct date d)
  • 整个结构可以作为参数的值传入函数
  • 这时候是在函数内新建一个结构变量,并复制调用者的结构的值
  • 也可以返回一个结构

2.2 输入结构

  • 没有直接的方式可以一次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);
int main(int argc,char const *argv[])
{
	struct point y={0,0};
	getStruc(y);
	output(y);
	return 0;
}
void getStruct(struct point p){
	scanf("%d",&p.x);
	scanf("%d",&p.y);
	printf("%d,%d\n",p.x,p.y);
}
void output(struct point p){
	printf("%d,%d\n",p.x,p.y);
}
  • 解决的方案
    • 之前的方案,把一个结构传入了函数,然后在函数中操作,但是没有返回去
      • 问题在于传入函数的是外面那个结构的克隆体,而不是指针
        • 传入结构和传入数组是不同的
    • 在这个函数中完全可以创建一个临时的结构变量,然后把这个结构返回给调用者
#include<stdio.h>
struct point{
	int x;
	int y;
};
struct getStruct(void);
void output(struct point);
int main(int argc,char const *argv[])
{
	struct point y={0,0};
	y=getStruct();
	output(y);
	return 0;
}
struct getStruct(void){
	struct point p;
	scanf("%d",&p.x);
	scanf("%d",&p.y);
	return p;
}
void output(struct point p){
	printf("%d,%d\n",p.x,p.y);
}

2.3 指向结构的指针

  • 用->表示指针所指的结构变量中的成员
struct date{
	int month;
	int day;
	int year;
}myday;
struct date *p=&myday;
(*p).month = 12;
p->month =12;

//2.2修改后代码
#include<stdio.h>
struct point{
	int x;
	int y;
};
struct getStruct(struct point*);
void output(struct point);
void print(const struct point *p);
int main(int argc,char const *argv[])
{
	struct point y={0,0};
	getStruct(&y);
	output(y);
	output(*getStruct(&y));
	print(getStruct(&y));
	return 0;
}
struct getStruct(struct point *p){
	scanf("%d",&p->x);
	scanf("%d",&p->y);
	return p;
}
void output(struct point p){
	printf("%d,%d\n",p.x,p.y);
}
void print(const struct point p){
	printf("%d,%d\n",p->x,p->y);
}

(3)结构中的结构

struct dateAndTime{
	struct date sdate;
	struct time stime;
};

三、联合

(1)类型定义

  • 自定义数据类型(typedef)
    • C语言提供了一个叫做typedef的功能来声明一个已有已有的数据类型的新名字。比如:
//使得Length成为int类型的别名。
typedef int Length;
  • 这样,Length这个名字就可以代替int出现在变量定义和参数声明的地方了:
Length a,b,len;
Length numbers[10];
  • 声明新的类型的名字
    • 新的名字是某种类型的别名
    • 改善了程序的可读性
typedef char *a[] String;
typedef long int64_t;
typedef struct ADate{
	int month;
	int day;
	int year;
} Date;
int64_t i=10000000;
Date d = {9,1,2005};

(2)联合

  • 存储
    • 所有的成员共享一个空间
    • 同时只有一个成员是有效的
    • 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++){
		peintf("%02hhx",chi.ch[i]);
	}
	printf("\n");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值