狂干C语言头像
关注

C语言——函数

1.数组在函数中的传参

全局数组传递的方式:
复制传递方式

  • 实参为数组的指针,形参为数组名(本质上是一个指针变量)

地址传递方式

  • 实参为数组的指针,形参为同类型的指针变量。

题目(1):计算一个一维整型数组的所有元素的和
题目(2):删除字符串中的空格

(1):

#include<stdio.h>  
int array_sum(int array[],int n);  // 函数声明:告诉编译器存在一个叫array_sum的函数,接收整数数组和整数参数,返回整数
int main()  
{  
    int a[]={1,2,3,4,5};  // 定义并初始化整数数组a:元素为1/2/3/4/5,编译器自动计算长度为5(数组下标从0开始)
    int sum=0;  // 定义整数变量sum并初始化为0:用于存储数组求和结果,初始化0避免随机值影响
    int n=sizeof(a)/sizeof(int);  // 计算数组长度:总字节数(sizeof(a))÷单个int字节数(sizeof(int))=元素个数(这里结果是5)
    sum=array_sum(a,n);  // 调用array_sum函数:传入数组a和长度n,将返回的求和结果赋值给sum
    printf("sum=%d \n",sum);  // 打印结果:按"sum=%d"格式输出sum的值,%d是整数占位符,\n是换行符
    return 0;  
}  
int array_sum(int array[],int n)  // 求和函数定义:实现数组求和逻辑,参数为数组array和长度n,返回整数
{  // array_sum函数代码块开始:函数内代码都包含在这个大括号内
    int sum = 0;  // 定义函数内局部变量sum并初始化为0:用于累加数组元素,和main里的sum不是同一个变量
    int i= 0;  // 定义循环变量i并初始化为0:用于遍历数组下标(从0开始)
    printf("n=%d \n",n);  // 打印数组长度n:调试用,验证传入的长度是否正确(这里输出n=5)
    for(i=0;i<n;i++)  // for循环:遍历数组所有元素,i从0到n-1(共n次循环)
    {  // for循环代码块开始:循环体代码包含在此
        sum =sum + array[i];  // 累加数组元素:把第i个元素的值加到sum上(最终sum=1+2+3+4+5=15)
    }  // for循环代码块结束
    return sum;  // 返回累加结果:将sum的值(15)返回给main函数的调用处
}  

(2)

代码:

#include<stdio.h>

void del_space(char*s);

int main()
{
    char s[]="A B C D";

    puts(s);

    del_space(s);

    puts(s);

    return 0;

}
void del_space(char*s)
{
    char *s2=s;
    while (*s !='\0')
    {
        if(*s==' ')
        {

            s++;
        }
        else
     {

            *s2=*s;
            s2++;
            s++;

        }
    }
    *s2='\0';
}

我们可以从「代码结构、核心函数逻辑、执行流程」三个层面拆解解释,让你清晰理解每一步的作用。

一、代码整体结构

代码分为两部分:

  1. main 函数:定义待处理的字符串、打印原始字符串、调用删除空格的函数、打印处理后的字符串。
  2. del_space 函数:实现 “删除字符串中所有空格” 的核心逻辑。

二、逐行解释(先看 main 函数)

#include<stdio.h>  

void del_space(char*s);  // 函数声明:告诉编译器有一个名为del_space的函数,接收字符指针参数,无返回值

int main()
{
    char s[]="A B C D";  // 定义字符数组s,内容是"A B C D"(包含3个空格),数组末尾自动补'\0'(字符串结束符)
    
    puts(s);  // 打印原始字符串,输出:A B C D(换行)
    
    del_space(s);  // 调用删除空格的函数,直接修改原字符数组s的内容
    
    puts(s);  // 打印处理后的字符串,输出:ABCD(换行)
    
    return 0;  // 程序正常结束
}

三、核心:del_space 函数详解

这个函数的核心思路是双指针遍历:用两个指针(s 和 s2)遍历字符串,s 负责 “找非空格字符”,s2 负责 “把非空格字符写回原数组”,最终在新的末尾补结束符。

void del_space(char*s)  // s是指向原字符数组的指针(传址,直接修改原数组)
{
    char *s2=s;  // 定义第二个指针s2,初始和s指向同一个位置(数组起始地址)
    while (*s !='\0')  // 循环:只要s指向的字符不是结束符'\0',就继续遍历
    {
        if(*s==' ')  // 如果当前字符是空格
        {
            s++;  // s指针后移,跳过这个空格(不处理)
        }
        else  // 如果当前字符不是空格
        {
            *s2=*s;  // 把s指向的非空格字符,赋值给s2指向的位置(覆盖原位置)
            s2++;    // s2后移,准备接收下一个非空格字符
            s++;     // s后移,继续找下一个字符
        }
    }
    *s2='\0';  // 遍历结束后,在s2的位置补'\0',作为新字符串的结束符
}

