(十二)C语言之函数

目录

1、函数的概述

2、函数的分类

3、函数的定义

4、函数的形参

4.1 普通变量作为函数的形参

4.2 一维数组作为函数的形参

4.3 二维数组作为函数的形参

5、随机数

6、常用排序方法

6.1 选择排序

6.2 冒泡排序

7、字符串操作(分函数且不使用库函数)

7.1 字符串的长度测量(等价于strlen)

7.2 字符串逆序

7.3 字符串拷贝

7.4 字符串追加

7.5 字符查找

7.6 字符删除

7.7 字符串的指定位置插入新字符串


C语言的特点:面相过程编程,C语言是将功能封装成一个函数,在按照一定的顺序调用,从而实现各种复杂功能的过程。

1、函数的概述

函数是C语言的功能单位。在封装函数时,一切以功能为准则,用功能来确定函数的形参、返回值、函数体、函数名。

2、函数的分类

按照定义分类:库函数,用户自定义函数、系统调用

按照参数分类:有参函数,无参函数

按照返回值分类:有返回值类型,无返回值类型

3、函数的定义

函数本身包括返回值类型、函数名、形参、函数体。

函数的定义:函数定义时,需要确定函数的返回值类型,函数名,形参个数、类型,实现函数体。

函数的声明:声明函数,是对函数的返回值类型,函数名,形参进行声明,不会实现函数体。

函数的调用:函数调用是使用函数名、形参等,对函数的使用。

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

//函数的声明
extern int add(int a,int b);

int main()
{
    int sum = 0;
    int data1 = 10;
    int data2 = 5;

    //函数的定义
    sum = add(data1,data2);

    printf("sum=%d\n",sum);

    system("pause");
    return 0;
}

//函数的定义
//int为函数的返回值类型;add为函数名;(int a,int b)为形参,用于传入外部值;{}中是函数体。
int add(int a,int b)
{
    //返回一个运算结果
    return a+b;
}

解释: 

4、函数的形参

函数的形参:在定义函数时不为形参开辟空间,在调用函数时才为形参开辟空间。

4.1 普通变量作为函数的形参

普通变量作为函数形参时,函数内部变量,不能修改函数外部的值。

4.2 一维数组作为函数的形参

函数内部想要操作函数外部数组的值,只需要将数组名传递即可,这就导致函数的形参必须是数组。

// 函数的声明
void printf_arr(int num[5], int data);
int main()
{
    int arr[5] = {1, 2, 3, 4, 5};
    int arr_num = sizeof(arr) / sizeof(arr[0]);
    int i = 0;

    printf("调用函数前函数外部:");
    for (i = 0; i < arr_num; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");

    printf_arr(arr, arr_num);

    printf("调用函数后函数外部:");
    for (i = 0; i < arr_num; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
    system("pause");
    return 0;
}
//此时形参的数组的[]号里面的元素个数可以省略
void printf_arr(int num[], int data)
{
    int i = 0;
    num[2] = 100; // 函数内部修改数组的值,函数外部数组的值也被修改
    printf("函数内部:");
    for (i = 0; i < data; i++)
    {
        printf("%d ", num[i]);
    }
    printf("\n");
    return;
}

注:函数外部数组名 arr 等同于函数形参 num 

解释:当一维数组作为函数参数时,传递进来的值被系统优化成指针变量(这个以后再讲,很重要),函数内部变量和函数外部变量都指向同一块内存空间,所以当在函数内部修改数组值后,函数外部的值也被修改,因为他俩是同一块内存。

4.3 二维数组作为函数的形参

函数内部形参可以操作函数外部数组的值。

void printf_arr(int num[][4], int row, int col);
int main()
{
    int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
    int row = sizeof(arr) / sizeof(arr[0]);
    int col = sizeof(arr[0]) / sizeof(arr[0][0]);

    printf_arr(arr, row, col);

    int i = 0, j = 0;
    printf("函数外部:\n");
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }

    printf("\n");
    system("pause");
    return 0;
}
//二维数组作为函数形参可以省略行号,不能省略列号
void printf_arr(int num[][4], int row, int col)
{
    int i = 0, j = 0;
    num[1][1] = 100; // 函数内部修改数组的值,函数外部数组的值也被修改
    printf("函数内部:\n");
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            printf("%d ", num[i][j]);
        }
        printf("\n");
    }

    return;
}

