当前位置: 首页 > news >正文

9-函数的定义及用法

一.前言

      C 语⾔强调模块化编程,这⾥所说的模块就是函数,即把每⼀个独⽴的功能均抽象为⼀个函数来实现。从⼀定意义上讲,C 语⾔就是由⼀系列函数串组成的。 我们之前把所有代码都写在 main 函数中,这样虽然程序的功能正常实现,但显得杂乱⽆章,代码可读性、可维护性较差。学完本节之后,应把每个具体的独⽴功能单位均抽象为⼀个函数,在 main 函数中 调⽤各个函数。

    1.概念: 

     函数是⼀系列 C 语⾔语句的集合, 为了完成某个可能会重复使⽤的功能, ⽽封装起来的代码。 

     设计的好处: 实现模块化的编程思想,提⾼程序的可读性。

     函数设计要求: ⻅名知意。

示例代码:

   2.使用方法:

       方法1:先声明在定义

返回值类型 函数名(类型 参数1,类型 参数2….);    // 函数的声明

int main()

 {
   函数名(参数1,参数2,参数3);                //  函数的调用
   return 0;
 }



返回值类型 函数名(类型 参数1,类型 参数2….)     // 函数的定义
{

    C语⾔代码;
    return 数据;
}
  

示例代码:

#include<stdio.h>
void printf_star();
/// *
/// **
/// ***
int main()                        // 入口
{
   
    for(int k = 1; k <= 3; k++)
    {
        printf_star();                 // 函数的调用
        
    }
    return 0; 
}   
    /// void表示返回空
    void printf_star()               // 函数的定义
    {
        for(int i = 1; i <= 3; i++)     // i代表行数
        {
            for(int j = 1;j <= i; j++)  //  每行输出的星星个数
            {
                printf("*");
            }
            printf("\n");
        }
        return 0;
    }

  

练习:

1. 设计⼀个 void do_sum() 函数,要求函数内部⽆参数和返回值,内部定义⼀个变量 int m, 要求⽤户从键盘输⼊⼀个数据赋值给 m 。

 判断 m 的值 , 若是 m 为奇数,输出 1 + 3 + 5 + 7 + 9 +...+m 的和 . 若是 m 为偶数,输出 0 + 2 + 4 + 6 + 8 +...+m 的和 . 

#include <stdio.h>

void do_sum() {
    int m;
    printf("请输入一个整数:");
    scanf("%d", &m);
    
    int sum = 0;
    
    if (m % 2 != 0) {
        // 计算奇数和 1+3+5+...+m
        for (int i = 1; i <= m; i += 2) {
            sum += i;
        }
    } else {
        // 计算偶数和 0+2+4+...+m
        for (int i = 0; i <= m; i += 2) {
            sum += i;
        }
    }
    
    printf("计算结果为:%d\n", sum);
}

int main() {
    do_sum();
    return 0;
}

2. 设计⼀个 void do_Result() 函数,要求函数内部定义 int a,b 两个变量,然后从键盘输⼊ 2 个整数赋值给 a,b ,并输出 (a + b) / 2 的值。

#include <stdio.h>

void do_Result() {
    int a, b;
    printf("请输入两个整数(用空格分隔):");
    scanf("%d %d", &a, &b);
    
    int result = (a + b) / 2;
    printf("计算结果为:%d\n", result);
}

int main() {
    do_Result();
    return 0;
}

二.全局 静态 局部变量

1.全局变量:

全局变量: 


在函数外部定义的变量,我们叫做全局变量.


特点:

(1) 在本⽂件中的任何函数中都可以使⽤。   ----作⽤域

(2) 在定义变量的时候,系统会申请内存空间,main()函数结束的时候,
    系统会回收全局变量对应的内存空间.   ----⽣命周期

(3) 全局变量未初始化,值默认为0

2.局部变量:

局部变量: 


在函数内部定义的变量,我们叫做局部变量。


特点:

(1) 只能在定义它的那个函数内部使⽤,其他位置不能使⽤。---作⽤域

