c语言学习笔记(函数详解)

int Add_Int(int a ,  int b); //这个是函数的声明

z = Add_Int (int x , int y);  //这个函数的调用是错的,不应该加int ,正确写法:z = Add_Int(x ,y);

int Add_Int(int a , int b)  //这个是函数的定义,不加分号

只有函数在被调用,局部变量,形参才在栈区

int Maxint(int a, int b) // 形参
{
	int c = a > b ? a : b;
	return c;  // 返回c的值的同时,把函数结束,把分配给函数的栈帧返回给系统但不是把c给max,而是把c的值放入到临时空间中去
}
int main()
{
	int x = 0, y = 0;
	int max = 0;
	scanf("%d %d", &x, &x);
	max = Maxint(x, y);  //实参
	printf("max = %d\n", max);
	return 0;
}

把实参给形参是从右想左赋值,也就是先把y的值赋给b,再把x的值赋给a

 举例子:要求从键盘中输入年份的整数year,通过程序判断该年是否为闰年

判断year年份是否是闰年,需要满足以下条件中的任意一个

1  该年能被4整除,同时不能被100整除

2  该年份能被400整除

函数写法:

法一:由于不是闰年就是平年,故只有两种可能,因此用bool型

bool Isleap(int year)
{
	if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
	{
		return true;
	}
	else
	{
		return false;
	}
}

这个是双分支,改成单分支为:

bool Isleap(int year)
{
	bool res = false;
	if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
	{
		res = true;
	}
	return res;
}

但是if 中本身也是bool值,故还可以简化

bool Isleap(int year)
{
	return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));
}

例二:输入year和month ,返回天数

上面写了平年和闰年的函数

bool IsLeap(int year)
{
	return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));
}
int Get_YM_Day(int year, int month)
{
	int day = 0;
	switch (month)
	{
	case 1: case 3: case 5: case 7: case 8: case 10: case 12:
		day = 31;
		break;
	case 4: case 6: case 9: case 11:
		day = 30;
		break;
	case 2:
		day = IsLeap(year) ? 29 : 28;
		break;
	}
	return day;
}
int main()
{
	int year, month, day;
	scanf_s("%d %d", &year, &month);
	day = Get_YM_Day(year, month);
	printf("year : %d month :%d day : %d", year, month, day);
	return 0;
}

但这种的健壮性不强,为什么呢?因为当月份输入是18时,显示为0,但实际上并没有18月,因此要对函数的合法性进行检测,怎么改呢?下面是更准确的写法

#define YEARERROR -1
#define MONTHERROR -2
bool IsLeap(int year)
{
	return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));
}
int Get_YM_Day(int year, int month)
{
	int day = 0;
	if (year < 1)  return YEARERROR;
	if (month < 1 || month > 12) return MONTHERROR;
	switch (month)
	{
	case 1: case 3: case 5: case 7: case 8: case 10: case 12:
		day = 31;
		break;
	case 4: case 6: case 9: case 11:
		day = 30;
		break;
	case 2:
		day = IsLeap(year) ? 29 : 28;
		break;
	}
	return day;
}
int main()
{
	int year, month, day;
	scanf_s("%d %d", &year, &month);
	day = Get_YM_Day(year, month);
	switch (day)  //在这里做一个判断
	{
	case YEARERROR :
		printf("year input error : %d\n", year);
		break;
	case MONTHERROR : 
		printf("month input error : %d\n", month);
		break;
	default:
		printf("year : %d month :%d day : %d", year, month, day);
		break;
	}
	return 0;
}

判断日期是否正确可以这样写:

if(day < 1 || day > Get_YM_Day(year , month))   return DAYERROR;

意思就是如果天数小于1或者天数大于上面函数输入年月后得到的天数时,就会返回天数错误

传递数值

void Swap_i(int a, int b)
{
	int tmp = a;
	a = b;
	b = tmp;
}
int main()
{
	int x = 10, y = 20;
	printf("%d %d \n", x, y);
	Swap_i(x, y);
	printf("%d %d\n", x, y);
	return 0;
}

得到输出的结果是

因为从主函数开始执行时,给main函数分配栈帧,再调用Swap_i 函数时分配栈帧,把实参的值给形参,即把y的值给 b ,x 的值 给a 。然后把a的值给tmp ,把b的值给a 再把tmp的值给b,但实参在另一个栈帧中,并不变,即此时输出的x仍是10,y 仍是20

传递地址 (什么类型的指针就存放什么类型变量的地址)

void Swap_i(int *ap, int *bp)
{
	int tmp = *ap;
	*ap = *bp;
	*bp = tmp;
}
int main()
{
	int x = 10, y = 20;
	printf("%d %d \n", x, y);
	Swap_i(&x, &y);
	printf("%d %d\n", x, y);
	return 0;
}

结果为

当解析*p时,系统的第一步先读取p的值,p也就是a的地址,下一步就通过这个地址去访问a

从主函数开始执行,给主函数分配栈帧,x 的值为 10 ,10的十六进制就是0a,由于是小端存储,因此为0a 00 00 00,在调用函数时,把y的地址给bp,再把x的地址给ap,当进入到函数时,把*ap也就是x本身的值给tmp,因此tmp为 0a 00 00 00 再把*bp 也就是y本身给*ap 也就是x本身,相当于把y的值给了x,接下来再把tmp的值给*bp ,即把tmp的值给了y,因此此时输出的是x = 20,y=10; 

形参 实参

c语言中不允许在函数中再定义函数

函数在调用时,先把实参的值传递给形参,之后函数开始正式调用

函数调用时发生的数据的传递是单向的,只能把实参的值传递给形参,而不能把形参的值反向传递给实参

两个例题:

1  、a , b , c 三个数找出其中最大值

int Max_Int(int a, int b)
{
	return a > b ? a : b;
}
int main()
{
	int a = 0, b = 0, c = 0;
	int max = 0;
	scanf("%d %d %d", &a, &b, &c);
	max = Max_Int(Max_Int(a, b), c);  //在这里调用了两次函数,简洁了许多
	printf("max = %d\n", max);
	return 0;
}

2 、a , b , c 三个数找出其中间值

void Swap_p(int* ap, int* bp)
{
	int tmp = *ap;
	*ap = *bp;
	*bp = tmp;
}
int Mid_Int(int a, int b, int c)
{
	if (a > b)
	{
		Swap_p(&a, &b);
	}
	if (b > c)
	{
		Swap_p(&b, &c);
	}
	if (a > b)
	{
		Swap_p(&a, &b);
	}
	return b;
}
int main()
{
	int a = 0, b = 0, c = 0;
	int mid = 0;
	scanf("%d %d %d", &a, &b, &c);
	mid = Mid_Int(a, b, c);
	printf("mid = %d\n", mid);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值