结构作为函数参数
int numberOfDays(struct date d)
{
}
◆ 整个结构可以作为参数的值传入函数
◆ 这时候是在函数内新建一个结构变量,并复制调用者的结构的值
◆ 也可以返回一个结构
◆ 这与数组完全不同
【例】给定日期,计算明天的日期:
#include <stdio.h>
struct date //日期的结构体
{
int month;
int day;
int year;
};
bool isLeap(struct date d); //是否闰年
int numberOfDays(struct date d); //本月有多少天
int main(int argc, const char* 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)) //today不是本月最后一天
{
tomorrow.day = today.day + 1;
tomorrow.month = today.month;
tomorrow.year = today.year;
}
else if (today.month == 12) //today是12月的最后一天
{
tomorrow.day = 1;
tomorrow.month = 1;
tomorrow.year = today.year + 1;
}
else //today是非12月的最后一天
{
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)) //d日期是2月且闰年
{
days = 29;
}
else //其他情况
{
days = daysPerMonth[d.month - 1];
}
return days;
}
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;
}
输入结构
◆ 没有直接的方式可以一次scanf() 一个结构
◆ 如果我们打算写一个函数来读入结构:
【错误的代码】
如下的程序,getStruct() 无法获取到main() 中的struct point y本身,只是得到了它的“值”:
#include <stdio.h>
struct point
{
int x;
int y;
};
void getStruct(struct point);
void output(struct point);
int main(int argc, char const* argv[])
{
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("p.x = %d, p.y = %d\n", p.x, p.y);
}
void output(struct point q)
{
printf("q.x = %d, q.y = %d\n", q.x, q.y);
}
可以看到,执行之后的结果,main() 中的struct point y并没有被修改,这是因为传参而不是将结构体本身传入函数,因此getStruct() 函数并没有去动main() 中的y的内容,导致在output(y) 时,output() 函数仍然得到的是 { 0, 0 }。
◆ 记住C在函数调用时是传值的
★ 所以getStruct() 函数中的p与main() 中的y是不同的,没有任何关系
★ 在函数读入了p的数值之后,没有任何东西回到main(),所以y还是{0 , 0}
解决的方案
◆ 之前的方案,把一个结构传入了函数,然后在函数中操作,但是没有返回回去
★ 问题在于传入函数的是外面那个结构体的克隆体,而不是指针
→ 传入结构和传入数组是不同的
◆ 在这个输入函数中,完全可以创建一个临时的结构变量,然后把这个结构返回给调用者
#include <stdio.h>
struct point
{
int x;
int y;
};
struct point inputPoint(void);
void output(struct point);
int main(int argc, char const* argv[])
{
struct point y = inputPoint();
output(y);
return 0;
}
struct point inputPoint(void)
{
struct point p;
scanf("%d", &p.x);
scanf("%d", &p.y);
return p;
}
void output(struct point q)
{
printf("q.x = %d, q.y = %d\n", q.x, q.y);
}
◆ 结构指针作为参数
★ K&R说过:“If a large structure is to be passed to a function, it is generally more efficient to pass a pointer than to copy the whole structure”
指向结构的指针
struct date
{
int month;
int day;
int year;
} myday;
struct date* p = &myday;
(*p).month = 12; //两行代码语义是等价的
p->month = 12; //“->”是一个运算符
◆ 用“->”表示指针所指的结构变量中的成员
#include <stdio.h>
struct point
{
int x;
int y;
};
struct point* inputPoint(struct point*);
void output(const struct point*);
int main(int argc, char const* argv[])
{
struct point y = { 0, 0 };
output(inputPoint(&y)); //函数的执行进行串接
return 0;
}
struct point* inputPoint(struct point* p) //一个小套路,传入的指针p在写回函数的返回值
{
scanf("%d", &(p->x));
scanf("%d", &(p->y));
return p;
}
void output(const struct point* q) //参数写为const struct*类型以保证不修改q指向的内容
{
printf("q->x = %d, q->y = %d\n", q->x, q->y);
}