C语言函数详解

文章目录

第1章 回顾

1. 数组
  • 本质:相同类型数据的集合,元素地址连续。
  • 数组名:代表数组首元素地址(如int a[5];中,a == &a[0])。
  • 多维数组示例:
    int a[5];          // 一维整型数组
    char a[5][80];     // 二维字符数组(常用于存储多个字符串)
    float a[3][6][20]; // 三维浮点型数组
    a[1][3][10];       // 三维数组元素访问
    
  • 字符数组操作:偏向字符串处理,依赖字符串函数(strlenstrcmpstrcpystrcatgetsputsmemset)。
  • 初始化:未显式初始化时,全局/静态数组默认值为0,局部数组为垃圾值(随机值)。
2. 指针
  • 核心原则:指针类型与保存的地址类型一致,不一致需强制转换。
  • 地址偏移:指针 ± n = 指针当前地址 + n × 空间大小(空间大小由指针类型决定)。
    示例:64位系统中,(short (**))p + 2(long *)p + 2 偏移量均为16字节(short(**)为8字节指针,2×8=16long*为8字节指针,2×8=16)。
  • const修饰:常用于系统库函数传参,限制指针操作(如常量指针、指针常量)。
3. typedef(类型重命名)
  • 作用:给已有数据类型起别名,简化复杂类型定义。
  • 注意点:typedef修饰的是“类型”,而非变量,需区分变量定义与类型重命名。