5、随机数

C语言中没有绝对的随机数,所谓的随机数都是将一个数据通过形参穿进去,之后后经过一系列计算,通过返回值传输出来的过程。

C语言中定义了rand()库函数,他就可以产生随机数。

在使用时,我们必须先设置随机数种子,通过srand()函数。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>//sranad函数,rand函数
#include <time.h>//time函数

int main()
{
    //设置随机数种子,注意,随机数种子设置一次即可(也可反复设置),但是,在使用rand后最好不要重新设置,有可能导致数据重复
    //time函数中保存的是1970年1月1日0时0分0秒到此时的秒数,以可以它为基准设置随机数种子
    srand(time(NULL));

    int i = 0;
    for(i=0;i<10;i++)
    {
        //产生随机数,并打印
        printf("%d\n",rand());
    }

    printf("\n");
    system("pause");
    return 0;
}

6、常用排序方法

6.1 选择排序

动画:

程序:

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

//选择排序
//系统优化后void selection_sort(int *data, int num)
void selection_sort(int data[], int num)
{
    int i = 0;
    for (i = 0; i < num - 1; i++)
    {
        int s, j;
        for (s = i, j = s + 1; j < num; j++)
        {
            if (data[j] < data[s])
                s = j;
        }
        if (s != i)
        {
            int tmp = data[s];
            data[s] = data[i];
            data[i] = tmp;
        }
    }
}

