C语言:函数的使用

函数的定义

格式:
数据类型 函数名 ([数据类型 形参名,数据类型 形参名,…])

例:

#include <stdio.h>
#include <stdlib.h>

int main(int argc,char *argv[])
{
  //argc:从终端计算传递多少个参数过来,比如我们执行./main 123 ABC 则argc就是4个,如果是./main 那么就是argc就是1
  //argv:用来保存从命令行传入传输的列表,*p是字符指针用来保存数组的首地址
  int i;
   printf("argc = %d\n",argc);
  
  for(i = 0;argv[i] != NULL;i++)   //主要是用于遍历
       puts(argv[i]);
    return 0;
    
}

结果:
在这里插入图片描述

例:

#include <stdio.h>
#include <stdlib.h>

void print_hello(void) //被调用函数,记住被调在主调函数之前,如果没有声明,如果实在需要主调在前那请在主调前面声明需要用到的被调函数:void print_hello(void);
//前void 表示不需要返回值,后void 表示不需要传参
{
    printf("Hello!\n");
    return ;  //如果是void 就是不需要返回值,因此不需要写,但是这个return表示当前函数执行结束
}

int main()  //主调用函数
{
    print_hello(); 
    
    return 0;
}

函数的传参

值传递:

直接传递数值,在被调用的函数中只能使用这个值,不能改变这个原始的值。

例:

#include <stdio.h>
#include <stdlib.h>

int printf_value(int i,int j) //完全可以使用主调函数的定义名称,主调使用完成以后就会结束,而被调再次使用也是重新开始的
{
    printf("i = %d,j = %d\n",i,j);
    return 0;
}

int main()
{
    int i = 3,j = 5;
    
    printf_value(i,j);
    
    return 0;
}

结果:
在这里插入图片描述

地址传递:

通过直接操作地址,来使用和更改这个值。
来看一个例子,是关于数值交换的错误操作

#include <stdio.h>
#include <stdlib.h>

int swap(int i,int j)
{
    int tmp; 
    tmp =i;
    i = j;
    j = tmp;
    printf("in-->i = %d,j = %d\n",i,j);
    return 0;
}

int main()
{
    int i = 3,j = 5;
    printf("befor-->i = %d,j = %d\n",i,j);
    swap(i,j);
    printf("after-->i = %d,j = %d\n",i,j);
    return 0;
}
//这样其实并没有值进行交换,因为在被调用函数的时候是交换了值,但是并没有在主调函数中交换这个值

结果:
在这里插入图片描述

例:正确交换的方法应该是直接改变对应的地址:

#include <stdio.h>
#include <stdlib.h>

int swap(int *p,int *q)  //主调函数传参的是数值的地址,因此被调函数应该用指针来保存对应的地址
{
    int tmp;
    tmp = *p;
    *p = *q;
    *q = tmp;
    printf("in-->i = %d,j = %d\n",*p,*q);
    return 0;
}
int main()
{
    int i = 3,j = 5;
    printf("befor-->i = %d,j = %d\n",i,j);
    swap(&i,&j);
    printf("after-->i = %d,j = %d\n",i,j);
    return 0;
}

在这里插入图片描述

函数的调用

函数的嵌套

例:输入数字 比较大小

#include <stdio.h>
#include <stdlib.h>

int maxfunc(int a,int b,int c)
{
    int temp;
    temp = a>b? a:b;
    return temp>c? temp:c;
}

int minfunc(int a,int b,int c)
{
    int temp;
    temp = a<b? a:b;
    return temp<c? temp:c;
}

int dist(int a,int b,int c)
{
    return maxfunc(a,b,c)-minfunc(a,b,c);
}

int main()
{
    int a,b,c;
    int res;
    printf("请输入比较的三个数字:\n");
    scanf("%d %d %d",&a,&b,&c);
    printf("%d\n%d\n%d\n",a,b,c);
    res = dist(a,b,c);
    printf("%d\n",res);
    
    return 0;
}

在这里插入图片描述

例:乘阶

#include <stdio.h>
#include <stdlib.h>

int func(int a )
{
    if(a<1)
        printf("input err\n");
        
    if(a == 1)
        return 1;
    return a *func(a-1);
}

int main()
{
    int a,b,c;
    int res;
    printf("请输入数字:\n");
    scanf("%d",&a);
    
    res = func(a);
    printf("%d\n",res);
    
    return 0;
}

结果:
在这里插入图片描述

例:求下列

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>

