C语言 结构体
结构体
1.声明结构的形式
1.1第一种形式
上面去声明结构
下面去定义变量
#include <stdio.h>
struct date {//声明:struct 结构名 {};
int month;
int day;
int year;
};
int main() {
struct date today;//使用结构的时候前面要跟上结构的名字
today.month=07;
today.day=31;
today.year=2014;
printf("Today's data is %i-%i-%i.\n",
today.year,today.month,today.day
);
return 0;
}
- 在函数内部声明的结构类型只能在函数内使用
- 所以我们通常在函数外部声明结构类型,这样可以被多个函数所使用了
1.2第二种形式
没有结构的名字,p1和p2是一种无名结构,里面有x和y,不会在其他地方使用
struct{
int x;
int y;
}p1,p2
//p1和p2里面有x,y
1.3第三种形式
struct point{//定义结构
int x;
int y;
}p1,p2;//声明变量
//p1和p2都是point里面的有x和y的变量
2.结构变量
调用形式:变量名.成员名
2.1结构变量的初始化
可以给特定的值进行初始化
- 方位为{值1,值2,值3}按照顺序给值,先定义的为第一个值,以此类推
可以指定结构成员进行初始化
- 方法为
- 没有给值的成员变量的值,会初始化为0和数组类似
#include <stdio.h>
struct date {
int month;
int day;
int year;
};
int main() {
struct date today= {07,31,2014};
struct date thismonth= {.month=7, .year=2014};
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;
}
//Today's data is 2014-7-31.
//This month is 2014-7-0.
3.结构成员
- 结构的单元可以是不同的类型,数组中的单元必须是同一类型
- 结构同
.
运算符和名字访问其成员,数组用数组名[下标]
来访问
4.结构运算
要访问整个结构,直接结构变量的名字
- 对于整个结构,可以做赋值、取地址,也可以传递给函数做参数
pl =(struct point){5,10};//把{5,10}强制转换为 point 结构变量
pl.x=5;
pl.y=10;
p1=p2; //相当于p1.x=p2.x;pl.y=p2.y;
例如:
#include <stdio.h>
struct date {
int month;
int day;
int year;
};
int main() {
struct date today;
today=(struct date) {
07,31,2014
};
struct date day;
day=today;
printf("Today's data is %i-%i-%i.\n",
today.year,today.month,today.day
);
printf("The day's data is %i-%i-%i.\n",
day.year,day.month,day.day
);
return 0;
}
5.结构指针
和数组不同,结构变量的名字并不是结构变量的地址,必须使用&运算符
struct date *pDate = &today;
#include <stdio.h>
struct date {
int month;
int day;
int year;
};
int main() {
struct date today;
today=(struct date) {
07,31,2014
};
struct date day;
day=today;
struct date *pDate = &today;
printf("Today's data is %i-%i-%i.\n",
today.year,today.month,today.day
);
printf("The day's data is %i-%i-%i.\n",
day.year,day.month,day.day
);
printf("address of today is %p\n",pDate);
return 0;
}
6.结构作为函数的参数
int number0fDays(struct date d)
- 整个结构可以作为参数的值传入函数
- 这时候是在函数内新建一个结构变量,并复制调用者的结构的值
- 也可以返回一个结构
案例:
6.1计算明天的日期
#include <stdio.h>
#include <stdlib.h>
struct date {
int month;
int day;
int year;
};
bool isLeap(struct date d); //这个函数用于判断是否是闰年
int number0fDays(struct date d);//这个函数用于判断输入的月份有几天
int main() {
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 data is %i-%i-%i.\n",
tomorrow.year,tomorrow.month,tomorrow.day
);
return 0;
}
int number0fDays(struct date d) {
int days;
const int daysPerMonth[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
//一个字面量int类型的数组
if( d.month==2 &&isLeap(d)) { //若为闰年 2月就为29天
days=29;
} else {
days=daysPerMonth[d.month-1];
}
return days;
}
//判断是否是闰年,闰年的二月有29天
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;
}
7.输入结构
-
没有直接的方式可以一次scanf一个结构
-
如果我们打算写入一个函数来读入结构
#include <stdio.h> struct point{ int x; int y; }; void getStruct(struct point p); void output(struct point p); int main() { struct point y={0,0}; getStruct(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); } //12 23 //12,23 //0,0 可以看到值并没有传回来,再一次调用还是0和0
-
所以在函数中的p与main中的y是不同的
解决方案:
- 在这个输入函数中,完全可以创建一个临时的结构变量,然后把这个结构返回给调用者
#include <stdio.h>
struct point{
int x;
int y;
};
struct point getStruct(void);
void output(struct point p);
int main()
{
struct point y={0,0};
y=getStruct();
output(y);
return 0;
}
struct point getStruct(void)
{
//定义一个结构变量,并返回回去
struct point p;
scanf("%d",&p.x);
scanf("%d",&p.y);
printf("%d,%d\n",p.x,p.y);
return p;
}
void output(struct point p)
{
printf("%d,%d\n",p.x,p.y);
}
/*12 23
12,23
12,23*/
- 利用结构体指针参数
#include <stdio.h>
struct point{
int x;
int y;
};
struct point *getStruct(struct point *p);
//传入一个struct point类型的指针p,并返回一个struct point类型的指针getStruct
void output(struct point p);
//传入一个 struct point类型 p
void print(const struct point *p);
//传入一个 struct point的指针 p
int main()
{
struct point y={0,0};
getStruct(&y);
output(y);
output(*getStruct(&y));
print(getStruct(&y));
*getStruct(&y)=(struct point){1,2,3};
return 0;
}
struct point *getStruct(struct point *p)//定义一个结构变量,并返回回去
{
scanf("%d",&p->x);
scanf("%d",&p->y);
printf("%d,%d\n",p->x,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);
}
8.指向结构的指针
struct date{
int month;
int day;
int year;
}myday;
struct date *p= &myday;
(*p).month =12;//一般不建议这么写
p->month =12;
- 用->表示指针所指的结构变量中的成员
9.结构数组
struct date dates[100];
struct date dates[]={{4,5,2005},{2,4,2005}}
//dates[1]:{4}
示例:
#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,17}
};
int i;
for (i=0; i<5; ++i) {
printf("Time is %.2i:%.2i:%.2i \n",
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;
}
}
}
return now; //返回结构体
}
10.结构中的结构
struct dateAndTime{
struct date sdate;
struct time stime;
};
10.1嵌套的结构
struct point{
int x;
int y;
};
struct rectangele{
struct point pt1;
struct point pt2;
};
如果有变量
struct rectangele r;
r.pt1.x,r.pt1.y //.pt1是一个结构
r.pt2.x和r.pt2.y
如果有变量定义:
struct rectangele r,*rp;
rp=&r;
那么下面的四种运算形式是等价的
r.pt1.x
rp->pt1.x
(r.pt1).x
(rp->pt1).x
但是没有rp->pt1->x(因为pt1不是指针)