结构(当想用一个整体使用多个类型数据时)
介绍:是一个复合的数据类型,在里面有各种类型的变量(称为成员),一般放在主函数外面,在主函数里面可以直接使用自己定义的结构。
//语法形式如下
struct (类型名字){
int x;
int y;
int z;
………………
}(变量名字1,变量名字2,………………);//注意有分号!!!,可以在结构定义时定义变量,也可在主函数内定义
//使用时形式如下
struct+结构名称+变量名称;//要把struct带上
//调用其内的成员时形式如下
变量名称.其内成员名称 = 某个值;
e.g.运用结构输出年月日
#include<stdio.h>
int main()
{
struct date{
int month;
int day;
int year;
}
struct date today;//用我们定义的struct date数据类型定义today这个变量,此时today内含有month,day,year三个成员
today.month = 07;
today.day = 31;
today.year = 2014;
//也可写成以下形式
struct date today = {07, 31, 2014};
struct date today = {.month = 07, .year = 2014};//没有赋值的会自动初始化为0,17-18行也称为结构的初始化
printf("Today's date is %i-%i-%i"today.month,today.day,today.year);/*输入为&today.month。 %d匹配十进制,而%i可以匹配八进制、十进制、十六进制表示的整数。例如: 如果输入的数字有前缀 0(018、025),%i将会把它当作八进制数来处理,如果有前缀0x (0x54),它将以十六进制来处理。 */
}
结构的运算
struct date{
int x;
int y;
}p1,p2;
p1 = p2//相当于p1.x = p2.x ; p1.y = p2.y。数组初始化后不能两个数组比较,而结构可以
p2.y = 2;
printf("%i %i", p1.x, p1.y);
printf("%i %i", p2.x, p2.y);//你会发现输出p1,p2时两个会不一样,说明p1,p2是两个东西,对p2操作,p1的值是不会改变的
结构与函数
结构可作为函数参数
int numberofDays(struct date d)//它在函数内为新的结构变量,与主函数那个不相同,也就是和普通变量的一样的。而数组是主函数和其他函数都是一样的
没有直接的方式可以一次性scanf一整个结构,但是我们可以自己写一个结构来读入
# include<stdio.h>
struct point{
int x;
int y;
};
void getstruct(struct point p);
void outstruct(struct point p);
void main()
{
struct point y = {0, 0};
getstruct(y);
outstruct(y);
}
void getstruct(struct point p)
{
scanf("%d", &p.x);
scanf("%d", &p.y);
printf("%d %d", p.x, p.y);
}
void outstruct(struct point p)
{
printf("%d %d", p.x, p.y);
}
//输入1 2后这个会输出1 2,但是在outstruct中输出为0,因为传进去的只是值,离开了getstruct就没了,所以要实现用结构作为输入,可以用以下方法
//方法一 在这个输入函数中创建一个临时的结构变量,把此结构调回给主函数
struct point getstruct()
{
struct point p;
scanf("%d%d", &p.x, &p.y);
printf("%d%d", &p.x, &p.y);
return p;
}
void outstruct(struct point p)
{
printf("%d %d", p.x, p.y);
}
//方法二 方法一比较费空间和时间,所以更好的方式为传指针,在结构中取结构变量中的成员一开始用(*p).x,但是因为打的符号过多所以简化为p -> x
#include<stdio.h>
void main()
{
struct point y = {0, 0};
getstruct(&y);
outstruct(y);
output(*getstruct(&y));//输出*p
print(getstruct(&y));//传入指针p
getstruct(&y)->x = 0;//通过指针改变y的成员x
*getstruct(&y) = (struct point){1, 2};//通过指针修改结构y
}
struct point* getstruct(struct point *p)//定义一个结构指针
{
scanf("%d%d", &p->x, &p->y);
printf("%d%d", p->x, p->y);
return p;//返回的是一个地址
}
void outstruct(struct point p)
{
printf("%d %d", p.x, p.y);
}
void print(const struct point *p)//只是输出,所以不需要改变,定义为const
{
printf("%d %d", p->x, p->y);
}
结构与指针
与数组名字不同,结构变量名字并不是地址,故要用&去取地址
当访问结构中的成员时,用p -> x的 ->,形式:定义的指针 + ‘->’ +结构体内的成员名称
结构与数组
相当于数组,数组可以做的它也可以做
struct time{
int hour;
int minutes;
int seconds;
}
//定义时
struct time testtimes[5]={
{11,59,59},{12,0,0},{1,29,59},{8,9,0},{0,0,0}
};
//取数组元素的成员时
testtimes[i].hour, testtimes[i].minutes, testtimes[i].seconds
结构的嵌套
结构内不仅仅只能放普通变量,也可放结构变量
struct time{
int hour;
int minutes;
int seconds;
};
struct date{
struct date sdate;//可以嵌套自己的结构类型
struct time stime;//也可以嵌套其他的结构类型
};//定义了一个结构,第一个成员为sdate,第二个成员为stime
如何访问结构中的结构的成员?
date.stime.hour 或 (date.stime).hour//访问date中的stime的hour
int *p = &date;
p -> stime.hour//定义的指针p指向date,用指针p取stime.hour的值来操作
//!!!没有p -> stime->hour这种形式,因为stime不是指针
它还可以用结构嵌套结构去定义结构数组等………………
#include<stdio.h>
struct point{
int x;
int y;
};
struct rectangle{
struct point p1;
struct point p2;
};
int main()
{
int i;
struct rectangle rects[ ] = {
{{1,2},{3,4}},
{{5,6},{7,8}}
};//定义一个数组rects内有两个成员,成员各自有两个成员
}
自定义数据类型(typedef)
声明已有数据类型的新名字,如
typedef int length;
//length成为int类型的别名
length a, b, len;
length numbers[10];
typedef char *string[10];//string是10个字符类型的数组的类型
typedef struct{
int month;
int day;
int year;
}date;//将此类型的结构命名为date,以后直接使用date定义变量,就少打一些符号,改善了程序的可读性
联合
和struct类似,区别是结构体struct 各成员各自拥有自己的内存,各自使用互不干涉 ,同时存在的, 一个struct变量的总长度等于所有成员的长度之和;而联合体union 各成员共用一块内存空间,并且同时只有一个成员可以得到这块内存的使用权 (对该内存的读写),各变量共用一个内存首地址。 因而,联合体比结构体更节约内存。
union anelt{
int i;
char c;
}elt1, elt2;
elt1.i = 4;
elt2.c = 'a';
elt2.i = 0xDEADBEEF;
枚举
这是一种用户定义的数据类型,关键字为enum,常量才可用(要定义多个const时),以以下语法来声明
enum 枚举类型名称 {名字0,……,名字n};
#include <stdio.h>
enum color {red, yellow, green};//定义了color的数据类型,color放在{}后面也可以,它的值是从0开始的,此内的red=0,yellow=1, green=2;
/*注1:可在最后放置一个"num + 枚举类型名称"的形式来统计枚举内有多少个常量,即 enum color {red, yellow, green, numcolor},方便进行某些操作*/
/*注2:可指定值,不一定令其从0开始,即enum color {red = 1, yellow, green = 5},此时yellow=2,就是跟着上一个值加一*/
int main()
{
enum color t = red;
scanf("%d", &t);//可当作int来进行输入输出(可用%d)
f(t);
return 0;
}
void f(enum color c)
{
printf("%d", c);//可当作int来进行输入输出(可用%d)
}
拓:枚举在c语言中并不好用,一般拿来定义符号量;枚举比宏好,因为枚举有int类型。