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,需要输入几次才会结束运行
*/