int func(int a )
{
    if(a<1)
        printf("input err\n");
        
    if(a == 1)
        return 1;
    return a *func(a-1);
}

int main()
{
    int m,n;
    int res;
    printf("请输入m数字和n数字:\n");
    scanf("%d %d",&m,&n);
    if(m<n)
    {
        printf("输入数字无效\n");
    }
    res = func(m)/(func(n)*func(m-n));
    printf("%d\n",res);
    
    return 0;
}

结果:
在这里插入图片描述

函数与数组

函数与一维数组

在传参中不光要传送数组的地址,还要传送这个数组有多少元素。

int a[N] = {1,2,3,4,5,6};
int *p = a;
在传参中不光要传送数组的地址,还要传送这个数组有多少元素
实参 ->a(a数组的首地址)		   *a(值(a[0]))		 a[0](值)	    &a[3](地址)       p[i](值)       p(地址)		      *p(值)		   p+1(地址)		
    
行参 ->int*(被调函数要使用指针)  	int(类型) 	     int(类型)		int *(指针)	      int(类型)		int*(指针)	     int(类型)		  int*(指针)

例:

#include <stdio.h>
#include <stdlib.h>

void printf_arr(int *p,int n)
//void printf_arr(int p[],int n)
{
    
    int i;
    for(i = 0;i < n;i++)
        printf("%d ",*(p+i));
    printf("\n");
}

int main()
{   
	int a[] = {1,3,5,7,9};
 
    printf_arr(a,sizeof(a)/sizeof(*a));
    
    return 0;
}

结果:
在这里插入图片描述

例:倒序算法

#include <stdio.h>
#include <stdlib.h>

void func(int *p,int n)
{
    int i = 0,j,tmp;
	int m = (n-1)/2;
	for( ;i <= m;i++)
    {
        j = n-1-i;
        tmp = p[i];
        p[i] = p[j];
        p[j] = tmp;
    }
}
int main()
{   
	int a[] = {1,3,5,7,9};
    int i;
 	for(i = 0;i < sizeof(a)/sizeof(*a);i++)
        printf("%d ",a[i]);
    printf("\n");
    
    func(a,sizeof(a)/sizeof(*a));
    
    for(i = 0;i < sizeof(a)/sizeof(*a);i++)
        printf("%d ",a[i]);
    printf("\n");
    
    return 0;
}

结果:
在这里插入图片描述

函数与二维数组

int a[M][N] = {...};
int *p = *a;
int (*q)[N] = a;

传实参 	a[i][j]		*(a+i)+j		a[i]+j		p[i]		*p
		q[i][j]		*q				q			p+3			q+2

接形参 	int			int *			int *		int			int
		int			int *			int (*)[N]	int *		int (*)[N]

例:

#include <stdio.h>
#include <stdlib.h>

#define M 2
#define N 3

void print_arr(int *p,int n)
{
    int i;
    
    for(i=0;i<n;i++)
    {
        printf(" %4d",p[i]);
    }
    printf("\n");
}
void print_arr1(int *p,int n)
{
    int i;
    
    for(i=0;i<n;i++)
    {
        printf(" %4d",p[i]);
    }
    printf("\n");
}
void print_arr2(int (*p)[N],int m,int n) //这个N 一定要和列数一样
//void print_arr2(int p[M][N],int m,int n)  这个也可以的
{
    int i,j;
    for(i=0;i<m;i++)
    {
        for(j=0;j<n;j++)
        {
            printf(" %4d",p[i][j]);     // *(*(a+i)+j)一样的
        }
        printf("\n");
    }
}

int main()
{
    int a[M][N] = {1,2,3,4,5,6};
    
    print_arr(*a,M*N);
    
    print_arr1(&a[0][0],M*N); //同样还可以使用 *a,a[0],*(a+0)
    
    print_arr2(a,M,N);
    
    
    return 0;
}

结果:
在这里插入图片描述

例:求平均数和查找某一行数

#include <stdio.h>
#include <stdlib.h>

#define M 3
#define N 4

float average_score(int *p,int n)
{
	int i;
	float sum = 0;
    for(i = 0;i < n;i++)
        sum += p[i];
    return sum/n;
}

void find_num(int (*p)[N],int num)
{
    int i;
	for(i = 0;i < N;i++)
		printf("%d",*(*(p+num)+i));
    printf("\n");
}

int main()
{
    float ave;
	int a[M][N] = {1,2,3,4,5,6,7,8,9,10,11,12};
	int num = 0; // 这个是决定于取哪一行,
    
    ave = average_score(*a,M*N);
    printf("ave = %f\n",ave);
	
    find_num(a,num);
    return 0;
}

