函数(一)

前言:

各位小伙伴,欢迎来到ljp-nan的博客参观,我又学到了不少有趣的知识,今天我给大家带来的是C语言中函数(一)的讲解。相信大家对数学中的函数有深入的了解,比如一个二次函数,幂函数,指数函数等等。但是C语言中没有那么多种类的函数,它只有两类函数,一种是库函数,另一种就是用户的自定义函数。没错就这两类,没有高数中的导数,更没有积分,是不是感觉很简单。那么接下来我们就进入正式的学习。下面的思维导图就是函数的讲解思路。

一、函数是什么?

先来看一个代码:

int max(int x, int y)
{
    return x > y ? x : y;
}
int main()
{
    //用1-100的数字同53作比较,返回比53大的数字,我们可以这样写
    for (int i = 1; i <= 100; i++)
    {
        //这里利用for循环调用多次max函数
        if (53 < max(53, i))
        {
            printf("%d ", max(53, i));
        }
    }
    return 0;
}

在本代码中,通过多次调用max()函数,使得代码没有那么多相同的代码,这就是函数的作用,减少代码的冗余度。

那么我们给出C语言中函数的定义:

函数是C程序中的基本组成单元,也称作子程序。所有C语言程序都是有一个或多个函数构成的。当一个C语言程序的规模很小时,可以用一个源文件来实现,当一个C语言程序的规模较大时,可以由多个源文件组成,但其中只有一个源文件包含main()函数,而其他源文件不能含有主函数。主函数可以调用其他函数,反之不行。其他函数之间可以互相调用,同一个函数可以被一个或多个函数调用任意多次。一个函数调用另一个函数,前者称为调用函数;后者称为被调函数。

相信大家已经对什么是函数有一定了解了,那么我们接下来看函数的分类。

二、函数的分类

C语言中函数可以分为库函数和用户自定义函数。

2.1 库函数

首先,一个问题,为什么会有库函数?

  1. 我们知道在我们学习C语言编程的时候,总是在一个代码编写完成之后迫不及待的想知道成果,想把这个结果打印到我们的屏幕上看看。这个时候我们会使用一个功能,那就是把数据输出到屏幕上。

  1. 在编程中,我们需要经常拷贝字符串。

  1. 在编程中,我们也会解决一些数值计算的问题,比如:加减乘除。

像以上所说的基础功能,当然还有很多,它们不是业务性的代码。我们在开发时,每个人都会用到这些功能,但是总不能让程序员一个一个编写吧,这个并不是一个聪明的办法。所以C语言提供了解决之道,那就是库函数。

怎么样学习库函数呢?

这里推荐一个网站,链接就在下面了。

https://cplusplus.com/

在这个网站里面,我们可以查询到C语言给用户提供的所有库函数。举两个例子。

比如,我们需要把一个字符数组里的内容拷贝到另一个字符数组里,这里就需要用到一个库函数strcpy。

在搜索狂输入你想要查找的函数。

代码举例:

#include <string.h> //strcpy 所在的头文件
#include <stdio.h>
int main()
{
    char arr1[20] = "hello world";
    char arr2[20] = "hello";
        //调用strcpy库函数,进行字符串的拷贝
    strcpy(arr2, arr1);    //arr2为目标字符串,arr1为源字符串,都是传址调用
    printf("arr1 = %s\n", arr1);
    printf("arr2 = %s\n", arr2);
    return 0;
}

以上就是网站的使用方法。

接下来你可以去搜索memset这个函数的使用方法。以下是关于这个函数的使用代码:

int main()
{
    char arr[20] = { "hello world" };
    memset(arr, 'x', 5);  
    printf("%s\n", arr);
    return 0;
}

注意:使用库函数必须包含#include对应的头文件。要掌握对照文档来学习库函数的方法。

以下还有许多学习C语言的库函数的网站,链接奉上:

MSDN(Microsoft Developer Network)
www.cplusplus.com
http://en.cppreference.com http://en.cppreference.com(英文版)
http://zh.cppreference.com (中文版)

2.2自定义函数

如果库函数能干所有的事情,那还要程序员干什么?

所以更加重要的是自定义函数。自定义函数和库函数一样,有函数名,返回值类型和函数参数。但是不一样的是这些都是我们自己来设计。这给程序员一个很大的发挥空间。