四、关键知识点总结

  1. 字符串本质:C 语言中字符串是字符数组,以 '\0' 结尾,修改数组内容就是修改字符串。
  2. 传址调用del_space 接收的是字符指针(数组首地址),因此函数内的修改会直接作用于原数组(而非副本)。
  3. 双指针技巧:一个指针(s)遍历找有效字符,另一个指针(s2)记录有效字符的存储位置,避免额外开辟数组空间,效率高。
  4. 结束符补全:遍历结束后必须给 s2 赋值 '\0',否则字符串会 “越界”(打印到原始的空格 / 字符)。

2.指针函数

指针函数是指一个函数的返回值为地址量的函数。
指针函数的定义的一般形式如下:

<数据类型> * <函数名称> (<参数说明>)
{
   语句序列;
}

简单来说,指针函数是一种返回值为内存地址(指针)的函数,它的核心是 “函数返回的不是普通数值,而是一个变量的地址”。

1. 定义形式拆解

<数据类型> * <函数名称> ( <参数说明> )
{ 语句序列; }
  • <数据类型> *:表示函数返回的是 “该数据类型变量的地址”(比如int *就是返回 int 变量的地址);
  • <函数名称>:是这个指针函数的名字;
  • <参数说明>:函数的输入参数(和普通函数一样)。

2. 举个实际代码例子(C 语言)

比如写一个 “返回数组元素地址” 的指针函数:

#include <stdio.h>

// 指针函数:返回int数组中指定下标的元素地址
int *f(int a[], int i) {
    // 返回数组a中第i个元素的地址
    return &a[i];
}

int main() {
    int n[] = {10, 20, 30};  // 数组n:存储3个整数
    int *p = f(n, 1);        // 调用指针函数f,接收返回的地址
    printf("值:%d\n", *p);  // 通过地址访问对应的值
    return 0;
}

2. 逐行解释(极简版)

第一步:理解核心符号含义
  • int *f(...)f 是函数名,int * 表示函数返回「int 类型变量的地址」(指针);
  • a[]a 是传入的整数数组(可以理解成 “一组整数的集合”);
  • ii 是要找的数组元素的 “位置编号”(下标);
  • &a[i]& 是取地址符号,意思是 “拿到数组 a 中第 i 个元素的内存地址”;
  • *p* 是解引用符号,意思是 “根据 p 里存的地址,找到对应的数值”。
第二步:逐行拆解代码
代码行解释
int *f(int a[], int i) { return &a[]; }定义指针函数f:1. 接收两个参数:整数数组a、位置编号i;2. 功能:找到数组a中第i个元素的地址,然后返回这个地址。
int n[] = {10, 20, 30};定义数组n,里面存了 3 个数:10(第 0 位)、20(第 1 位)、30(第 2 位)。
int *p = f(n, 1);调用函数f,给它传两个值:数组n、位置编号 1;函数f返回 “数组 n 第 1 位元素的地址”,把这个地址存到指针变量p里。
printf("值:%d\n", *p);根据p里的地址,找到对应的数值(也就是数组 n 第 1 位的 20),打印出来。
return 0;程序正常结束。

3.递归函数

递归函数是指一个函数的函数体中直接或间接调用了该函数自身。
递归函数调用的执行过程分为两个阶段:
递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到 递归的终止条件
回归阶段:按递归终止条件求出结果,并逐步代入递归公式,回归到原问题求解

例如求n的阶乘:

先补基础:阶乘的定义

阶乘(用 ! 表示)是数学概念,规则如下:

  • 0! 和 1! 的结果都是 1(特殊规定);
  • 对于大于 1 的整数 n,n! = n × (n-1) × (n-2) × ... × 1;比如 5! = 5×4×3×2×1 = 120,3! = 3×2×1 = 6

代码

#include<stdio.h>

int fac(int n);
int main()
{
    int n = 0;

    printf("please 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);
    }

3.1 代码核心拆解

#include<stdio.h>  
int fac(int n);     //函数声明

int main()          // 程序入口,从这开始执行
{
    int n = 0;
    printf("please input;");  // 提示输入数字
    scanf("%d",&n);           // 读取你输入的数字存到n里
    printf("%d \n",fac(n));   // 调用fac算n的阶乘,然后输出结果
    return 0;                

// fac函数:专门算阶乘(递归)
int fac(int n)
{
    if(n==0 || n== 1)  // 终止条件:0/1的阶乘直接返回1
    {
        return 1;
    }
    return n*fac(n-1); // 递推:n! = n × (n-1)!,自己调用自己算n-1的阶乘
}
3. 2关键执行逻辑(以输入 3 为例)
  1. main 里调用fac(3),跳去 fac 函数;
  2. fac (3) 发现 n≠0/1,要算3×fac(2),再跳去算 fac (2);
  3. fac (2) 发现 n≠0/1,要算2×fac(1),再跳去算 fac (1);
  4. fac (1) 触发终止条件,返回 1;
  5. 往回算:fac (2)=2×1=2 → fac (3)=3×2=6;
  6. 回到 main,输出结果 6。
3.3递归核心(就两句话)
  • 终止条件:n=0 或 1 时直接返回 1(不然会无限套娃崩溃);
  • 递推:算 n! 先算 (n-1)!,再乘以 n,层层拆解后再层层返回结果。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/2501_93772061/article/details/156098782

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--