示例代码含义说明
typedef int INT; INT b;int起别名INTbint类型变量(占4字节,64位系统)
typedef int (*p)[30]; p a;给“指向30个int的数组指针”起别名pa的类型是int (*)[30]
typedef int * INT; INT a, b;int*起别名INTab均为int*类型指针(各占8字节,64位系统)
int *a, b;aint*指针(8字节),bint变量(4字节)(未用typedef,仅修饰a

第2章 必背知识点

本章需熟记内存分区、变量特性、关键字作用。

2.1 C语言5大分区

C程序运行时,内存分为5个独立区域,各区域存储的数据特性不同:

分区名称存储内容管理方式
栈区(Stack)局部变量、临时变量、函数形参系统自动管理(函数调用时分配,函数结束时释放),空间小、速度快
堆区(Heap)程序员自主申请的内存(如动态数组)手动管理(malloc()申请,free()释放),空间大、需避免内存泄漏
静态全局区全局变量、静态修饰的局部变量(static修饰)系统管理(程序启动时分配,程序结束时释放),默认初始值为0
文字常量区常量(如123"hello")、const修饰的常量只读区域(不可修改),程序结束时释放
二进制代码段程序的二进制指令(如函数体代码)只读区域,程序加载时分配

2.2 局部变量

特性说明
关键字无(无需特殊修饰)
存储位置栈区
定义位置函数内部(或代码块内部,如iffor语句块)
使用范围仅在定义它的函数/代码块内部有效(超出范围不可访问)
生命周期函数/代码块运行时创建,运行结束后自动释放(值丢失)
初始值未初始化时为垃圾值(随机值,不可直接使用)

2.3 全局变量

特性说明
关键字无(无需特殊修饰)
存储位置静态全局区
定义位置函数外部(通常在文件开头)
使用范围整个当前文件(所有函数均可访问),若用extern声明可跨文件访问
生命周期程序启动时创建,程序结束时释放(全程有效)
初始值未显式初始化时,默认值为0(静态全局区特性)

2.4 静态局部变量

static修饰的局部变量,兼具局部变量的“作用范围”和全局变量的“生命周期”:

特性说明
关键字static
存储位置静态全局区(而非栈区,区别于普通局部变量)
定义位置函数内部
使用范围仅在定义它的函数内部有效(与普通局部变量一致)
生命周期函数第一次运行时创建,程序结束时释放(全程有效,值可继承)
初始值未显式初始化时默认值为0;显式初始化时,仅第一次函数调用时初始化

示例代码(静态局部变量的值继承):

#include <stdio.h>
void fun(void); 

int main() {
    for (int i = 0; i < 3; i++) {
        fun(); // 调用3次fun,观察a的值变化
    }
    return 0; 
}

void fun(void) { 
    static int a = 0; // 仅第一次调用时初始化a=0
    a++; // 每次调用继承上次的值,依次为1、2、3
    printf("a=%d\n", a); // 输出:a=1 → a=2 → a=3
}

2.5 外部声明变量(了解)

extern修饰,用于“声明”外部文件的全局变量,而非“定义”变量。

特性说明
关键字extern
存储位置静态全局区(变量实际定义在外部文件中)
核心作用声明“该变量来自外部文件”,避免重复定义(仅声明,不分配空间)
使用场景多文件编程时,跨文件访问全局变量(需确保外部文件已定义该变量)

示例(多文件协作):

  • A.c(定义变量):int a = 5;(分配空间,定义全局变量a)
  • B.c(声明变量):extern int a;(仅声明,不分配空间,可使用A.c中的a)

2.6 关键字

2.6.1 static(静态修饰符)

static是C语言核心关键字,主要有两大作用:

  1. 修饰局部变量:延长生命周期

    • 普通局部变量(栈区):函数结束后值丢失;
    • 静态局部变量(静态全局区):函数结束后值保留,下次调用继承。
  2. 修饰全局变量/函数:私有化(限制作用域)

    • 未修饰的全局变量/函数:默认“外部可见”,可通过extern跨文件访问;
    • 静态全局变量/函数:仅在当前文件内可见,外部文件无法访问(避免命名冲突)。
    • 有些别人封装的函数有时加上staic,如果需要在另外的文件中使用需要删除staic关键字
2.6.2 extern(外部声明符)

extern仅用于“声明”,不用于“定义”,核心作用:

  1. 声明外部全局变量:告诉编译器“该变量已在其他文件定义,此处仅使用”。
  2. 声明外部函数:多文件编程时,声明其他文件定义的函数(若函数定义在当前文件后,也可用于提前声明)。

注意:extern不能初始化变量(如extern int a = 5;错误,会被视为定义,而非声明)。

2.7 局部变量与全局变量能否同名?

可以同名,遵循就近原则

  • 查找变量时,优先在“当前代码层”(如函数内部、if块)查找;
  • 若当前层无该变量,则向上一层查找(如函数内部→文件全局)。

示例代码(就近原则验证):

#include <stdio.h> 
int a[5] = {6,6,7,7,8}; // 全局变量(最外层)

int main() {
    int a[5] = {1,2,3,4,5}; // 局部变量(main函数层,覆盖全局)
    if (1) {
        int a[5] = {1,1,1,1,1}; // 临时变量(if块层,覆盖main局部)
        for (int i=0; i<5; i++) {
            printf("%d ", a[i]); // 输出:1 1 1 1 1(优先if块的a)
        }
        printf("\n"); 
    }
    for (int i=0; i<5; i++) {
        printf("%d ", a[i]); // 输出:1 2 3 4 5(main函数的a)
    }
    printf("\n"); 
    return 0;
}

2.8 实参&形参

实参(实际参数)与形参(形式参数)是函数传参的核心概念,二者需满足“三个一致”(类型一致、数量一直、顺序一致)。

对比维度实参(实际参数)形参(形式参数)
定义时机函数调用时传入(如fun(1,2)中的12函数定义时声明(如void fun(int a, int b)中的ab
本质具体的值或变量(有实际内存与值)临时变量(仅在函数内部有效,函数调用时分配空间,结束后释放)
作用向函数传递数据接收实参传递的数据,用于函数内部运算

示例代码(实参与形参):

#include <stdio.h> 
void fun(int a, int b); // 函数声明(形参a、b在此声明)

int main() {
    fun(1, 2); // 函数调用(实参1、2传入)
    return 0; 
} 

// 函数定义(形参a、b在此定义,接收实参值)
void fun(int a, int b) { 
    int c = 0; 
    c = a + b; 
    printf("%d\n", c); // 输出:3(实参1+2的结果)
}

第3章 函数

函数是C语言的“代码封装单元”,用于实现模块化编程,提高代码复用率,减少重复代码。

3.1 函数的作用

  1. 封装代码:将一个功能(如求和、排序)封装为一个函数,逻辑更清晰。
  2. 复用代码:同一功能可在多个地方调用,无需重复编写。
  3. 简化维护:修改功能时,仅需修改函数内部代码,无需修改所有调用处。
  4. 模块化协作:多文件编程时,可按功能拆分函数,便于团队协作。

3.2 函数分类

按功能与地位,函数分为主函数子函数

3.2.1 主函数(main()
  • 特殊地位:C程序的唯一入口出口,程序从main()开始执行,从main()结束。
  • 特性
    • 有且仅有一个(一个程序不能有多个main());
    • 可调用子函数;
    • 返回值类型为int(默认返回0,代表程序正常结束)。
  • 基本格式:
    int main() {
        // 代码逻辑
        return 0; // 程序正常结束,返回0
    }
    
3.2.2 子函数
  • 本质:实现特定功能的代码块,被调用时才执行
  • 特性
    • 可多个(根据功能需求定义);
    • 子函数之间可互相调用;
    • 不能调用主函数(主函数是入口,子函数调用主函数会导致死循环);
    • 命名需遵守标识符规则(字母、数字、下划线,首字符非数字)。

3.3 函数命名

遵循“望文生义”原则,名称直接体现函数功能,便于阅读与维护:

  • 示例:求和函数命名为sum,求字符串长度函数命名为str_len
  • 辅助:复杂函数需加注释,说明功能、参数含义、返回值含义。

3.4 函数定义格式

函数定义需明确“返回值类型”“函数名”“形参”和“函数体”,基本格式:

函数类型 函数名(形参类型1 形参1, 形参类型2 形参2, ...) {
    // 函数体(封装的代码逻辑)
    [return 返回值;] // 若函数类型非void,需返回对应类型的值
}
  • 函数类型:与返回值类型一致(如返回int则类型为int,无返回值则为void)。
  • 形参列表:无参数时,可写void或空(如void fun(void)void fun())。

3.5 函数传参

函数传参是“实参向形参传递数据”的过程,分为值传参地址传参,核心区别是“是否影响实参的值”。

3.5.1 值传参
  • 原理:实参将“值的副本”传递给形参,形参是独立的临时变量。
  • 特点:修改形参的值,不会影响实参(形参与实参内存地址不同)。如下代码fun1里再怎么增加b的值a还是5不变。
  • 示例代码:
    #include <stdio.h> 
    void fun1(int b); // 值传参函数声明
    
    int main() {
        int a = 5; 
        fun1(a); // 实参a的值(5)传递给形参b
        printf("a=%d\n", a); // 输出:a=5(形参b修改不影响a)
        return 0; 
    } 
    
    void fun1(int b) { 
        b++; // 修改形参b(b从5变为6)
        printf("b=%d\n", b); // 输出:b=6
    }
    
3.5.2 地址传参
  • 原理:实参将“变量的地址”传递给形参(形参为指针类型),形参通过地址间接操作实参内存。
  • 特点:修改形参指向的内存值,会直接影响实参(形参与实参指向同一内存)。
  • 示例代码:
    #include <stdio.h> 
    void fun2(int *p); // 地址传参函数声明(形参为int*指针)
    
    int main() {
        int a = 5; 
        fun2(&a); // 实参为a的地址(&a),传递给指针p
        printf("a=%d\n", a); // 输出:a=6(形参p通过地址修改了a)
        return 0; 
    } 
    
    void fun2(int *p) {
        ++(*p); // 通过指针p间接修改a的值(a从5变为6)
        printf("fun2=%d\n", *p); // 输出:fun2=6
    }
    

3.6 函数类型

函数类型由“返回值类型”决定,不同类型对应不同用法,核心规则:

  • 返回值唯一:一个函数只能返回一个值(若需返回多个值,需用地址传参或结构体,不需要一定有return,把多个值写入一个结构体或者数组,将结构体或数组的地址传入,直接就能修改其中的值)。
  • return作用:执行return后,函数立即结束,后续代码不再执行。

常见函数类型示例:

函数类型含义示例代码
void无返回值void fun(void) { printf("Hello"); }(无需return,或return;)
int返回整型值int sum(int a, int b) { return a + b; }(返回a+b的结果)
float返回浮点型值float avg(int a, int b) { return (a + b)/2.0; }(返回平均值)
char*返回字符指针(地址)char* get_str() { return "hello"; }(返回字符串首地址)

示例(有返回值函数的使用):

#include <stdio.h>
int fun(void); // 函数声明(返回int类型)

int main() {
    int ret = fun(); // 接收函数返回值
    printf("%d\n", ret); // 输出:6(fun返回a=6)
    return 0; 
}

int fun(void) {
    int a = 5; 
    a++; // a从5变为6
    return a; // 返回a的值(6)
}

3.7 函数的声明

函数声明的作用是“告诉编译器函数的存在”,避免“未定义函数”错误,适用场景:

  • 函数定义在main()之后;
  • 函数定义在其他文件中。
声明格式

函数定义的“第一行”末尾加;,即:

函数类型 函数名(形参类型1 形参1, 形参类型2 形参2, ...);
  • 简化写法:形参名可省略,仅保留类型(如void fun(int, int);)。
示例代码
#include <stdio.h>
// 函数声明(fun定义在main之后,需提前声明)
void fun(int a, int b); 

int main() {
    fun(1, 2); // 调用fun,编译器已知fun存在
    return 0; 
}

// 函数定义(在main之后)
void fun(int a, int b) { 
    printf("%d\n", a + b); // 输出:3
}

3.8 函数调用

函数调用是“执行函数代码”的过程,格式与注意事项:

  • 调用格式函数名(实参1, 实参2, ...);(无参数则写函数名();)。
  • 核心要求:实参与形参需满足“三一致”(类型、数量、顺序)。
  • 返回值处理
    • 有返回值函数:可将返回值赋值给变量(如int ret = sum(1,2);),或直接使用(如printf("%d", sum(1,2));)。
    • 无返回值函数(void):直接调用(如fun();),无需处理返回值。

3.9 递归函数

递归函数是“自己调用自己”的函数,需满足“终止条件”(避免死循环),核心思想是“分治”(将大问题拆为小问题)。

3.9.1 固定模板

递归函数必须包含两大要素:递归终止条件(停止调用自己)和递归调用语句(调用自己,缩小问题规模):

函数类型 递归函数名(参数) {
    // 1. 递归终止条件(必须有,否则死循环)
    if (终止条件) {
        return 基础值; // 问题最小化时的结果
    }
    // 2. 递归调用(调用自己,参数需向终止条件靠近)
    return 递归表达式; 
}
3.9.2 递归示例代码
  1. 递归求和:计算1+2+3+…+n
    思路:sum(n) = n + sum(n-1),终止条件n=1sum(1)=1)。

    #include <stdio.h>
    int sum(int n); 
    
    int main() {
        printf("%d\n", sum(5)); // 输出:15(1+2+3+4+5)
        return 0;
    }
    
    int sum(int n) {
        if (n == 1) { // 终止条件:n=1时返回1
            return 1;
        }
        return n + sum(n-1); // 递归调用:sum(5)=5+sum(4),直至sum(1)
    }
    
  2. 递归转二进制:输入十进制数,输出对应的二进制(逆序输出,需再处理)
    思路:十进制数 % 2取余数(二进制位),十进制数 / 2缩小规模,终止条件十进制数=0

    #include <stdio.h>
    void dec_to_bin(int n); 
    
    int main() {
        dec_to_bin(10); // 输出:1010,即10的二进制
        return 0;
    }
    
    void dec_to_bin(int n) {
        if (n == 0) { // 终止条件:n=0时停止
            return;
        }
        dec_to_bin(n / 2); // 递归调用,先处理高位
        printf("%d", n % 2); // 输出余数(二进制位)
    }
    
  3. 练习:计算1-2+3-4+5-…±n(提示:终止条件n=1,递归表达式n * (n%2==1?1:-1) + fun(n-1))。

3.10 指针函数&函数指针

二者是“指针与函数”的结合,核心区别是“本质是函数还是指针”。

1. 指针函数(返回值为指针的函数)
  • 本质:函数,其返回值是一个地址(指针)。
  • 定义格式返回值类型 * 函数名(形参列表) { ... }
  • 示例:返回两个数中较大值的地址
    #include <stdio.h>
    int *get_max(int *a, int *b); // 指针函数声明
    
    int main() {
        int x=3, y=5;
        int *p = get_max(&x, &y); // 接收返回的指针(指向y)
        printf("%d\n", *p); // 输出:5
        return 0;
    }
    
    int *get_max(int *a, int *b) {
        return (*a > *b) ? a : b; // 返回较大值的地址
    }
    
2. 函数指针(指向函数的指针)
  • 本质:指针,其指向的内存是函数的入口地址。
  • 定义格式返回值类型 (*指针名)(形参类型列表);()不可省略,否则变为指针函数)。
  • 核心用法:通过函数指针调用函数(与直接调用函数效果一致)。

示例代码:

#include <stdio.h>
void fun(void); // 函数声明

int main() {
    void (*p)(void) = fun; // 定义函数指针p,指向fun
    fun();  // 直接调用fun
    p();    // 通过函数指针p调用fun(与fun()等价)
    return 0;
}

void fun(void) {
    printf("Hello Function Pointer!\n"); // 输出:Hello Function Pointer!
}
3. 函数指针数组(存储函数指针的数组)
  • 定义格式:返回值类型 (*数组名[数组大小])(形参类型列表);
  • 用途:批量管理同类型函数(如多个同参数、同返回值的函数)。

示例代码:

#include <stdio.h>
// 两个同类型函数(int返回值,两个int参数)
int fun1(int a, int b) { return a + b; }
int fun2(int n, int m) { return n * m; }

int main() {
    // 定义函数指针数组p,存储fun1和fun2的地址
    int (*p[2])(int, int) = {fun1, fun2}; 
    printf("%d\n", p[0](5,6)); // 调用fun1(5,6),输出:11
    printf("%d\n", p[1](1,2)); // 调用fun2(1,2),输出:2
    return 0;
}

3.11 函数传参传递数组的3种形式(重点)

数组传参的本质是“传递数组首元素地址”(而非整个数组),因此形参有3种等价写法,均为指针类型。

假设有字符数组char a[50] = "hello";,函数传参的3种形式如下:

形参形式函数声明示例说明
指针形式(char *pvoid fun(char *p);最直观,p接收数组首元素地址(p == a),通过p[i]*(p+i)访问元素
数组形式(char p[]void fun(char p[]);语法糖,编译器会将p[]解析为char *p,与指针形式完全等价
定长数组形式(char p[50]void fun(char p[50]);定长无意义,编译器仍解析为char *p,数组长度不影响传参

示例代码(3种形式等价验证):

#include <stdio.h>
// 3种形参形式的函数声明(等价)
void fun1(char *p); 
void fun2(char p[]); 
void fun3(char p[50]); 

int main() {
    char a[50] = "hello";
    fun1(a); // 传递数组首地址
    fun2(a);
    fun3(a);
    return 0;
}

// 指针形式:通过*(p+i)访问元素
void fun1(char *p) {
    for (int i=0; p[i]!='\0'; i++) {
        printf("%c", *(p+i)); // 输出:hello
    }
    printf("\n");
}

// 数组形式:通过p[i]访问元素
void fun2(char p[]) {
    printf("%s\n", p); // 输出:hello(p是数组首地址,%s打印字符串)
}

// 定长数组形式:与前两种等价
void fun3(char p[50]) {
    printf("%s\n", p); // 输出:hello
}

3.12 函数示例代码

以下示例覆盖“无参无返回值”“有参有返回值”“地址传参”“全局变量传参”等场景,均实现“两数求和”功能。

示例1:无参无返回值(函数内部输入输出)
#include <stdio.h> 
void fun(void); // 函数声明

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

void fun(void) {
    int a=0, b=0, c=0;
    scanf("%d%d", &a, &b); // 函数内部输入
    c = a + b;
    printf("%d\n", c); // 函数内部输出
}
示例2:有参无返回值(主函数输入,函数输出)
#include <stdio.h> 
void fun(int a, int b); // 函数声明

int main() {
    int a=0, b=0;
    scanf("%d%d", &a, &b); // 主函数输入
    fun(a, b); // 传递实参
    return 0; 
} 

void fun(int a, int b) { 
    int c=0; 
    c = a + b;
    printf("%d\n", c); // 函数输出
}
示例3:有参有返回值(主函数输入+接收结果+输出)
#include <stdio.h> 
int fun(int a, int b); // 函数声明(返回int类型)

int main() {
    int a=0, b=0, ret=0;
    scanf("%d%d", &a, &b); // 主函数输入
    ret = fun(a, b); // 接收函数返回值
    printf("%d\n", ret); // 主函数输出
    return 0; 
} 

int fun(int a, int b) { 
    int c=0; 
    c = a + b;
    return c; // 返回求和结果
}
示例4:地址传参(函数内部修改主函数变量)
#include <stdio.h> 
void fun(int *a, int *b); // 形参为指针

int main() {
    int a=0, b=0;
    scanf("%d%d", &a, &b);
    fun(&a, &b); // 传递变量地址
    return 0;
} 

void fun(int *a, int *b) { 
    int c=0; 
    c = *a + *b; // 通过指针访问主函数变量
    printf("%d\n", c); // 输出结果
}
示例5:全局变量传参(函数直接访问全局变量)
#include <stdio.h> 
void fun(void); 
int a=0, b=0, c=0; // 全局变量(函数可直接访问)

int main() {
    scanf("%d%d", &a, &b); // 主函数给全局变量赋值
    fun(); // 函数直接使用全局变量
    return 0;
} 

void fun(void) { 
    c = a + b; // 直接访问全局变量a、b
    printf("%d\n", c); 
}

第4章 回顾函数

本章汇总函数相关核心知识点,形成知识体系,重点掌握“内存分区”“变量特性”“关键字作用”“函数传参”四大模块。

4.1 核心知识点汇总

1. 五大分区(再梳理)
分区关键存储内容核心特性
栈区局部变量、形参、临时变量自动分配释放,生命周期短(随函数)
堆区动态内存(malloc申请)手动管理,生命周期长(需free释放)
静态全局区全局变量、静态局部变量(static自动分配释放,生命周期长(随程序),默认值为0
文字常量区常量、const变量只读,不可修改
二进制代码段函数体代码只读,程序加载时分配
2. 局部变量与全局变量对比(表格版)
对比维度局部变量全局变量
存储位置栈区静态全局区
作用范围函数/代码块内部当前文件(全局可见)
生命周期随函数/代码块(创建→结束)随程序(启动→结束)
初始值垃圾值默认0
关键字无(加static变为静态全局变量)
3. 关键字作用(重点)
关键字作用1(修饰局部变量)作用2(修饰全局变量/函数)作用3(其他)
static延长生命周期(静态全局区存储)私有化(仅当前文件可见)-
extern-声明外部变量/函数(跨文件访问)避免重复定义
typedef--重命名数据类型(简化复杂类型)
4. 实参与形参对比
维度实参形参
定义时机函数调用时函数定义时
本质具体值/变量(有实际内存)临时变量(仅函数内部有效)
数据传递传递值/地址给形参接收实参数据
影响范围地址传参时可能被形参修改,值传参不会仅影响自身,不影响实参(值传参)

4.2 字符串函数重写示例(实践巩固)

通过重写标准字符串函数,加深“指针操作”“函数传参”的理解。

1. 重写strlen(计算字符串长度)

功能:计算字符串有效长度(不含结束符\0)。

#include <stdio.h> 
int strlen_t(char *p); // 自定义strlen函数

int main() {
    char a[500] = {0}; 
    gets(a); // 输入字符串
    int len = strlen_t(a); // 调用自定义函数
    printf("%d\n", len); // 输出长度
    return 0; 
}

int strlen_t(char *p) {
    int i = 0; 
    while (*p) { // 循环至'\0'结束(*p为'\0'时循环终止)
        p++; // 指针后移(访问下一个字符)
        i++; // 计数+1
    }
    return i; // 返回长度
}
2. 重写strcmp(比较两个字符串)

功能:比较两个字符串,返回差值(相等返回0,s1>s2返回正数,s1<s2返回负数)。

#include <stdio.h> 
int strcmp_t(char *s1, char *s2); // 自定义strcmp函数

int main() {
    char a[500] = {0}, b[500] = {0};
    int ret = 0;
    gets(a); 
    gets(b);
    ret = strcmp_t(a, b); // 比较两个字符串
    if (ret == 0) {
        printf("相同\n");
    } else {
        printf("不同\n");
    }
    return 0; 
}

int strcmp_t(char *s1, char *s2) { 
    // 循环条件:两字符相等且未到字符串结束(*s1!='\0')
    while (!(*s1 - *s2) && (*s1)) { 
        s1++; // 指针后移
        s2++;
    }
    return *s1 - *s2; // 返回最后一个字符的差值
}
3. 重写strcpy(字符串复制)

功能:将s2指向的字符串复制到s1指向的空间(含\0),返回s1首地址。

#include <stdio.h> 
char *strcpy_t(char *s1, char *s2); // 指针函数(返回s1地址)

int main() {
    char a[500] = {0}, b[500] = {0};
    gets(b); // 输入源字符串
    char *p = strcpy_t(a, b); // 复制s2到s1,接收返回地址
    printf("%s\n", p); // 输出复制结果
    return 0; 
}

char *strcpy_t(char *s1, char *s2) {
    char *tmp = s1; // 保存s1首地址(避免后续指针后移丢失)
    // 循环条件:*s2!='\0'(复制至结束符),赋值后指针后移
    while (*s1 = *s2) { 
        s1++;
        s2++;
    }
    return tmp; // 返回s1首地址
}
4. 重写strcat(字符串拼接)

功能:将s2指向的字符串追加到s1指向的字符串末尾(覆盖s1\0,再添加s2\0),返回s1首地址。

#include <stdio.h> 
char *strcat_t(char *s1, char *s2); // 指针函数

int main() {
    char a[500] = {0}, b[500] = {0};
    gets(a); // 输入目标字符串
    gets(b); // 输入源字符串
    char *p = strcat_t(a, b); // 拼接字符串
    printf("%s\n", p); // 输出结果
    return 0; 
}

char *strcat_t(char *s1, char *s2) {
    char *tmp = s1; // 保存s1首地址
    // 第一步:将s1指针移至末尾(*s1!='\0')
    while (*s1) { 
        s1++;
    }
    // 第二步:将s2复制到s1末尾(含'\0')
    while (*s1 = *s2) { 
        s1++;
        s2++;
    }
    return tmp; // 返回s1首地址
}
该数据集通过合成方式模拟了多种发动机在运行过程中的传感器监测数据,旨在构建一个用于机械系统故障检测的基准资源,特别适用于汽车领域的诊断分析。数据按固定时间间隔采集,涵盖了发动机性能指标、异常状态以及工作模式等多维度信息。 时间戳:数据类型为日期时间,记录了每个数据点的采集时刻。序列起始于2024年12月24日10:00,并以5分钟为间隔持续生成,体现了对发动机运行状态的连续监测。 温度(摄氏度):以浮点数形式记录发动机的温度读数。其数值范围通常处于60至120摄氏度之间,反映了发动机在常规工况下的典型温度区间。 转速(转/分钟):以浮点数表示发动机曲轴的旋转速度。该参数在1000至4000转/分钟的范围内随机生成,符合多数发动机在正常运转时的转速特征。 燃油效率(公里/升):浮点型变量,用于衡量发动机的燃料利用效能,即每升燃料所能支持的行驶里程。其取值范围设定在15至30公里/升之间。 振动_X、振动_Y、振动_Z:这三个浮点数列分别记录了发动机在三维空间坐标系中各轴向的振动强度。测量值标准化至0到1的标度,较高的数值通常暗示存在异常振动,可能与潜在的机械故障相关。 扭矩(牛·米):以浮点数表征发动机输出的旋转力矩,数值区间为50至200牛·米,体现了发动机的负载能力。 功率输出(千瓦):浮点型变量,描述发动机单位时间内做功的速率,取值范围为20至100千瓦。 故障状态:整型分类变量,用于标识发动机的异常程度,共分为四个等级:0代表正常状态,1表示轻微故障,2对应中等故障,3指示严重故障。该列作为分类任务的目标变量,支持基于传感器数据预测故障等级。 运行模式:字符串类型变量,描述发动机当前的工作状态,主要包括:怠速(发动机运转但无负载)、巡航(发动机在常规负载下平稳运行)、重载(发动机承受高负荷或高压工况)。 数据集整体包含1000条记录,每条记录对应特定时刻的发动机性能快照。其中故障状态涵盖从正常到严重故障的四级分类,有助于训练模型实现故障预测与诊断。所有数据均为合成生成,旨在模拟真实的发动机性能变化与典型故障场景,所包含的温度、转速、燃油效率、振动、扭矩及功率输出等关键传感指标,均为影响发动机故障判定的重要因素。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值