结构(笔记)

C语言结构作为函数的参数,此时是在函数内部直接建立了另一个外部结构的克隆体,将外面的结构直接复制过来后在函数的内部进行相应的运算。
与数组完全不同,数组传入的是指针,而结构体传入的是值。也可以返回整个结构。
例如下列代码段

#include <stdio.h>
#include <stdbool.h>

struct date {    //定义全局结构体,包含三个整型变量 
	int month;
	int day;
	int year;
};

bool isLeap(struct date d);  //需要一个结构体作为函数参数,函数返回类型为布尔型
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 ) {  //隐藏条件是today.month==12 && today.day==numberOfDays(today)
		tomorrow.day = 1;//注意隐含条件,表示今天所处的月份是12月份且今天是本月的最后一天时,和前面的if条件中相呼应 
		tomorrow.month = 1;
		tomorrow.year = today.year+1;   //年加一,其他置为1 
	}
	else {                       //其他情况,使月份加一,年份不变,天数置为1 
		tomorrow.day = 1;
		tomorrow. month = today.month+1;
		tomorrow.year = today.year;
	}     
/*
上述代码为,对当天进行运算,判断当天所处的月份的天数,月份,以及年份是闰年还是平年 
*/
		
	printf("Tomorrow's date is %i-%i-%i\n", 
	tomorrow.year, tomorrow.month, tomorrow.day );   //输出第二天的年份,月份以及具体哪一天 
	
	return 0;
}

int numberOfDays(struct date d)
{
	int days;
	
	const int daysPerMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
	//每个月有多少天 
	if ( d.month ==2 && isLeap(d) )
	{      //如果本月是2月且利用leap函数进行计算后当年的年份是闰年 
		days = 29;   //满足条件天数是29天 
	} else {
		days = daysPerMonth[d.month-1];
	}
	
	return  days;  //单一出口原则 
}


bool isLeap(struct date d)  //定义结构体,判断当天所在的年份是闰年还是平年,返回值为布尔值,true or false 
{
	bool leap = false;
	
	if ( (d.day%4 ==0 && d.year%100 !=0 ) || d.year%400 ==0 )
	{
		leap = true; 
	}
	
	return leap;
}

结构体函数输入结构
C语言中并没有直接的方式可以直接scanf一个结构体,需要自行编写一个输入结构函数
但是C语言的调用是传值的,在函数中的p和main中的y没有任何关系,在函数中没有返回值操作,所以在函数读入了P值后,没有任何东西回到main,所以y还是{0, 0}。具体代码如下

#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};  //定义结构变量,并设置初始值为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 12,返回值为12 12     0 0*/

解决方案一:
之前的方案,把一个结构传入了函数,然后在函数中操作,但是没有返回回去
问题在于传入函数的是外面那个结构的克隆体,而不是指针
传入结构和传入数组是不同的
在这个输入函数中,完全可以创建一个临时的结构变量,然后把这个结构返回给调用者
将代码段1改为代码段2

代码段1
void main()
{
	struct point y = {0,0};
	y = inputPoint( );
	output(y):
}
代码段2
struct point inputPoint()
{
	struct point temp;
	scanf(""%d",&temp.x):
	scanf("%d",&temp.y);
	return temp;
}

主代码如下

#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};  //定义结构变量,并设置初始值为0 0 
	y = getStruct();//调用时令y等于函数,两个结构变量可以互相赋值,这样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 12   返回值为12 12     12 12
*/

指向结构的指针,将前面的getStruct改为下面形式

#include <stdio.h>

struct point{  //定义结构 
	int x;
	int y;
};

struct point* 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};//定义结构变量并初始化为0 0 
	getStruct(&y);  //函数直接得到的是结构变量y的地址 
	output(y);      //输出函数得到结构变量,在函数内部克隆 
	output(*getStruct(&y));  //getstruct函数返回的是结构变量的指针,代表的是结构变量y的地址, *getStruct(&y)表示的是函数得到结构变量y的地址后,同时返回结构变量的地址,在函数的外层利用地址运算符号
	//即   *getStruct(&y) = y  (利用*取回函数所返回的那个东西)
	print(getStruct(&y));//函数得到的是结构变量y的指针 
	
	*getStruct(&y) = (struct point){1, 2}; //赋值 
	
	return 0;
}

struct point* getStruct(struct point *p) //不能加const,在函数运行过程中需要依据传入的结构变量的指针,访问到那个结构变量,并对里面的参数进行修改 
{
	scanf("%d",&p->x);//给结构体中的x赋值p->x表示的是p所指的那个结构变量里面的成员,运算符 -> 优先级要高于运算符 & 
	//“&p->x”操作具体步骤为,利用结构指针寻址找到对应结构变量,并在结构变量中定位到当前变量x,此时 p->x 的类型是x对应类型,程序中为整型int
	//再利用取地址符号 & 对整型变量p->x,即指针p所指的结构变量中的那个变量取地址,并进行赋值运算 
	scanf( "%d",&p->y);
	printf("%d,%d\n",p->x, p->y);//输出赋值后的内容, p->x 表示的是整型数据
	
	return p;//这里的p表示的是指针,其值代表的是结构变量的地址,传入此函数的是结构变量的指针 
}
/*
返回类型为指针,参数类型为指针,得到当前结构的地址后,在函数内进行运算 
并且在运算完成后将得到的那个结构体的指针返回到主函数,这样做的好处是,在函数执行完毕后,将指针返回到主函数中后,在其他函数中,利用*运算符进行访问时,可以更加方便快捷,如果不需要,此返回类型也可以是void等其他类型,同时返回的指针也可以交给其他函数进行运算
*/	

void output(struct point p)  //这里的p表示的是结构体p,不是指针,传入函数的是结构变量 
{
	printf("%d,%d\n",p.x,p.y);
}
/*
定义输出函数,且无需返回类型,函数的参数类型为结构变量,输出结构变量里面的参数 
*/

void print(const struct point *p) //函数参数加const表示在执行函数过程中不需要对结构变量里面的参数进行修改 
{
	printf("%d,%d\n",p->x,p->y);
}
/*
定义输出函数,且无需返回类型,函数的参数类型为结构指针,输出结构变量里面的参数值 
*/
/*
主函数程序中,每运行到getStruct函数时,程序需要输入一次,即主函数程序有几个getStruct,需要输入几次才会结束运行 
*/

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值