目录
1.函数是什么
C语言函数是什么?维基百科中对函数的定义:子程序
在计算机科学中,子程序是一个大型程序中的某部分代码,有一个或者多个语句块组成。它负责完成某项特点的任务,而且相较于其他代码,具备相对的独立性。
一般情况有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软件库。
2.函数的分类
(1)库函数
C语言自己提供频繁被大量使用的功能,实现这些功能的函数,称为库函数
对于想学习库函数中的函数有以下3个途径:
1.cplusplus.com - The C++ Resources Network
2.下载软件MSDN(Microsoft Developer Network)或者有在线版MSDN
3.cppreference.com(这个网站是中文的)
(2)自定义函数
自定义函数和库函数一样区别在与,自定义函数的函数名,返回值类型和函数参数需要我们自己来设计。
ret_type fun_name(para1)
{statement;//函数体
}
//ret_type 函数返回类型
//fun_name 函数名
//para1 函数参数
例如:定义一个函数输出俩个整数a,b中最大的。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int getmax(int a,int b)
{
return a < b ? b : a;
}
int main()
{
printf("%d",getmax(1, 2));
return 0;
}
3.函数参数
函数参数分为:形式参数和实际参数
例如:
1.比较a,b大小输出较大的
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int getmax(int a,int b)//int a和int b为形式参数
{
return a < b ? b : a;
}
int main()
{
printf("%d",getmax(1, 2));//传值调用
//getmax(1,2)中的1和2为实际参数,
//在主函数中将实际参数传到自定义函数中的形式参数中并在自定义函数中运行并返回结果
return 0;
}
2.交换a,b的值(考研对形式参数和实际参数的理解)还需要学习指针知识,之后对比以下俩个程序的不同。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void swap(int *pa,int *pb)//void类型函数表示函数没有返回值
{
int t=0;
t = *pa;
*pa = *pb;
*pb = t;
}
int main()
{
int a=1;
int b=2;
swap(&a, &b);//传址调用
printf("%d\n%d",a,b);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void swap(int a,int b)
{
int t=0;
t = a;
a = b;
b = t;
}
int main()
{
int a=1;
int b=2;
swap(a, b);//传值调用
printf("%d\n%d",a,b);
return 0;
}
4.函数调用:
传值调用:揭示函数参数模块中的第二题中的第二个程序,函数的形式参数和实际参数分别占用不同的内存块,对形参的操作不会影响到实参,有人要问了那函数参数模块中的第一题为什么就不需要指针,因为第一天不需要去修改实参,只需要将实参数据传到形参中,然后从形参中比较出一个较大值然后输出,当需要改变实参时,我们要用的就不是传值调用,而是传址调用,只有用地址才能来对实参进行修改。
传址调用:传址调用,意思是实际参数传到形式参数的值是一个地址,也就是函数参数模块中第二题的第一个程序。
例如:写一个函数用于在有序素组中实现二分查找
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int erfen(int arr[],int a,int len)
{
int max = len - 1;
int min = 0;
while (min<=max) {
int mid = (max + min) / 2;
if (a <arr[mid] ) {
max = mid-1;
}
else if (a > arr[mid])
{
min = mid +1;
}
else
{
return mid;
}
}
return -1;
}
//有序数组的二分查找,
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int a=0;
int len = sizeof(arr) / sizeof(arr[0]);
printf("请输入1-20内的数");
scanf("%d", &a);
int ret=erfen(arr,a,len);
//这里函数传数组,仅仅是传了arr数组的首元素地址
//并不是将整个数组传过去了
if (ret!=-1)
{
printf("%d", arr[ret]);
}
else
{
printf("没找到");
}
return 0;
}
5.函数的嵌套调用和链式访问
函数的嵌套调用:C语言支持函数的嵌套调用,但是不支持嵌套定义,区分二者区别,例如:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void test1()
{
test2();
}
int test2()
{
printf("Hellow world!!!");
}
int main()
{
test1();
return;
}
链式访问:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = { 0 };
char arr2[] = "bit" ;
printf("%s\n",strcpy(arr1, arr2));//将数组arr2复制给arr1
//函数strcpy()的返回值做了printf()函数的参数---链式访问
printf("%d", printf("%d", printf("%d", 43)));//--耐人寻味,请查printf()的官方定义
return;
}
6.函数的声明和定义
因为编译是从前往后的,如果将函数定义到主函数的后面,不提前声明会出现下面这种情况,
函数的声明一般出现在函数的使用之前,先声明后调用,
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int a = 2;
int b = 3;
int add(int,int);//函数声明
int z = add(a, b);
printf("%d",z);
return;
}
int add(int a, int b)
{
return a + b;
}
注:函数的声明一般放在头文件中。
7.函数的递归
函数递归:函数本身调用自己,有些问题运用递归可以更简单的解决问题。
实例:将输入的数逆序输出,例如输入4321,输出1 2 3 4,注:这里要区分%与/的区别才能读懂程序
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int digui(int a)//这个函数是将输入的数字逆序输出每一位,例如:输入4123 输出3 2 1 4
{
printf("%d\t", a % 10);
a = a / 10;
if (a!=0)
{
digui(a);
}
}
void digui1( int b)//这个函数是将输入的数字顺序输出每一位,例如:输入4123 输出4 1 2 3
{
if (b > 9)
{
digui1(b / 10);
}
printf("%d\t",b%10);
}
int main()
{
int a = 0;
scanf("%d",&a);
digui(a);
return;
}
例题:算出字符串长度,注:不可使用临时变量,要使用递归
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
my_strlen(char* p)
{
if (*p != '\0')
{
return 1 + my_strlen(p+1);
}
else
return 0;
}
int main()
{
char arr[] = "hello";
printf("%d",my_strlen(arr));
return;
}