电视台网站建设方案,网上购物app排行榜,丽水市莲都区建设局网站,推动高质量发展的必要性一、函数的概念
•C语⾔中的函数#xff1a;⼀个完成某项特定的任务的⼀⼩段代码 •函数又被翻译为子函数#xff08;更准确#xff09; •在C语⾔中我们⼀般会⻅到两类函数#xff1a;库函数 ⾃定义函数
二、库函数
1 .标准库和头文件
•C语⾔的国际标准ANSIC规定了⼀…一、函数的概念
•C语⾔中的函数⼀个完成某项特定的任务的⼀⼩段代码 •函数又被翻译为子函数更准确 •在C语⾔中我们⼀般会⻅到两类函数库函数 ⾃定义函数
二、库函数
1 .标准库和头文件
•C语⾔的国际标准ANSIC规定了⼀些常⽤的函数的标准被称为标准库那不同的编译器⼚商根据ANSI提供的C语⾔标准就给出了⼀系列函数的实现这些函数就被称为库函数 •库函数相关头文件https://zh.cppreference.com/w/c/header
2.库函数的使用方法
1库函数学系工具链接
•C/C官方的链接https://zh.cppreference.com/w/c/header •cplusplus.comhttps://legacy.cplusplus.com/reference/clibrary/
2库函数使用顺序
•包含头文件头文件中声明了库函数的原型告诉编译器函数的名称、返回类型和参数类型 •调用函数调用函数时需要按照函数的原型提供正确的参数并根据需要处理返回值
注意事项 • 参数类型和数量调用函数时确保提供的参数类型和数量与函数原型一致 • 库函数的限制了解库函数的使用限制和前提条件某些函数对输入参数有特定的要求
3举例库函数 sprt
• 库函数sprt的功能:Compute square root(计算平方根) 和Returns the square root of x返回平⽅根 • sqrt的头文件是math.h
#include stdio.h//scanf printf的头文件
#include math.h//sqrt 的头文件
int main()
{double n,r;scanf(%lf, n);r sqrt(n);//调用函数printf(%lf, r);return 0;
}三、自定义函数
1.自定义函数的语法形式
return_type fun_name(形式参数)
{}•return_type是⽤来表⽰函数计算结果的类型(int float double char…)返回类型可以是void表示什么都不返回 •fun_name是函数名,函数名尽量要根据函数的功能起 •形式参数函数的参数也可以是void明确表⽰函数没有参数。如果有参数要交代清楚参数的类型和名字以及参数个数 •{}括起来的是函数体
2.自定义函数简单举例
写⼀个除法函数完成2个浮点型变量的除法法操作
#include stdio.h
double Division(double x, double y)
{double z x / y;return z;
}
int main()
{double a, b, result;scanf(%lf %lf, a, b);//输入result Division(a, b);//调用除法函数完成a和b相除//求商的结果放在result中printf(%lf\n, result);//输出return 0;
}Division函数可以简化为
double Division(double x, double y)
{return x / y;
}注意 •函数的参数部分需要交代清楚参数个数每个参数的类型是什么形参的名字是什么
上⾯只是⼀个例⼦未来我们是根据实际需要来设计函数函数名、参数、返回类型都是可以灵活变化的
四、形参和实参
以上面的代码为例
#include stdio.h
double Division(double x, double y)
{double z x / y;return z;
}
int main()
{double a, b, result;scanf(%lf %lf, a, b);//输入result Division(a, b);//调用除法函数完成a和b相除//求商的结果放在result中printf(%lf\n, result);//输出return 0;
}1.实参
result Division(a, b);•调⽤Division函数时传递给函数的参数a和b称为实际参数简称实参 •实际参数就是真实传递给函数的参数
2.形参
double Division(double x, double y)•函数名Division后的括号中写的x和y称为形式参数简称形参 •如果只是定义了Division函数⽽不去调⽤的话 Add 函数的参数x和y只是形式上存在不会向内存申请空间,所以叫形式参数。形式参数只有在函数被调⽤的过程中为了存放实参传递过来的值才向内存申请空间这个过程是形参的实例化
3.形参和实参的关系
•形参和实参各⾃是独⽴的内存空间 x和y确实得到了a和b的值但是x和y的地址和a和b的地址是不⼀样的所以我们可以理解为形参是实参的⼀份临时拷⻉
五、return语句
运用return的注意事项
1.函数中有可能出现return也可能没有
void menu()//无需返回任何类型的函数
{~~~~~~~
}2.return后边可以是⼀个数值也可以是⼀个表达式如果是表达式则先执⾏表达式再返回表达式的结果
例子写一个函数判断一个整数是奇数是偶数是偶数返回0是奇数返回1
return 后面是数值
#include stdio.h
int judge(int x)
{if (x % 2 0){return 0;//数值}if (x % 2 1){return 1;//数值}
}
int main()
{int n 0;scanf(%d, n);int ret judge(n);if (ret 1){printf(奇数);}if(ret 0){printf(偶数);}return 0;
}return 后面是表达式
#include stdio.h
int judge(int x)
{return x % 2;//表达式
}结果都可以正确判断奇偶
3.return后边也可以什么都没有直接写return; 这种写法适合函数返回类型是void的情况 •return;适合一个函数在执行的过程遇到某个条件需要提前返回但是不需要带回任何值的情况
4.return语句执⾏后函数就彻底返回后边的代码不再执⾏
例子输入一个数如果是偶数输出I LOVE A和I LOVE B,如果是奇数输出I LOVE A
#include stdio.h
void test(int x)
{printf(I LOVE A\n);if (x % 2 1){return;//输入的是奇数直接返回下面的语句不会执行}printf(I LOVE B\n);
}
int main()
{int n 0;scanf(%d, n);test(n);return 0;
}结果
5.return返回的值和函数返回类型不⼀致系统会⾃动将返回的值转换为函数的返回类型
举例
#include stdio.h
int test()//函数的返回类型是整型
{return 3.5;// 需要返回的数字是浮点型// return的返回类型与函数的不同// 系统会⾃动将return返回的值转换为函数的返回类型// return返回的值为3
}
int main()
{double r test();printf(%.1f, r);//输出一位小数3.0
}6.如果函数中存在if等分⽀的语句则要保证每种情况下都有return返回否则会出现编译错误
举例
#include stdio.h
double test(double x)
{if (x 1){return 3.5;// n!1的时候有些编译器的函数返回值是不可预测的}
}
int main()
{double n 0;scanf(%lf, n);double r test(n);printf(%.1f, r);return 0
}编译器会报错
7.函数的返回类型如果不写编译器会默认函数的返回类型是int
举例
#include stdio.h
test()//函数无返回类型默认返回类型是int
{return 3.5;//返回的是浮点型
}
int main()
{double r test();//函数真正值是3printf(%.1f, r);//输出一位小数3.0
}结果
8.函数写了返回类型但是函数中没有使⽤return返回值那么函数的返回值是未知的
举例
#include stdio.h
int test()
{//没有return
}
int main()
{int r test();printf(%d, r);
}结果
六、数组做函数参数
数组传参的⼏个重点知识 • 函数的形式参数要和函数的实参个数匹配 • 函数的实参是数组形参也是可以写成数组形式的 • 形参如果是一维数组数组大小可以省略不写 • 形参如果是二维数组行可以省略但 是列不能省略 • 数组传参形参是不会创建新的数组的 • 形参操作的数组和实参的数组是同一个数组
举例写两个函数一个函数设置数组的值一个负责输出函数的值
#include stdio.h
void set_arr(int arr[], int sz)//设置对应的形参
{int i 0;for (i 0; i sz; i){arr[i] i;//设置arr数组的值0~9}
}void printf_arr(int arr[], int sz)//设置对应的形参{int i 0;for (i 0; i sz; i){printf(%d , arr[i]);//输出arr数组的值0~9}
}
int main()
{ int arr[10] { 0 };//计算数组的元素个数int sz sizeof(arr) / sizeof(arr[1]);//设置数组的值set_arr(arr,sz);//传入arr数组和数组的元素个数//书橱数组的值、printf_arr(arr, sz);//传入arr数组和数组的元素个数return 0;
}结果
七、嵌套调用和链式访问
1.嵌套调用
嵌套调用就是在函数中调用其他函数
举例计算某年某月有多少天 逻辑 1.每个月的天数通常是固定的除了二月份 • 一月1月31天 • 二月2月28天或29天闰年 • 三月3月31天 • 四月4月30天 • 五月5月31天 • 六月6月30天 • 七月7月31天 • 八月8月31天 • 九月9月30天 • 十月10月31天 • 十一月11月30天 • 十二月12月31天 2. 判断闰年对于二月份需要判断该年是否为闰年 3. 闰年的判断规则是年份能被4整除但不能被100整除或者能被400整除 4. 计算天数根据月份和是否为闰年返回相应的天数 • 如果是二月份且是闰年则返回29天 • 如果是二月份但不是闰年则返回28天 • 对于其他月份直接返回固定的天数31天或30天
#include stdio.h//判断闰年
int is_LeapYear(int year)
{if ((year % 4 0 year % 100 ! 0) || (year % 400 0)){return 29;}else{return 28;}
}//判断有多少天
int day_In_month(int year, int month)
{switch (month){//有31天的月份{case 1:case 3:case 5:case 7:case 8:case 10:case 12:return 31;}//有30天的月份{case 4:case 6:case 9:case 11:return 30;}//二月28天或29天闰年case 2:{return is_LeapYear(year);//判断闰年}}
}
int main()
{int year, month, day;regain1:printf(请输入你要查询的年和月);regain2:while (scanf(%d %d, year, month) ! EOF){//判断年月输入是否正确if (year 0 || month 0 || month12){if (year 0 (month 0 month 12)){printf(年份输入错误请输 (year0)的数\n请重新输入你要查询的年和月);goto regain2;}if (year 0 (month 0 || month 12)){printf(月份输入错误请输入(month0 month12)的数\n请重新输入你要查询的年和月);goto regain2;}if (year 0 (month 0 || month 12)){printf(年份和月份输入错误请输入(year0 month0 month12)的数\n请重新输入你要查询的年和月);goto regain2;}}day day_In_month(year, month);printf(%d年%d月有%d天\n, year, month, day);goto regain1;}return 0;
}• main 函数调⽤ scanf 、 printf day_In_month • day_In_month 函数调⽤ is_LeapYear
2.链式访问
链式访问就是将⼀个函数的返回值作为另外⼀个函数的参数
例子printf的返回值 •printf函数返回的是打印在屏幕上的字符的个数 •printf的详细内容https://blog.csdn.net/Siri_s12/article/details/144370792?spm1001.2014.3001.5501
#include stdio.h
int main()
{printf(%d, printf(%d, printf(%d, 43)));return 0;
}•第三个printf打印43在屏幕上打印2个字符再返回2 •第⼆个printf打印2在屏幕上打印1个字符再放回1 •第⼀个printf打印1 所以屏幕上最终打印4321
八、函数的声明和定义
1.单个文件
函数的定义实现函数功能的代码
//判断闰年
int is_LeapYear(int year)
{if ((year % 4 0 year % 100 ! 0) || (year % 400 0)){return 29;}else{return 28;}
}函数的调用运用函数的地方
比如这里的 return is_LeapYear(year);
//二月28天或29天闰年case 2:{return is_LeapYear(year);//判断闰年}•如果函数的定义在函数的调用之后编译时就会有报错把怎么解决这个问题呢就是函数调⽤之前先声明函数声明函数只要交代清楚函数名函数的返回类型和函数的参数比如int is_LeapYear(int year);
#include stdio.hint is_leap_year(int y);//函数声明int main()
{int y 0;scanf(%d, y);int r is_leap_year(y);if (r 1)printf(闰年\n);elseprintf(⾮闰年\n);return 0;
}
//判断是不是闰年
int is_leap_year(int y)
{if (((y % 4 0) (y % 100 ! 0)) || (y % 400 0))return 1;elsereturn 0;
}•函数的调⽤⼀定要满⾜先声明后使⽤ •函数的定义也是⼀种特殊的声明所以如果函数定义放在调⽤之前也是可以的
2.多个文件
函数的声明、类型的声明放在头⽂件(.h)中函数的实现是放在源⽂件(.c)⽂件中
比如: add.c
//函数的定义
int is_LeapYear(int year)
{if ((year % 4 0 year % 100 ! 0) || (year % 400 0)){return 29;}else{return 28;}
}int day_In_month(int year, int month)
{switch (month){//有31天的月份{case 1:case 3:case 5:case 7:case 8:case 10:case 12:return 31;}//有30天的月份{case 4:case 6:case 9:case 11:return 30;}//二月28天或29天闰年case 2:{return is_LeapYear(year);//判断闰年}}
}add.h
//函数的声明
int is_LeapYear(int year);
int day_In_month(int year, int month);test.c
#include stdio.h
#include add.h
int main()
{int year, month, day;regain1:printf(请输入你要查询的年和月);regain2:while (scanf(%d %d, year, month) ! EOF){//判断年月输入是否正确if (year 0 || month 0 || month12){if (year 0 (month 0 month 12)){printf(年份输入错误请输 (year0)的数\n请重新输入你要查询的年和月);goto regain2;}if (year 0 (month 0 || month 12)){printf(月份输入错误请输入(month0 month12)的数\n请重新输入你要查询的年和月);goto regain2;}if (year 0 (month 0 || month 12)){printf(年份和月份输入错误请输入(year0 month0 month12)的数\n请重新输入你要查询的年和月);goto regain2;}}day day_In_month(year, month);printf(%d年%d月有%d天\n, year, month, day);goto regain1;}return 0;
}3.static和extern
1作用域
• 定义在C语言中作用域Scope指的是一个标识符如变量名、函数名等有效、可被访问的区域通俗来说一个变量在哪里可以使用哪里就是它的作用域
•局部变量的作⽤域是变量所在的局部范围 这个代码中a的作用域在
{int a 0;printf(%d, a);
}•全局变量的作⽤域是整个⼯程项⽬ int a 10所有函数内都可以使用
2生命周期
•⽣命周期指的是变量的创建(申请内存)到变量的销毁(收回内存)之间的⼀个时间段
•局部变量的⽣命周期是进⼊作⽤域变量创建⽣命周期开始出作⽤域⽣命周期结束
•全局变量的⽣命周期是整个程序的⽣命周期
3static和extern
static 是静态的的意思可以⽤来 • 修饰局部变量 • 修饰全局变量 • 修饰函数
extern 用来声明外部符号
astatic修饰局部变量
对比两个函数的结果 代码1的test函数中的局部变量a是每次进⼊test函数先创建变量⽣命周期开始并赋值为0然后a再打印出函数的时候变量⽣命周期将要结束释放内存
代码2中我们从输出结果来看a的值有累加的效果其实 test函数中的a创建好后出函数的时候是不会销毁的重新进⼊函数也就不会重新创建变量直接上次累积的数值继续计算
结论 static修饰局部变量改变了变量的⽣命周期⽣命周期改变的本质是改变了变量的存储类型本来⼀个局部变量是存储在内存的栈区的但是被static修饰后存储到了静态区。存储在静态区的变量和全局变量是⼀样的⽣命周期就和程序的⽣命周期⼀样了只有程序结束变量才销毁内存才回收。但是作⽤域不变的
使⽤建议 ⼀个变量出了函数后还想保留值等下次进⼊函数继续使⽤就可以使⽤static修饰
b static 修饰全局变量
int a 100没有static修饰可以跨文件正常使用
int a 100有static修饰不可以跨文件正常使用
结论 ⼀个全局变量被static修饰使得这个全局变量只能在本源⽂件内使⽤不能在其他源⽂件内使⽤。 本质原因是全局变量默认是具有外部链接属性的在外部的⽂件中想使⽤只要适当的声明就可以使⽤但是全局变量被 static 修饰之后外部链接属性就变成了内部链接属性只能在⾃⼰所在的源⽂件内部使⽤了其他源⽂件即使声明了也是⽆法正常使⽤的
使⽤建议 如果⼀个全局变量只想在所在的源⽂件内部使⽤不想被其他⽂件发现就可以使⽤static修饰。
cstatic 修饰函数
Add函数没有static修饰,Add函数可以使用
Add函数有static修饰,Add函数不可以使用 结论 static 修饰函数和 static 修饰全局变量是⼀模⼀样的⼀个函数在整个⼯程都可以使⽤被static修饰后只能在本⽂件内部使⽤其他⽂件⽆法正常的链接使⽤了
使⽤建议 ⼀个函数只想在所在的源⽂件内部使⽤不想被其他源⽂件使⽤就可以使⽤ static 修饰