函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。
一般形式如下:
<数据类型> <函数名称>(<形式参数说明>)
函数的参数传递
函数之间的参数传递方式:
- 全局变量
- 复制传递方式
- 地址传递方式
1.全局变量
全局变量就是在函数体外说明的变量,它们在程序中的每个函数里都是可见的。
全局变量一经定义就会在程序的任何地方可见。函数调用的位置不同,程序的执行结果可能会收到影响。不建议使用
2.复制传递
调用函数将实参传递给被调函数,被调用函数将创建同类型的形参并用实参初始化。
形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。
3.地址传递
按地址传递,实参为变量的地址,而形参为同类型的指针。
被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作,相当于对实参本身的操作)。
#include <stdio.h>
int str_fun(char *p);
int main(int argc, char *argv[])
{
char s[] = "welcome2023Jiangxi";
int n;
n = str_fun(s);
printf("n=%d %s\n", n, s);
return 0;
}
// char *p = n 我们需要习惯将形参联想等于实参,两端逻辑需要相通
int str_fun(char *p)
{
int num = 0;
while(*p != '\0')
{
if(*p <= 'z' && *p >= 'a')
{
num++;
*p -= ' ';
}
p++;
}
return num;
}
函数的传参--数组
全局数组传递方式
复制传递方式:实参为数组的指针,形参为数组名(本质是一个指针变量)
地址传递方式:实参为数组的指针,形参为同类型的指针变量
案例一
#include <stdio.h>
int array_sum(int data[], int n); //相当于int array_sum(int *data, int n);
int main(int argc, char *argv[])
{
int a[] = {
5, 9, 10, 3, 10};
int sum = 0;
sum = array_sum(a,sizeof(a) / sizeof(int));
printf("sum=%d\n", sum);
return 0;
}
int array_sum(int data[], int n) // int data[] = a;-->error
{
int ret = 0;
int i;
for(i = 0; i < n; i++)
{
ret += data[i];
}
return ret;
}
上述程序需要我们对数组的元素个数进行计算,如果函数单纯传入一个数组,并且在程序代码段中再进行数组长度的计算,由于我们传入的是int data[]
,此时的int data[]实际就是int *data
,使用sizeof()函数则会得到一个指针的字节长度,而并非我们想要的数组长度
。
案例二
// try to write a function,which delete the space character of character string.
#include <stdio.h>
void del_space(char *str);
int main(int argc, char *argv[])
{
char a[] = "hello world,hello linux!";
puts(a);
del_space(a);
puts(a);
return 0;
}
void del_space(char *str)
{
char *p;
p = str;
while(*str)
{
if(*str == ' ')
{
str++;
}
else
{
*p = *str;
p++;
str++;
}
}
*p = '\0';
}
此处是删除一段字符串中的空格字符,在void del_space()函数中,我们采取的是指针地址传递的形式
,由于我们需要实现的功能是删除字符串中多余的空格,所以当字符指针为空格时,指针向后移动一位,当遇到字符时,将指针字符2复制给指针字符1,同时两者地址同时后移一位,这里需要注意的是,当字符指针便利到最后一位\0
时,代表字符串的末尾,因此我们也需要为赋值*p = '\0';
代表末位。
指针函数
1.基本概念
指针函数是指一个函数的返回值为地址量
的函数。
2.定义形式
函数指针的定义的一般形式如下:
<数据类型> * <函数名称>(<参数说明>){
语句序列;
}
`返回值:全局变量的地址 / static变量的地址 / 字符串常量的地址 / 堆的地址`
3.示例
// 编写一个指针函数,删除一个字符串中的空格
#include <stdio.h>
#include <string.h>
char *del_space(char *s);
int main(int argc, char *argv[])
{
char * r;
char str[] = "How ar e y ou!";
r = del_space(str);
printf("----%s---\n",r);
puts(str);
return 0;
}
char *del_space(char *s)
{
char *p = s;
char *r = s;
while(*s)
{
if(*s == ' ')
{
s++;
}
else
{
*p = *s;
s++;
p++;
}
}
*p = '\0';
return r;
}
// 编写一个函数,实现两个字符串的连接
#include <stdio.h>
char *mstrcat(char *dest, const char * src);
int main(int argc, char *argv[])
{
char dest[59] = "welcome";
char src[] = "makeru";
puts(mstrcat(dest,src));
puts(dest);
return 0;
}
char *mstrcat(char *dest, const char * src)
{
char *r = dest;
while(*dest)
{
dest++;
}
while(*src)
{
*dest = *src;
dest++;
src++;
}
*dest = '\0';
return r;
}
// 编写一个函数,将传入的整型转成字符串
#include <stdio.h>
char * itoa(int n);
int main(int argc, char *argv[])
{
int n;
char s[50], *r;
printf("input:");
scanf("%d",&n);
r = itoa(s, n);
puts(r);
puts(s);
return 0;
}
char * itoa(char *p, int n)
{
int r, i = 0, j;
//static char p[50];
while(n)
{
r = n % 10;
n /= 10;
p[i] = r + '0';
i++;
}
p[i] = '\0';
j = i - 1;
i = 0;
while(i < j)
{
r = p[i];
p[i] = p[j];
p[j] = r;
j--;
i++;
}
return p;
}
递归函数
1.基本概念
递归函数是指一个函数的函数体中直接或间接调用了该函数自身
递归函数调用的执行过程分为两个阶段:
- 递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件。
- 回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归原问题。
2.示例
// 计算n!
#include <stdio.h>
int fac(int n);
int main(int argc, char *argv[])
{
int n;
printf("input:");
scanf("%d",&n);
printf("%d\n", fac(n));
return 0;
}
int fac(int n)
{
if(n == 0 || n == 1)
return 1;
return n * fac(n-1);
}
// 编写一段程序,计算斐波那契序列
#include <stdio.h>
int fib(int n);
int main(int argc, char *argv[])
{
int n = 1;
while(n <= 10)
{
printf("%d ",fib(n));
n++;
}
printf("\n");
return 0;
}
int fib(int n)
{
if(n == 1 || n == 2)
return 1;
return fib(n-1)+fib(n-2);
}
函数指针
1.基本概念
函数指针用来存放函数的地址
,这个地址是一个函数的入口地址
- 函数名代表了函数的入口地址
2.定义形式
函数指针变量说明的一般形式如下:
<数据类型> (*<函数指针名称>) (<参数说明列表>);
eg:
int (*p)(int a, int b);
3.函数指针数组
定义:函数指针数组是一个保存若干个函数名的数组。
一般形式如下:
<数据类型> (*<函数指针数组名称>)(<大小>)(<参数说明列表>);
---<大小>:指函数指针数组元素的个数
---其他等同普通的函数指针
4.示例
// 编写一段程序,实现qsort()排序的功能
#include <stdio.h>
int compare(const void*, const void *);
int main(int argc, char *argv[])
{
int s[] = {
89, 23, 5, 54, 75}, n, i;
n = sizeof(s) / sizeof(int);
qsort(s, n, sizeof(int), compare);
for(i = 0;i < n; i++)
printf("%d ",s[i]);
puts("");
return 0;
}
int compare(const void* p, const void *q)
{
return (*(int *)p - *(int *)q);
}