1 函数的定义
数据类型 函数名 (【数据类型 形参名 ,数据类型 形参名 ,...........】)
main函数完整体:
#include <stdio.h>
#include <stdlib.h>
int main(int argc , char *argv[])//argc为传入参数的个数,*argv[]将传入的数据存放在字符数组中
{
int i;
printf("argc = %d\n",argc);//打印传入数据的个数
// for(i = 0 ; i <argc ; i++) 写法一
for(i = 0 ; argv[i] != NULL ;i++) //写法二,因而argv[]数组最后都会存放一个NULL表示数组的结束,以NULL来判断
puts(argv[i]);//打印传入的内容
exit(0);
}
2 函数的传参
值传递
#include <stdio.h>
#include <stdlib.h>
void printf_value(int a, int b)
{
printf("i = %d , j = %d",a,b);
return ;
}
int main()
{
int i = 2,j = 3;
printf_value(i,j);
exit(0);
}
地址传递
#include <stdio.h>
#include <stdlib.h>
void printf_value(int *p, int *q)
{
int temp;
temp = *p;
*p = *q;
*q = temp;//交换位置
return ;
}
int main()
{
int i = 2,j = 3;
printf("i = %d ,j = %d\n",i,j);
printf_value(&i,&j);//传入地址
printf("i = %d ,j = %d\n",i,j);
exit(0);
}
3 函数的调用
嵌套调用
#include <stdio.h>
#include <stdlib.h>
int mini(int a,int b,int c)//求最小值
{
int tmp;
tmp = a < b ? a : b;
return c < tmp ? c : tmp;
}
int max(int a,int b,int c)//求最大值
{
int tmp;
tmp = a > b ? a : b;
return c > tmp ? c : tmp;
}
int dist(int a,int b,int c)//最大值减最小值
{
return max(a,b,c) - mini(a,b,c);
}
int main()
{
int a,b,c;
int res;//结果
printf("please enter a,b,c for compare!\n");
scanf("%d%d%d",&a,&b,&c);
res = dist(a,b,c);//调用
printf("res = %d",res);//打印
exit(0);
}
递归
一个函数间接或直接地调用自身
利用递归解决阶乘问题:
n! = n * (n-1)!
#include <stdio.h>
int func(int n)
{
if(n < 0)
return -1; //终止条件
if(n == 0 || n == 1)
return 1; //0! = 1; 1! = 1; 特殊情况特殊说明
return n * func(n-1); // n! = n * (n-1)!
}
int main()
{
int n,res;
printf("please enter a num for n!\n");
scanf("%d",&n);
res = func(n);
printf("%d! = %d\n",n,res);
return 0;
}
利用递归解决斐波那契问题:
n = (n - 1) + (n - 2)
1 , 1 , 2 , 3 , 5 , 8 , 13 , 21 , 34 , 55........
#include <stdio.h>
int fib(int n)
{
if(n < 1)
return -1;
if(n == 1 || n == 2)
return 1;
return fib(n-1)+fib(n-2);
}
int main()
{
int n,res;
printf("please enter a num for fib\n");
scanf("%d",&n);
res = fib(n);
printf("fib[%d] = %d\n",n,res);
return 0;
}
4 函数与数组
函数与一维数组
#include <stdio.h>
#include <stdlib.h>
//void printf_arr(int p[],int n) 形参中的p[]看似是数组,其实也是int型的指针,sizeof也是8,固定大小,
void printf_arr(int *p,int n)//传入数组a的地址及其有效个数
{
int i;
printf("%s : %d\n",__FUNCTION__,sizeof(p));//打印指针p的大小,因为指针的大小是固定的,所以无法判断传入的数组地址中存 在多少个连续的数据,只能间接通过传参获取个数
for(i = 0 ; i < n ; i++)
printf("%d\n",*(p+i));
printf("\n");
return ;
}
int main()
{
int a[] = {1,2,3,4,5};//定义数组
printf("%s : %d\n",__FUNCTION__,sizeof(a));//打印数组a的大小
printf_arr(a,sizeof(a)/sizeof(*a));//将参数传入函数
exit(0);
}
注意,在形参中,int *p与int p[],或者说char **argc与char *argv[]是等价的,在形参中,一个[]相当于一颗*
函数与一维数组练习:
#include <stdio.h>
#include <stdlib.h>
int fun(int *p,int n)
{
int i,j,m,tmp;
m = (n-1)/2;//二分法
for(i = 0; i <= m ; i++)//逆序
{
j = n-1-i;
tmp = p[i];
p[i] = p[j];
p[j] = tmp;
}
}
int main()
{
int i;
int a[] = {1,2,3,4,5,6,7,8,9};
//printf("%s : %d\n",__FUNCTION__,sizeof(a));
for(i = 0; i < sizeof(a)/sizeof(*a) ; i++)
printf("%d\t",a[i]);
printf("\n");
fun(a,sizeof(a)/sizeof(*a));
for(i = 0; i < sizeof(a)/sizeof(*a) ; i++)
printf("%d\t",a[i]);
printf("\n");
exit(0);
}
函数与二维数组
#include <stdio.h>
#include <stdlib.h>
#define M 3 //行
#define N 4 //列
void func(int *p,int n)//将二维数组一行输出,大的一维数组
{
int i;
printf("sizeof(p) = %d\n",sizeof(p));//打印指针大小
for(i = 0; i < n ; i++)
{
printf("%d\t",*(p+i));//打印
}
printf("\n");
return ;
}
//void func1(int m,int n,int p[][N])//int p[][N]也是指针,与int (*p)[N]等价,同样为8个字节大小
void func1(int m,int n,int (*p)[N])//建立数组指针接受a的传参,二维数组形式输出
{
int i,j;
printf("sizeof(p) = %d\n",sizeof(p));//打印数组指针的大小
for( i = 0 ; i < m ; i++)
{
for(j = 0; j < n ; j++)
{
printf("%4d ",*(*(p+i)+j));//按需打印
//printf("4d ",p[i][j]);
}
printf("\n");
}
return ;
}
int main()
{
int a[M][N] = {1,2,3,4,5,6,7,8,9,10,11,12};//定义一个二维数组
printf("sizeof(a)= %d\n",sizeof(a));//打印数组所占的字节数
//func(*a,M*N);//*a , a[0] ,*(a+0) 将行指针转换成列指针去传参, ->*(a+0)+0
func1(M,N,a);//传入行指针
exit(0);
}
调用func()的结果:
调用func1()的结果:
函数与字符指针
#include <stdio.h>
#include <stdlib.h>
char *mystrcpy(char *dest,const char * src)//定义一个char*型的函数实现将数组str2拷贝到数组str1的功能
{
char *ret = dest;//将目标数组dest的起始地址赋值给ret
if((dest != NULL) && (src != NULL)) //判断目标指针与起始指针都不为空指针
while((*dest++ = *src++) != '\0');//将源数组的内容拷贝到目标数组中,遇到'\0'结束
return ret;//返回ret
}
char *mystrncpy(char *dest,char *src,size_t n )//定义一个char*型的函数实现将数组str2拷贝到数组str1的功能,多加了设置传入字符个数的功能
{
int i;
for(i = 0 ; i < n && (dest[i] = src[i]); i++)
; //循环执行
for(; i < n ;i++)
dest[i] = '\0';//当源数组在传入数据过程中没有'\0',是根据判断条件i < n结束传输的,记得给目标数组补上'\0'
return dest;//返回目标地址
}
int main()
{
char str1[] = "hello world";//源数组
char str2[128];//目标数组
mystrcpy(str2,str1);
//mystrncpy(str2,str1,7);
puts(str2);
exit(0);
}
5 函数与指针
指针函数
返回值 *函数名 (形参)
如:int *fun(int) ->int * (int,int) p
#include <stdio.h>
#define M 3//行
#define N 4//列
int *find_num(int (*p)[N] ,int num)//定义寻找函数
{
if(num > M-1)//如果输入的学生不存在,则返空指针
return NULL;
return *(p+num);//存在则返回学生所在行的地址
}
int main()
{
int num = 0;
int i;
int *res;
int a[M][N] = {1,2,3,4,5,6,7,8,9,10,11,12};//学生成绩
res = find_num(a,num);//将返回的地址存入res中
if(res == NULL)
printf("Can not find!\n");
else
for(i = 0; i < N ; i++)
printf("%d\t",res[i]);//*(res+i)
printf("\n");
}
函数指针
类型 (*指针名) (形参)
如,int (*p)(int ,int ) - >int (int,int) ( *p);
#include <stdio.h>
#include <stdlib.h>
int sum(int a,int b)//加法
{
return a+b;
}
int sub(int a,int b)//减法
{
return a-b;
}
int main()
{
int a = 2,b = 3;
int i;
int *ret;
int (*p)(int ,int);//定义函数指针
int (*q)(int ,int);//定义函数指针
p = add;
q = sub;//传地址
ret = p(a,b);
printf("%d\n",ret);
ret = q(a,b);
printf("%d\n",ret);//打印
exit(0);
}
函数指针数组
类型 ( * 函数名[N] ) ( 形参 )
如: int (*funcp[2])(int ,int ); ->本质抽象 int (int,int) ( *funcp[2]);(TYPE NAME)
#include <stdio.h>
#include <stdlib.h>
int sum(int a,int b)
{
return a+b;
}
int sub(int a,int b)
{
return a-b;
}
int main()
{
int a = 2,b = 3;
int i;
int ret;
int (*funcp[2])(int ,int ); //定义函数指针数组
funcp[0] = sum;//获取函数入口
funcp[1] = sub;
for(i = 0; i < 2; i++)
{
ret = funcp[i](a,b);
printf("%d\n",ret);//打印
}
exit(0);
}