在这里插入图片描述

函数与字符数组

例:仿写stcpy和strncpy

#include <stdio.h>
#include <stdlib.h>

#include "stdio.h"
#include "stdlib.h"

char *mystrcpy(char *dest,const char *src) //参考man stcpy 发现返回的是一个指针 因此前面要加一个*
{
    char *ret =dest;
    if(dest != NULL && src != NULL)
    	while((*dest++ = *src++) != '\0');//src++表示不断向后移动,dest++也是不断向后移动。直到拷贝到!= '\0',不等于尾零为止。
    return ret;
}

char *mystrncpy(char *dest,const char *src,size_t n)
{
    int i;
    for(i = 0;i < n && (dest[i] = src[i]);i++);//dest[i] = src[i]确保每一个数都移过去,如果移是0的话,就会结束
    
    dest[i] = '\0';  //确保'\0'也是能移过去
    for(;i < n;i++)  //遍历一次 查看是否结束为0,
        dest[i] = '\0';
    return dest;
}
int main()
{
	char str1[] = "I love china!";
    char str2[128];
    
    mystrcpy(str2,str1);
    puts(str2);
     
    mystrncpy(str2,str1,8);
    puts(str2);
    return 0;
}

结果:
在这里插入图片描述

函数与指针

指针函数

返回值为指针的函数。
格式:返回值 *函数名(形参)
如: int *fun(int);

例:优化一下求平均数和查找某一行数

#include <stdio.h>
#include <stdlib.h>

#define M 3
#define N 4

int *find_num(int (*p)[N],int n)  //N表示列数  int* 是返回的是一个指针函数 
{
    if(n>M-1)   //这个是为了判断输入的行数不能大约原本的行数
        return NULL;  //如果是越界了 则返回空即可
    return *(p+n);   //可以写成 p[n],表示已经找到了列数,但是不需要打印 也可以其他的用途,只需要返回即可
}

int main()
{
    int i;
    int *res;   //定义一个返回的指针
    int a[M][N] = {1,2,3,4,5,6,7,8,9,10,11,12};
    
    int num = 1;   // 表示需要查找的行数
    
    res = find_num(a,num);
    
    if(res != NULL)   //判断是否返回为空
    {
        for(i=0;i<N;i++)  //遍历这一行的所有列数
        {
            printf("%d   ",res[i]);
        }
        printf("\n");
    }
    else
    {
        printf("erro end\n");
    }
    return 0;//exit(0);
}

结果:
在这里插入图片描述

函数指针

指向函数的指针。
格式:类型 (*指针名) (形参)
如: int (*p)(int)

例:

#include <stdio.h>
#include <stdlib.h>

int add(int m,int n)
{
    return m+n;
}

int sub(int m,int n)
{
    return m-n;
}


int main()
{
    int a = 5;
    int b = 8;
    int res1,res2;
    
    int (*p)(int,int);
    int (*q)(int,int);
    
    p = add;  //也可以写成 &add
    q = sub;  //也可以写成 &sub
    
    
    res1 = add(a,b)-sub(a,b);
    
    res2 = p(a,b) - q(a,b);  
   // res2 =  *p(a,b) - *q(a,b);  这个与上面的取地址一起更改
    
    printf("%d\n",res1);
    printf("%d\n",res2);
}

在这里插入图片描述

函数指针数组

存放指向函数指针的数组
格式:类型 (*数组名[下标]) (形参)
如: int (*arr[N])(int)

例:

#include <stdio.h>
#include <stdlib.h>

int add(int m,int n)
{
    return m+n;
}

int sub(int m,int n)
{
    return m-n;
}
int main()
{
    int a = 5;
    int b = 8;
    int i;
    int res;
    
    int (*fun[2])(int,int);
    
    fun[0] = add;
    fun[1] = sub;
    
    for(i = 0;i<2;i++)
    {
        res = fun[i](a,b);
        printf("%d\n",res);
    }
}

结果:
在这里插入图片描述

指向指针函数的函数指针数组

1.首先是一个数组     比如说 [N]
2.其次是一个指针数组   比如说 (*fun[N]) 
3.上述所说 这个指针数组里面每一个指针都是指向函数 就是函数指针数组了 比如说: int  (*fun[N]) (int)
4.指向什么的函数呢,是指向指针的函数,指针函数就是一个函数返回为指针。最终结果就是  int  * (*fun[N]) (int)
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值