int main()
{
    int arr[10] = {0};
    int arr_num = sizeof(arr) / sizeof(arr[0]);
    int i = 0;

    // 获取键盘输入
    printf("请输入%d个int型数据:",arr_num);
    for (i = 0; i < arr_num; i++)
    {
        scanf("%d", &arr[i]);
    }

    // 选择排序
    selection_sort(arr, arr_num);

    // 遍历数组
    for (i = 0; i < arr_num; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");

    system("pause");
    return 0;
}

6.2 冒泡排序

动画:

程序:

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

// 冒泡排序
//系统优化后void bubble_sort(int *data, int num)
void bubble_sort(int data[], int num)
{
    int i = 0;
    for (i = 0; i < num - 1; i++)
    {
        int j = 0;
        int flag = 0;
        for (j = 0; j < num - i - 1; j++)
        {
            // 交换语句
            if (data[j] > data[j + 1])
            {
                int tmp = data[j];
                data[j] = data[j + 1];
                data[j + 1] = tmp;
                flag = 1;
            }
        }
        if (flag == 0) // 说明内层循环没有一次交换 说明数组已经有序
        {
            break;
        }
    }
}

int main()
{
    int arr[10] = {0};
    int arr_num = sizeof(arr) / sizeof(arr[0]);
    int i = 0;

    // 获取键盘输入
    printf("请输入%d个int型数据:", arr_num);
    for (i = 0; i < arr_num; i++)
    {
        scanf("%d", &arr[i]);
    }

    // 冒泡排序
    bubble_sort(arr, arr_num);

    // 遍历数组
    for (i = 0; i < arr_num; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");

    system("pause");
    return 0;
}

7、字符串操作(分函数且不使用库函数)

7.1 字符串的长度测量(等价于strlen)

初学者版本:

// 测量字符串长度
// 系统优化成int my_strlen(char *sor)
int my_strlen(char sor[])
{
    int num = 0;
    while (sor[num] != '\0')
    {
        num++;
    }
    return num;
}

进阶者版本:

// 测量字符串长度
// 系统优化成int my_strlen(char *sor)
int my_strlen(char sor[])
{
    int num = 0;
    while (sor[num] && ++num);//利用了&&的短路特性 和 ++符号在前,先加后使用的特性
   
    return num;
}

7.2 字符串逆序

字符串逆序,不是倒着输出,是将字符串倒过来。

//字符串逆序
//系统优化成void my_overturn(char *sor)
void my_overturn(char sor[])
{
    // 数组首元素下标
    int i = 0;

    // 数组尾元素下标('\0'左边的元素)
    int j = 0;
    while (sor[j] && ++j); // 利用了&&的短路特性 和 ++符号在前,先加后使用的特性
    j--;  // 定位数组尾元素下标('\0'左边的元素)

    // 元素交换
    while (i < j)
    {
        char tem = sor[i];
        sor[i] = sor[j];
        sor[j] = tem;
        i++;
        j--;
    }
}

7.3 字符串拷贝

//字符串拷贝:将sor的内容拷贝到des中
//系统优化成char* my_strcpy(char *des,char *sor)
//返回值类型为char*,即为拷贝后的数组名,初学者可以不用考虑返回值
char* my_strcpy(char des[],char sor[])
{
    int i = 0;
    while(sor[i])
    {
        des[i] = sor[i];
        i++;
    }
    return des;
}

7.4 字符串追加

// 字符串追加:将sor的内容追加到des尾部
// 系统优化成char* my_strcat(char *des,char *sor)
// 返回值类型为char*,即为追加后的数组名,初学者可以不用考虑返回值
char *my_strcat(char des[], char sor[])
{
    // 确定des的尾部
    int i = 0;
    while (des[i] && ++i)
        ;

    // 确定sor的开头
    int j = 0;
    while (sor[j])
    {
        des[i++] = sor[j++]; // 利用++在后面,先使用后自增
    }
    des[i] = '\0'; // 为追加的字符串最后添加'\0'

    return des;
}

7.5 字符查找

// 字符查找:从sor中查找ch字符
// 系统优化成int my_strchr(char *sor,int ch)
// 返回值类型为int,返回的是字符下标,未找到返回-1
int my_strchr(char sor[], int ch)//在库函数中一般使用int类型存放字符类型的数据
{
    int i = 0;
    while (sor[i] != '\0')
    {
        if (sor[i] == ch)
            break;
        i++;
    }
    if (sor[i] == '\0')
        return -1;
    return i;
}

7.6 字符删除

// 字符删除:将sor的中的下标为pos的字符删除
// 系统优化成char* my_delete(char *sor,int pos)
// 返回值类型为char*,即为删除后的数组名,初学者可以不用考虑返回值
char *my_delete(char sor[], int pos)
{
    // 判断pos的有效性
    int len = 0;
    while (sor[len] && ++len)
        ;
    if (!(pos >= 0 && pos < len))
    {
        printf("输入的下标位置无效,删除失败!!!\n");
        return sor;
    }

    // 进行删除动作(移动元素)
    while (sor[pos] != '\0')
    {
        sor[pos] = sor[pos + 1];
        pos++;
    }

    return sor;
}

7.7 字符串的指定位置插入新字符串

// 字符串插入:将sor的插入到des字符串的pos下标位置中
// 系统优化成char *my_insertion(char des[], char sor[],int pos)
// 返回值类型为char*,即为插入后的数组名,初学者可以不用考虑返回值
char *my_insertion(char des[], char sor[],int pos)
{
    // 1、获取des和sor的长度
    int len1 = 0, len2 = 0;
    while (des[len1] && ++len1)
        ;
    while (sor[len2] && ++len2)
        ;

    // 2、判断pos的合法性
    if (!(pos >= 0 && pos <= len1))
    {
        printf("输入的下标位置无效,插入失败!!!\n");
        return des;
    }

    // 3、移动数据保证足够的插入位置(从尾元素开始移动)
    int i = len1;
    while (i >= pos)
    {
        des[i + len2] = des[i];
        i--;
    }

    // 4、将sor的逐个元素插入到pos位置中
    int j = 0;
    while (sor[j] != '\0')
    {
        des[pos] = sor[j];
        pos++;
        j++;
    }

    return des;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值