(2) 调⽤函数时,运⾏在定义变量代码的时候,系统会申请内存空间, 
    当定义该变量的函数调⽤结束后,系统会回收局部变量对应的内存空间. ----⽣命周期

(3) 局部变量未初始化,值默认为随机值。

示例代码:

#include<stdio.h>

    int global = 20;

    void do_global()
    {
        global ++;
        printf("global = %d\n",global);
    }

    void do_local()
    {
        int t = 10;
        t++;
        printf("t = %d\n", t);
        return ;
    }

int main()
{
    do_global();
    do_global();
    do_global();
    printf("======================\n");
    global++;
    printf("g = %d\n",global);
    do_local();
    do_local();
    do_local();
       
    return 0;
}

3.静态局部变量

静态局部变量


格式: static  数据类型 变量名;

     static int c;


特点:
(1)静态局部变量,可以改变原来变量的⽣命周期,当定义该变量的函数调⽤结束后,系统不会回收对应的内存空间,当main()函数结束后, 内存空间才会被回收.

(2)只能在定义它的那个函数内部使⽤,其他位置不能使⽤。---作⽤域

(3)静态局部变量未初始化,值默认为0

示例代码:

#include <stdio.h>
 void do_local()
 {
        static int t = 10;
        t++;
        printf("t = %d\n",t);
 }
 int main()
 {
        do_local();
        do_local();
        do_local();
        return 0;
 }

练习:

定义全局变量 global_data = 0; 设计⽆参数的函数 global_calc() ,在这个函数内部 要求⽤户从键盘输⼊⼀个数据赋值给 global_data, 然后要求 该函数输出,从 1~global_data 之间所有能被 7 整除的数据。 main 函数来调⽤以下 global_calc() 这个函数。

#include <stdio.h>

int global_data = 0;  // 定义全局变量

void global_calc() {
    printf("请输入一个正整数:");
    scanf("%d", &global_data);
    
    if(global_data < 7) {
        printf("没有符合条件的数字\n");
        return;
    }
    
    printf("能被7整除的数字:\n");
    for(int i = 7; i <= global_data; i++) {
        if(i % 7 == 0) {
            printf("%d ", i);
        }
    }
    printf("\n");
}

int main() {
    global_calc();
    return 0;
}

三.函数传参之值传递

本质: 函数传参的本质, 变量之间的赋值操作。
功能 :在传递变量中保存的数据。核⼼思想是传递什么样⼦类型的变量。
在接收的位置,就定义什么样类型的变量来接受。

示例代码:

#include<stdio.h>

int do_calc(const int x,const int y)
    {
        int sum = 0;
        printf("x = %d y = %d\n", x,y);
        sum = x + y;
        return sum;
    }
int main()
{


        int a = 0,b = 0;
        int t = 0;
        printf("please input two data :");
        scanf("%d%d",&a,&b);

        t = do_calc(a,b);
        printf("a + b =%d\n", t);

        t = t*100-8;
        printf("expression result = %d\n",t);

    
    
    return 0;
}

运行结果:

四.函数传参之地址传递

功能:我们在使⽤函数传参的时候,除了传递普通的变量外,在某些时刻不得不传递变量的地址。
传递变量的地址,我们在使⽤的时候,就只能通过指针来接收了。


好处:传递变量的地址,通过指针接收,可⽤通过指针修改原变量的值。

示例代码:

#include<stdio.h>

void change_value(int *x, int*y)
{
    int t;
    t = *x;
    *x = *y;
    *y = t;
    return ;
}

void do_calc(int x, int y,int *m,int *n)
{
    int sum1 = 0,sum2 = 0;
    sum1 = x+y;
    sum2 = x-y;
    *m = sum1;
    *n = sum2;
    return ;
}

int main()
{
    int a = 0,b = 0;
    int ret1 = 0,ret2 = 0;
    int t = 0;
    printf("please input two data :");
    scanf("%d%d",&a,&b);
    do_calc(a,b,&ret1,&ret2);
    printf("a+b=%d\n",ret1);
    printf("a-b=%d\n",ret2);
    
    return 0;
}

