目录
函数
一、函数的分类
C语言中,从使用的角度,函数可以分类两类。
- 库函数,也称为标准函数,是由C系统提供的,用户不必自己定义,可直接使用它们,使用库函数,必须包含 #include 对应的头文件。
- 自定义函数,解决具体需求而自己定义的函数,需先定义再使用。
二、函数基本语法
1.声明函数语法
返回类型 函数名(参数列表)
{
函数体语句1;
函数体语句2;
… 函数体语句n;
return 返回值;
}
2.函数语法的组成部分
- 函数名:函数被调用时使用的名字,函数名要符合标识符规范。
- 函数体:函数中所包含的代码块,用于实现函数的具体功能和操作。
- 参数:用于接收调用函数时传递进来的值。
- 返回值:函数执行完毕后,从函数传回到调用点的值,返回值的类型要与函数名前面的返回类型对应,如果没有返回值,返回类型可以写 void。
代码示例
#include <stdio.h>
// 声明一个函数
void show_hello()
{
printf("啊捏哈塞呦! \n");
}
// 声明一个求最大值的函数
int get_max_num(int x, int y)
{
return x > y ? x : y;
}
// 声明一个求和的函数
int add(int x, int y)
{
return x + y;
}
int main()
{
return 0;
}
注意:C程序中的所有函数都是互相独立的,一个函数并不从属于另一个函数,即函数不能嵌套声明。
3.调用函数
函数名后面加上圆括号即是函数的调用,参数写在小括号中,函数每调用一次,函数体语句都会执行一遍。
#include <stdio.h>
// 声明一个函数
void show_hello()
{
printf("啊捏哈塞呦! \n");
}
// 声明一个求最大值的函数
int get_max_num(int x, int y)
{
return x > y ? x : y;
}
// 声明一个求和的函数
int add(int x, int y)
{
return x + y;
}
int main()
{
show_hello();
printf("最大值为:%d \n",get_max_num(10,5));
printf("和为:%d \n",add(10,5));
return 0;
}
4.函数的返回值
函数调用后数能得到一个确定的值,这就是函数的返回值,返回值常常是一个计算的结果,或是用来作为判断函数执行状态的标记。
函数返回值分为以下三种情况:
- 无返回值类型:针对函数无返回值或明确不需返回值的情况,使用void(即空类型)表示。
- 有返回值类型:指明具体的类型,比如,int、float、char等。需要在函数体内与return语句搭配使用。
- 如果返回值类型不是void,但函数中没有return语句,则函数会返回一个不确定的值。
5.函数的参数
函数的参数分为形参与实参:
- 形参:在定义函数时,函数名后面括号()中声明的变量称为形式参数,简称形参。
- 实参: 在调用函数时,函数名后面括号()中的使用的常量、变量、表达式称为实际参数,简称实参。
注意:实参的数量要与形参的数量一致,否则报错。
6.主函数
主函数是程序的入口函数,即所有的程序一定要包含一个主函数,程序总是从这个函数开始执行,如果没有该函数,程序就无法启动。
主函数中可以调用其它函数,但其它函数不能反过来调用主函数,主函数也不能调用自己。
三、作用域
作用域用于确定在代码中某个标识符(如变量、标识符常量、数组等)的可见性和访问范围,它决定了在程序的哪些部分可以引用或访问该标识符。
作用域可以分为全局作用域、局部作用域、块级作用域。
同一个作用域中不能声明同名的标识符。
1.全局作用域
在函数和代码块(分支语句、循环语句等)以外定义的变量、标识符常量、数组等具有全局作用域,在程序的任何地方都可以被访问,通常称它们为全局变量、全局常量、全局数组等。
简述:在所有函数外部定义的变量:全局变量
对于全局变量,如果没有显式指定初始值,它们将自动初始化为零值。
对于全局数组,如果没有显式初始化它们,它们的元素将自动初始化为零值,字符数组,将初始化为空字符 \0。
2.局部作用域
在函数内定义的变量、标识符常量、数组等具有局部作用域,只有在该函数内部才能被访问,通常称它们为局部变量、局部常量、局部数组等。需要注意的是,函数的形参也是局部变量。
如果局部作用域中定义了与全局作用域中同名的标识符,优先使用本作用域中定义的数据。
与全局变量和全局数组不同,局部变量和局部数组如果没有显式初始化,它们的初始值是机器垃圾值,即系统之前分配给这块空间的值。所以不对局部变量、局部数组初始化是不安全且强烈不建议的。
3.块级作用域
块级作用域是C99标准引入的概念,在代码块(分支语句、循环语句等)中定义的变量、标识符常量、数组等具有块级作用域,只有在该代码块内部才能被访问,代码块通常具有花括号 {}
结构。
这些被称为块级变量、块级常量、块级数组等,同时也可以被称为局部变量、局部常量、局部数组,且与函数中的局部变量、局部常量、局部数组具有相同的特性。
四、递归函数
1.递归函数概念
· 一个函数在函数体内又调用了本身,我们称为递归调用,这样的函数就是递归函数。
递归函数成功执行需满足以下两个条件:
- 必须有一个明显的结束条件。
- 必须有一个趋近于结束条件的趋势。
2.原理分析
3.案例
1,1,2,3,5,8,13... 这是一个斐波那契数列,它的规则是第1个和第2个斐波那契数是1,从第3个数开始,每个斐波那契数都是前两个数之和。编写程序,输入一个整数,计算它的斐波那契数?
#include <stdio.h>
int fib(int a)
{
if (a == 1 || a == 2)
{
return 1;
}
return fib(a - 1) + fib(a - 2);
}
int main()
{
int n;
printf("请输入一个数字: \n");
scanf("%d", &n);
printf("%d 的 斐波那契数列结果:%d \n", n, fib(n));
return 0;
}
有一堆桃子,猴子第一天吃了其中的一半,并多吃一个。以后每天猴子都吃其中的一半,然后再多吃一个。当到第十天时,想再吃时(注意:此时还没吃),发现只有1个桃子了。问:最初共多少个桃子?
#include <stdio.h>
int peach(int day){
if(day==10){
return 1;
}else{
return (peach(day + 1) + 1) * 2;
}
}
int main()
{
printf("第十天桃子数量:%d \n",peach(10));
printf("第九天桃子数量:%d \n",peach(9));
printf("第一天桃子数量:%d \n",peach(1));
return 0;
}
4.常用系统函数
<string.h> 头文件中的函数
函数名 | 描述 |
strlen(str) | 返回str的长度,类型是 size_t |
strcpy(str1,str2) | 将str2中的字符串复制到str1中 |
strcat(str1,str2) | 将 str2 中的字符串追加到 str1 后面 |
<stdio.h> 头文件中的函数
标准库的头文件 <stdio.h> 中,也有两个字符串函数:
sprintf(),用于将格式化数据写入字符串。相比于 printf(),多了一个参数,第一个参数是要写入的字符串,后面参数与 printf() 一致。简单地讲,sprintf() 是将内容写入字符串而不是输出。
sscanf(),用于从一个字符串中按照指定的格式提取数据。相比于 scanf(),多了一个参数,第一个参数是要提取数据的字符串,后面参数与 scanf() 一致。简单地讲,sscanf() 是从字符串中提取数据而不是从用户输入提取数据。
日期时间相关函数
函数名 | 描述 |
time(&变量) | 获取当前日期赋值到变量中,该变量需是 time_t 类型 |
ctime(&时间值) | 将时间值转为字符串并返回,时间值需是 time_t 类型 |
difftime(时间值1,时间值2) | 返回两个时间值的差,返回值是 double 类型,时间值需是 time_t 类型 |
数学相关函数
数学相关函数,在头文件 <math.h> 中
函数名 | 描述 |
sqrt(x) | 计算平方根 |
cbrt(x) | 计算立方根 |
pow(x,y) | 计算x的y次方 |
fabs(x) | 计算x的绝对值 |
ceil(x) | 向上取整 |
floor(x) | 向下取整 |
round(x) | 四舍五入取整 |
trunc(c) | 截断小数部分 |