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是不同的

解决方案:

  1. 在这个输入函数中,完全可以创建一个临时的结构变量,然后把这个结构返回给调用者
#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*/
  1. 利用结构体指针参数
#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不是指针)
posted @ 2021-10-18 11:31  DL50  阅读(76)  评论(0编辑  收藏  举报