练习:

1.main() 函数定义 4 个变量, int a,b,max_value,sum. 要求⽤户从键盘输⼊2 个数据赋值给 a和b 

2. 设计⼀个叫做 calc_data() 函数,⾃定义返回值和参数,要求该函数中 求出 a 和 b 中的最⼤值,函数调⽤结束后,要求给 main 函数 max_value 存储的 是两个数中较⼤的值。在求两个数的和,要求给 main 函数 sunm 存储的两个 数据的和。

3. 在 main 函数中打印 max_value 和 sum 的值。

#include <stdio.h>

void calc_data(int x, int y, int *max_ptr, int *sum_ptr) {
    *max_ptr = (x > y) ? x : y;
    *sum_ptr = x + y;
}

int main() {
    int a, b, max_value, sum;
    
    printf("请输入两个整数:");
    scanf("%d %d", &a, &b);
    
    calc_data(a, b, &max_value, &sum);
    
    printf("最大值:%d\n", max_value);
    printf("两数之和:%d\n", sum);
    
    return 0;
}

五.. 函数传参之数组

本质 :函数传参的本质是变量间的赋值操作,数组名本质是⾸元素的地址,传递数组的⾸地址,我 们定义指针来接收接⼝。

示例代码:

#include<stdio.h>

void input_array(int *p,const int plen)
    {
        int i = 0;
        printf("please input %d data:",plen);
        for(i = 0; i < plen; i++)
        {
            scanf("%d",&p[i]);
        }
    }

void output_array(int *p, const int plen)
    {
        int i = 0;
        for(i = 0; i < plen; i++)
        {
            printf("%d\n",&p[i]);
        }
    }
    
int main()
{
    int a[5] = {0};
    int len = sizeof(a) / sizeof(a[0]);
    input_array(a,len);
    output_array(a,len);

    
    return 0;
}

六.字符串相关操作函数1

1.strcpy   ---- 字符串拷贝函数

头文件: #include <string.h>

strcpy (char dest[], char src[])   ---------string copy

功能:把src数组中'\0'之前的所有字符,连同'\0'一起拷贝到dest中。
      要求在定义dest时要足够大

参数:
    dest--------目标数组
    src --------源数组---------[数组首地址或字符串]



例如:

    char buf [20] = {0};

    strcpy(buf,"hello");
    
    printf("buf = %s\n", buf);
    

代码示例:

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

int main()
{
    char buf[20] = {'h','e','l','l','o','\0'};
    int i = 0;

    strcpy(buf,"QQ");
    for(i = 0; i < 20; i++)
    {
        printf("%c: %d\n",buf[i],buf[i]);
    }    
    printf("buf = %s\n",buf);
    
    return 0;
}

2.strcat

头⽂件: #include <string.h>


strcat(char dest[], char src[]);

功能:把src数组'\0'之前的字符串追加到dest字符串后,若是dest中有'\0',会把dest中的'\0'给覆盖掉,然后组成的dest字符串会重新添加'\0'


参数:

例如:
        @ dest      ⽬标数组

        @ src       源数组    [字符数组或字符串]

 
 char buf[] = "hello";
 strcat(buf," world"); 

代码示例:

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

int main()
{
    char word[20];
    char explain[20];
    char sql[50];

    printf("please input you select word:");
    gets(word);

    printf("please input word explain:");
    gets(explain);

    strcpy(sql,word);
    strcat(sql,explain);

    printf("%s\n",sql);

    
    
    return 0;
}

七.字符串相关操作函数 2

   1.strlen字符串长度计算函数--------不算\0

   

头文件: #include <stdio.h>


int strlen(const char s[]);

功能:计算s数组中第一个'\0'前字符的个数,并返回

参数:


     @  s 目标数组,存放字符串
返回值:返回计算的字符个数

例如:

char buf[] = "hello";