函数的组成:

ret_type fun_name(para1, * )
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1 函数参数

举个例子:

写一个函数,计算两个加数的和;

int add(int x, int y)
{
    return x + y;
}
int main()
{
    int x = 10;
    int y = 20;
    printf("%d\n", add(x, y));
    return 0;
}

该函数的传参示意图:

我们来看这一个例子:

//实现函数交换两个数的值
void Swap1(int x, int y)
{
    int tmp = 0;
    tmp = x;
    x = y;
    y = tmp;
}
//此时,Swap1函数只改变形参的值,不会改变实参的值。不会交换两个数的值
void Swap2(int* x, int* y)
{
    int tmp = 0;
    tmp = *x;
    *x = *y;
    *y = tmp;
}
//传址调用,通过指针改变实参的值,会交换两个数的值

int main()
{
    int x = 6;
    int y = 7;
    printf("调用Swap1前:x = %d,y = %d\n", x, y);
    Swap1(x, y);
    printf("调用Swap1后:x = %d,y = %d\n", x, y);
    printf("调用Swap2前:x = %d,y = %d\n", x, y);
    Swap2(&x, &y);
    printf("调用Swap2后:x = %d,y = %d\n", x, y);
    return 0;
}

那么为什么是这样的结果呢,需要画图来描述

传值调用:

传址调用:

以上就是传值调用和传址调用的不同。

三、函数的参数

3.1 实际参数(实参):

真实传给函数的参数,叫实参。

实参可以是:常量、变量、表达式、函数等。

无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形

参。

3.2 形式参数(形参):

形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内

存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有

形式参数实例化后,相当于实参的一份临时拷贝

四、函数的调用

4.1 传值调用

函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。

4.2 传址调用

传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。

这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操

作函数外部的变量

一些练习:

1. 写一个函数可以判断一个数是不是素数。

#include <math.h>
int is_prime(int i)
{
    int j = 0;
    for (j = 2; j <= sqrt(i); j++)
    {
        if (i % j == 0)
        {
            return 0;  //不是素数,返回0
        }
    }
    return 1; //是素数返回1
}
int main()
{
    int i = 0;
    for (i = 100; i <= 200; i++)
    {
        if (1 == is_prime(i))
        {
            printf("%d ", i);  //是素数打印
        }
    }
    return 0;
}

2. 写一个函数判断一年是不是闰年。

int is_leap_year(int year)
{
    return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}
int main()
{
    int year = 0;
    for (year = 1000; year <= 2000; year++)
    {
        if (is_leap_year(year))
        {
            printf("%d ", year);
        }
    }
    return 0;
}

3. 写一个函数,实现一个整形有序数组的二分查找。

int find(int arr[],  int sz,int k)
{
    int left = 0;
    int right = sz - 1;
    int mid = 0;
    while (left <= right)
    {
        mid = left + (right - left) / 2;
        if (arr[mid] < k)
        {
            left = mid + 1;
        }
        else if(arr[mid]>k)
        {
            right = mid - 1;
        }
        else
        {
            return mid;
        }
    }
    return -1;
}
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int sz = sizeof(arr) / sizeof(arr[0]);   //注意这个语句不能写在函数里
    int left = 0;                            //因为,在函数中我们传进去的是首元素地址,它的大小只能是4/8。
    int right = sz - 1;
    int mid = left + (right - left) / 2;
    int k = 7;
    printf("找到了,下标是%d ", find(arr,  sz, k));
    if (-1 == find(arr, sz,k))
    {
        printf("没找到\n");
    }
    return 0;
}

4. 写一个函数,每调用一次这个函数,就会将 num 的值增加1。

void num_add(int* p)
{
    *p += 1;
}
int main()
{
    int num = 0;
    printf("第一次调用:> ");
    num_add(&num);
    printf("%d\n", num);
    printf("第二次调用:> ");
    num_add(&num);
    printf("%d\n", num);
    printf("第三次调用:> ");
    num_add(&num);
    printf("%d\n", num);
    return 0;
}

谢谢大伙的捧场,今后我会继续加油的。

觉得有用,就点点赞吧!

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值