int len = strlen(buf);

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

代码示例:

2.strcmp

 头文件:#include <string.h>

 int strcmp(char s1[], char s2[]);

功能:  对s1和s2字符串中的每个字符逐个⽐较

若是s1中某个字符>s2中的某个字符,则返回⼤于0的数。
若是s1中某个字符<s2中的某个字符,则返回⼩于0的数。

若是当前s1和s2的字符相等,则⽐较后⼀个字符。若是完全相等,返回0

参数:
  
 @ 待⽐较的数组s1   [字符串或字符数组]
 @ 待⽐较的数组s2   [字符串或字符数组]


返回值:
在gcc的32bit编译器下,

返回如下值:若是s1 > s2 ,返回1
          若是s1 == s2,返回0
          若是s1 < s2 ,返回-1



char buf1[] = "hello";
char buf2[] = "heltt";
ret = strcmp(buf1,buf2);

示例代码:

#include <stdio.h>
#include <string.h>  
int main()
{
       char buf1[20];
       char buf2[20];
       int ret = 0;
       printf("please input string buf1 : ");
       gets(buf1);

       printf("please input string buf2 : ");
       gets(buf2);
       
       ret = strcmp(buf1,buf2);
       printf("ret = %d\n",ret);

       if(ret > 0)
       {
               printf("buf1 > buf2");        
       }else if(ret == 0)
       {
               printf("buf1 == buf2");        
       }else if(ret < 0)
       {
               printf("buf1 < buf2");        
       }

       putchar('\n');
       return 0;
}

运行结果:

练习:

char buf[] = "I Love China";

(1) 设计⼀个 count_uppercase_character() 函数,⾃⼰定义参数和返回值,要求 统计上述数组中⼤写字符的个数。

(2) 调⽤⾃⼰设计的函数,并输出。

代码示例:

#include <stdio.h>
#include <ctype.h>

// 统计大写字母数量的函数
int count_uppercase_character(const char *str) {
    int count = 0;
    while (*str) {
        if (isupper(*str)) {
            count++;
        }
        str++;
    }
    return count;
}

int main() {
    char buf[] = "I Love China";
    
    int result = count_uppercase_character(buf);
    printf("大写字母数量:%d\n", result);  // 输出:3
    
    return 0;
}

八.指针函数

本质:是⼀个函数,只不过返回值是⼀个地址。

思考:如何定义⼀个指针函数?

返回值类型 * 函数名称 (类型 1 参数 1, 类型 2 参数 2 ,…);

例如:
int * fun (int a, int b);

(也就是说,指针函数其实和普通的函数⼀样的,只不过返回值是⼀个指针类型。
并且它必须⽤同类型的指针变量来接受)

练习:

(1) 要求⼤家是设计⼀个 design_arary() 函数 , ⾃⼰定义返回值和参数。 要求 design_array() 函数中定义⼀个 ,static char a[100] = {0};, 然后 把数组⾸地址和⻓度返回。

(2) 设计⼀个 input_array() 函数,⾃定义返回和参数,要求⽤户从键盘 输⼊任意的字符串,存放到 a 数组中

(3) 设计⼀个 output_array() 函数,要求输出 a 数组中的每个⼀字符, 以空格作为区分 . w u h a n s h a n g h a i

(4) 设计⼀个 cout_space() 函数,⾃定义返回和参数,要求⽤户统计数组 a 中⽤户 输⼊的空格个数,并返回值给 main 函数。

(5)main ()函数调⽤以上函数,并输出空格个数。

代码示例:

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

// (1) 定义静态数组并返回信息
char* design_array(int *length) {
    static char a[100] = {0};
    *length = 100;
    return a;
}

// (2) 输入字符串到数组
void input_array(char *arr) {
    printf("请输入字符串:");
    fgets(arr, 100, stdin);
    arr[strcspn(arr, "\n")] = '\0'; // 去除换行符
}

// (3) 输出字符用空格分隔
void output_array(const char *arr) {
    for(int i = 0; arr[i] != '\0'; i++) {
        printf("%c ", arr[i]);
    }
    printf("\n");
}

// (4) 统计空格数量
int cout_space(const char *arr) {
    int count = 0;
    for(int i = 0; arr[i] != '\0'; i++) {
        if(arr[i] == ' ') count++;
    }
    return count;
}

int main() {
    int len;
    char *arr = design_array(&len);
    
    input_array(arr);
    
    printf("\n字符输出:");
    output_array(arr);
    
    int spaces = cout_space(arr);
    printf("空格数量:%d\n", spaces);
    
    return 0;
}

九.函数指针

1.方法1

函数指针:本质是⼀个指针,只不过使⽤来函数的地址的。 通过函数指针来调⽤,我们需要的函数。

数据类型(*指针变量名)(类型1  参数1,类型2 参数2...);   

注:(1)函数名代表函数的⾸地址
    (2)上述中的参数1,参数2.。。等可省略




例如:
int (*funp)(int ,int) = add; 
 

add(10,20);  
funp(10,20);
#include<stdio.h>

int add(int a,int b)
{
    return a + b;
}

///  函数名就代表函数的地址
int sub(int a,int b)
{
    return a - b;
}

int main(int argc,const char*argv[])
{
    int ret = 0;
    ret = add(10,20);
    printf("a+b=%d\n",ret);

    printf("add=%p\n",add);
    printf("=============\n");

    int(*funp)(int , int) = add;
    printf("funp = %p\n",funp);

    ret = funp(10,20);
    printf("a+b=%d\n",ret);

    funp = sub;
    printf("a-b=%d\n",ret);
    
    
    
    return 0;
}

2.方法2

概念:

    回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的地址作为参数传递给另⼀个函数,在另⼀个函数中通过指针来接收 , 通过指针来调⽤其函数,我们就说这是回调函数。

  

#include <stdio.h>
 int add(int a,int b)
 {
    return a + b;
 }
 int sub(int a,int b)
 {
    return a - b;
 }
 int calc(int a,int b,int (*pfun)(int,int))
 {
      int result;
      result = pfun(a,b);
      return result;
 }
 int main()
 {
    int result = 0;
    result = calc(20,10,add)
    printf("a + b = %d\n",result);
    result = calc(20,10,sub)
    printf("a - b = %d\n",result);
    return 0;
 }

相关文章:

  • ASP.NET Core 性能优化:服务器端响应缓存
  • Lab Cloud FPGA 硬件在线实验云平台介绍
  • aviator 自定义表达式
  • 猫咪如厕检测与分类识别系统系列【二】多图上传及猫咪分类特征提取更新
  • 设计模式:工厂方法模式 - 高扩展性与低耦合的设计之道
  • 【AI】免费GPU算力平台部署wan2.1
  • 三肽-10瓜氨酸(核心蛋白聚糖肽)-抗皱抗衰 改善肤质
  • 华为的欧拉操作系统怎么进行开发、环境搭建、编译、调试等
  • 分库分表设计与Java实践:从理论到实现
  • 【KWDB 创作者计划】KWDB 数据库全维度解析手册
  • 机器学习--网格搜索
  • 第一部分——Docker篇 第四章 搭建镜像仓库
  • 路由器端口映射设置方法教程,和无公网IP内网穿透实现外网访问方案步骤
  • AIP-217 不可达资源
  • 【Redis】string类型
  • 算法---子序列[动态规划解决](最长递增子序列)
  • 在 Wireshark 中如何筛选数据包
  • 在线论坛系统
  • Charles抓包-安装和IOS抓包指导
  • HTML、CSS、JavaScript
  • node怎么做网站/百度客服人工服务电话
  • 岳阳建设公司网站/百度推广营销页
  • wordpress+取消边栏/上海快速优化排名
  • 微商城网站建设教程/软文代写接单平台
  • 提供邢台企业做网站/b2b平台有哪些网站
  • 贵阳做网站好的公司/西安百度推广客服电话多少