• 重温c语言九----函数的学习


    函数

    1.为什么需要函数?

    -1.不使用函数的话可能会导致代码冗余(过多重复的代码)

    -2.不利于代码的维护等问题。

    解决办法:

    -1未完成某一个功能的程序指令()语句的集合,称为函数。

    -2.在C语言中,函数分为:自定义函数、系统函数(查看手册)

    -3.函数还有其他的叫法,比如方法。

    2.函数的定义

    -1.基本语法

    返回类型 函数名 (形参列表){
       执行语句....//函数体
      return 返回值;//可选
    }
    
    • 1
    • 2
    • 3
    • 4

    -2.解释:

    1)形参列表:表示函数的输入

    2)函数的语句:表示为了实现某一功能代码块

    3)函数可以有返回值,也可以没有,如果没有返回值,返回类型声明为void;

    案例:

    输入两个数,再输入一个运算符(+,-*,/)得到结果

    #include 
    //说明
    /*
     * 1.函数名call
     * 2.有返回值double
     * 3.形参列表为(int n1,int n2,char oper)
     * 4.在函数中我们使用的变量名需要和形参列表上的变量名一样
     */
    double call(int n1,int n2,char oper){
        //定义一个变量保存运算的结果
        double res=0.0;
    
        switch (oper) {
            case'+' :
                res=n1+n2;
                break;
            case'-' :
                res=n1-n2;
                break;
            case'*' :
                res=n1*n2;
                break;
            case'/' :
                res=n1/n2;
                break;
            default:
                printf("你的符号有误!");
                break;
        }
    
        printf("%d %c %d=%.2f\n",n1,oper,n2,res);
        return res;
    }
    int main() {
        int num1=-10;
        int num2=20;
        double res=0.0;
        char oper='-';
        printf("使用函数解决任务!\n");
    
        res =call(num1,num2,oper);//函数返回一个值,我们用res接收该数
     printf("res返回的结果为%.2f",res);
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    传统方案不好,就使用函数进行优化程序

    3.头文件

    -1.需求:

    在实际的开发中,我们往往需要在不同的文件中,去调用其他文件的定义的函数,比如hello.c中,去使用myfuncs.c文件中的函数,如何实现引入头文件

    -2.头文件的基本概念

    1)头文件是拓展名为.h的文件,包含了C函数声明和宏定义,被多个源文件中引用共享。有两种类型的头文件:程序员编写的头文件和C标准库自带的文件

    2)在程序中要使用头文件,需要C预处理指令#include来引用他,前面已经看过stdio.h头文件他是C语言标准库里面自带的头文件

    3)#include叫做头文件包含命令,用来引入对应的头文件(.h文件)。#include也是C语言预处理命令的一种

    4)#include的处理过程很简单,就是将头文件的内容插入到该命令所在的位置,从而把头文件和当前源文件连接成一个源文件,这与复制粘贴的效果相同。但是我们不会直接在源文件中复制头文件的内容,因为这么做很容易出错。特别在程序是由多个源文件组成的时候。

    5)建议把所有的常量、宏、系统全局变量和函数原形都写在头文件中,在需要的时候随时应用这些头文件

    -3.头文件工作原理图:

    在这里插入图片描述

    -4.头文件的注意事项和细节说明

    1)引用头文件相当于复制头文件的内容

    2)源文件的名字可以不和头文件一样,但是为了便于管理,一般头文件名和源文件名一样

    3)C语言include<> 与include" "区别

    • include<>:引用的是编译器的类库路径里面的头文件,用于引用系统头文件
    • include " ":引用的是你程序目录的相对路径中的头文件,如果在程序目录没有找到引用的头文件则到编译器的类库路径的目录下找该头文件,用于引用用户头文件
    • 所以:引用系统头文件,两种形式都可以;推荐使用include< >,因为效率高;
    • 引用用户头文件,只能使用include " ".

    4)一个#include命令只能包含一个头文件,多个头文件需要多个#include命令

    5)同一个头文件如果被多次引入,多次引入的效果和一次引入的效果相同,因为头文件在代码层面有防止重复引入的机制(嵌套头文件)没有问题

    #include
    //声明函数
    int myCall(int n1,int n2,char oper);
    int myCallss(int n1,int n2,char oper);
    
    • 1
    • 2
    • 3
    • 4

    6)不管是标准头文件,还是自定义头文件,都只能包含变量和函数的声明,不能包含定义,否则在多次引入时会引起重复定义错误

    #include
    //声明函数
    int myCall(int n1,int n2,char oper);
    int myCallss(int n1,int n2,char oper);
    
    #void sayhello(){//错误写法!!!!!
    #printf("hello");
    #}
    void sayhello();//正确
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    7)自定义头文件实例代码:

    1. myfun.h(自定义头文件)

      #include
      //声明函数
      int myCall(int n1,int n2,char oper);
      
      • 1
      • 2
      • 3
    2. myfun.c(与头文件对应的源文件)

      //实现int mycall(int n1,int n2,char oper);函数
      #include 
      int myCall(int n1,int n2,char oper){
          //定义一个变量保存运算的结果
          double res=0.0;
      
          switch (oper) {
              case'+' :
                  res=n1+n2;
                  break;
              case'-' :
                  res=n1-n2;
                  break;
              case'*' :
                  res=n1*n2;
                  break;
              case'/' :
                  res=n1/n2;
                  break;
              default:
                  printf("你的符号有误!");
                  break;
      
          }
      
          printf("%d %c %d=%.2f\n",n1,oper,n2,res);
          return res;
      }
      
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
    3. hello.c(实践带有main( ))

      #include //引入系统头文件
      #include "myfun.h"//引入我们需要的头文件("用户头文件")
      void main(){
         //使用myCall完成计算任务
         int n1=10;
         int n2=50;
         char oper ='+';
         double res=0.0;
        res= myCall(n1,n2,oper);//调用从myfun.h里面提供的myCall()函数
        printf("\nres=%.2f\n",res);
      }
      
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

    4.函数的调用机制

    -1.案例演示:

    定义一个函数存入一个整数,然后进行加1操作,void类型

    #include 
    //说明
    /*
     * 1。函数名字test
     * 2.函数没有返回,void
     * 3.完成功能,传入一个参数
     */
    void test (int n){
        int n2=n+1;
        printf("n2=%d",n2);
    }
    void main(){
        int num=3;
        test(num);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    -2.return语句

    1)基本语法:

    c函数支持返回值

    返回类型 函数名(形参列表){
    语句....;
    return 返回值;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 如果没有返回值返回类型就填void

    • 如果有返回值,返回值类型要明确,要求返回值和返回类型要匹配,或者可以相互转换(自动或者强制)

      int getsum(int n1,int n2){
          return (int)(n1+n2+1.0);
      
      • 1
      • 2

    -3.函数调用的规则

    • 当调用(执行)一个函数时,就会开辟一个独立的空间(栈)
    • 每个栈空间都是相互独立的
    • 当函数执行完毕后,会返回到调用函数位置,继续执行。
    • 如果函数有返回值,则将返回值赋给接收的变量
    • 当一个函数返回1后,该函数对应的栈空间也就销毁了

    案例排查

    1.char *getSum(int num1,int num2){
        inr res=num1+num2;
        return res;
    }//错误,原因是类型不匹配
    
    • 1
    • 2
    • 3
    • 4
    2.double getSum(int num1,int num2){
        inr res=num1+num2;
        return res;
    }//OK,int->double 自动转换
    
    • 1
    • 2
    • 3
    • 4
    3.int getSum(int num1,int num2){
        inr res=num1+num2;
        return res;
    }//ok!
    
    • 1
    • 2
    • 3
    • 4
    4.double getSum(int num1,int num2){
        inr res=num1+num2;
        return 0.0;
    }//可以运行但是有警告,有精度损失double--》int
    
    • 1
    • 2
    • 3
    • 4
    5.int getSum(int num1,int num2){
        inr res=num1+num2;
        return (int)0.0;
    }
    
    • 1
    • 2
    • 3
    • 4

    -4.函数-递归调用

    基本介绍

    一个函数在函数体内又调用了自身,我们称为递归归调用

    调用函数时,开辟的函数栈,都会完整的执行函数里的代码。

    void test1(int n) {
        if (n > 2) {
            test1(n - 1);
        }
        printf("n=%d\n", n);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    程序执行图解:

    在这里插入图片描述

    先执行if里面的语句再执行if外的语句

    将上述代码加入一个else

    void test3(int n){
            if(n>2){
                test3(n-1);
            }else{
                printf("n=%d",n);//最后只输出2,因为进入if里面的语句就不会进入到else
            }
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    程序执行图解

    在这里插入图片描述

    -5.函数递归需要遵守的重要原则

    1. 执行一个函数时,就创建一个新的受保护的独立空间(新函数栈)

    2. 函数的局部变量是独立的,不会相互影响

    3. 递归必须向退出递归的条件逼近,否则就是无限递归,死龟了(栈溢出)。

    4. 当一个函数执行完毕,或者遇到return,就会返回到调用函数的位置,遵守谁调用,就将结果返回给谁

      void test3(int n){
              if(n>2){
                  test3(n-1);
                  return;//直接将栈退出,if-else后面的代码就执行不到了
              }else{
                  printf("n=%d",n);
              }
              printf("\nhello\n");
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9

      递归练习:

      #include 
      /*
       * 请使用递归的方式,求出斐波那契数1,1,2,3,5,8,13....
       * 给你一个整数n,求出他的斐波那契数是多少
       * 分析:
       * 1.如果n=1,n=2时,返回1
       * 2,从n=3开始,对应的菲薄那切数就是前面两个数的和
       */
      int feibo(int n){
       if(n==1 || n==2){
           return 1;
       }
          return feibo(n-1)+feibo(n-2);
      
      }
      void main(){
       int res=feibo(7);//输出13正确!!!
       printf("%d\n",res);
      }
      
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      /*
       * 题2:求函数值 已知f(1)=3;fn=2*f(n-1)+1;
       * 请使用递归的思想编程,求出f(n)的值。
       * 该题的公式已经给出,直接套用即可
       */
      int func2(int n){
          if(n==1){
              return 3;
          }
              return 2 * func2(n - 1) + 1;
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      /*
       * 题3:猴子吃桃子的问题有一堆桃子,猴子第一天吃了其中的一半,并且再多吃了一个!以后每天猴子都吃其中的一半
       * 然后有多吃一个
       * 当到第10天使,想再吃时(还没吃),发现只有1个桃子了。问题:最初有多少个桃子
       * 1.day=10有1个桃子
       * 2.day=9有  (day10+1)*2=4
       * 3.day=8有(day9+1)*2=10;
       */
      int monkey(int day){
          if(day==10){
              return 1;
          }else{
              return (monkey(day+1)+1)*2;
          }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

      好好体会

    5.函数的注意事项和细节讨论

    1).函数的形参列表可以有很多个

    2).C语言传递参数可以是值传递(pass by value),也可以是指针传递(a pointer passeed by value)也叫引用传递

    3).函数的命名遵循标识符命名规范,首字母不能是数字,可以采用驼峰法或者下划线法比如getNax() get_max().

    4).函数中的变量是局部的,函数外不生效

    5).基本数据类型默认是值传递的,即值进行拷贝,在函数内进行修改,不会影响到原来的值

    6)如果希望函数内的变量能修改函数外的变量,可以传入变量的地址&,函数内以指针的方式操作变量。从效果上看类似引用(即指针传递)

    /*
     * 如果希望函数内的变量能修改函数外的变量,可以传入变量的地址&
     * 函数内以指针的方式操作变量,从效果上看类似引用(即传递指针)
     */
    void f32(int *p){
        (*p)++;//*取值符,得到p指针指向的变量,会影响函数外的变量
    }
    void main(){
        f32(&n);//传入n变量的地址进去就可以修改main函数变量里的值了
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    7)C语言不支持函数重载

    //C语言不支持重载,即不能通过参数的个数不同,或者类型不同的;来区别函数
    void f2(int){
    ...
    }
    void f2(int n,int n2){//##error
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    8)C语言支持可变参数

    #include 
    #include 
    //num表示传递的参数格式
    //...表示可以传递多个参数和num
    int fun(int num, ...){//可变函数:参数的个数可以不确定使用...
        int i,totalSum=0;//totalSum一定要初始化
        int val=0;
        va_list v1;//v1实际上是一个字符指针,从头文件可以找到
        va_start(v1,num);//使v1指向可变列表中的第一个值,即num后的第一个参数
        printf("v=%d\n",*v1);
        for(i=0;i<num;i++){//num减一是为了防止下标超限
            val=va_arg(v1,int);//该函数返回v1的值,并使v1向下移动一个int的距离
            //使其指向下一个null
            printf("res=%d",val);
            totalSum +=val;
        }
        va_end(v1);//关闭v1指针,使其指向null
        return totalSum;
    
    }
    void main(){
        fun(3,10,30,60);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    指针传值交换题:

    #include 
    //编写一个函数swap(int *n1,int *n2)可以交换n1和n2的值
    void swap(int *n1,int *n2){
        int tmp =*n1;//表示n1指针指向的变量赋给tmp
        *n1=*n2;//表示将n2这个指针指向的变量的值赋给这个指针指向的变量的值
        *n2=tmp;//表示将tmp赋给n2指针变量所指向的值
    
    }
    void main(){
       int n1=1;
       int n2=2;
       swap(&n1,&n2);//相互交换了值
       printf("n1=%d,n2=%d",n1,n2);
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    6.函数参数传递的方式

    1)基本介绍

    函数参数传递的方式有两种,一种使值传递,一种是传递指针也叫传递地址或者是引用传递

    2)两种传递方式

    -1.值传递

    -2.引用传递(传递指针,地址)

    事实上,不管是值传递还是引用传递,传递给函数的都是变量的副本,不同的是,值传递的是值的拷贝,引用传递的是地址的拷贝,一般来说地址的拷贝效率高。因为数据量小,而值拷贝决定拷贝的数据大小,数据越大,效率越低。

    3)值传递和引用传递的使用特点

    -1值传递:变量直接存储值,内存通常分配在栈中

    -2.默认是值传递的数据类型有1.基本数据类型,2.结构体3,共用体,4.枚举类型

    -3引用传递:变量存储的是一个地址,这个地址对应的空间才真正存储数据(值)

    -4默认是引用传递的数据类型有:指针和数组

    -5.如果希望函数内的变量能修改函数外的变量,可以传入变量的地址&函数内以指针的方式操作变量(*指针)。从效果来看类似引用,比如修改结构体的特性

    在这里插入图片描述

    7.变量作用域

    1)基本说明

    所谓变量作用域(scope),就是指变量的有效范围

    -1.函数内部声明/定义的局部变量,作用域仅限于函数内部

    -2.函数的参数,形式参数,被当作该函数内的局部变量。如果与全局变量同名他们会优先使用 局部变量(编译器使用就近原则

    -3在一个代码块,比如for/if中的局部变量,那么这个变量的作用域就在该代码块

    -4在所有的函数外部定义的变量叫全局变量,作用域在整个程序都有效

    #include 
    int n=20;//函数外部定义的为全局变量,
    void sayHello(){
        char name[]="tom";
        printf("hello %s\n",name);
    }
    //函数的形参会被视为f10的局部变量;
    //说明:当局部变量和全局变量同名时,以局部变量为准(就近原则)
    void f10(int n){//n为形参变量
        printf("n=%d",n);
    }
    void main(){
        printf("n=%d\n",n);//调用全局变量
    
        sayHello();
        //printf("name=%s",name);//这里我们不能使用到sayHello的name变量
        f10(10);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2)初始化局部变量和全局变量

    -1局部变量,系统不会对其默认初始化,必须对局部变量初始化之后才能使用,否则程序运行后可能会异常退出。

    -2.全局变量,系统会自动对其初始化。如下图所示

    数据类型初始化默认值
    int0
    char‘\0’
    float0.0
    double0.0
    pointerNULL

    -3.正确地初始化变量是一个良好的编程习惯,否则有时候程序可能会产生意想不到的结果,因为未初始化的变量会导致一些在内存位置中已经可用的垃圾直

    #include 
    int a;
    float t;
    double d1;
    main(){
        //局部变量,系统不会对其默认初始化
        //必须对局部变量初始化之后才能使用,否则,程序运行后可能会导致异常退出
      //  int i;
        printf("\na=%d t=%.2f d1=%.2f",a,t,d1);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3)作用域的注意事项和细节

    -1.全局变量(global Variable)保存在内存的全局存储区,占用静态的存储单元,它的作用域默认是整个程序,也就是所有的代码文件,包括源文件(.c文件)和头文件(.h文件)

    -2.局部变量(local Variable)保存在栈中,函数被调用时才动态地分配存储单元,他的作用域仅限于函数的内部

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z8CtW7aD-1659835844638)(D:\myfile\常见科目\C语言\picture\C程序内存图.jpg)]

    -3.C语言规定,只能从小的作用域向大的作用域中去寻找变量,而不能反过来,使用更小的作用域中的变量

    -4在同一个作用域,变量名不能重复,在不同的作用域中,变量名可以重复,使用时也由编译器采用就近原则。

    -5.由{ }包围的代码块也拥有独立的作用域

    看完103集。

    8.static关键字

    1)基本介绍

    static关键字在C语言中比较常用,使用恰当能够大大提高程序的模块化程序,有利于程序维护。

    2)局部变量使用static修饰

    -1局部变量被static修饰后,我们称为静态局部变量

    -2.对应静态局部变量在声明时未赋值,编译器也会把它初始化为0

    #include 
    void main(){
         static int n;//n就是静态局部变量
         printf("%d",n);//结果为0,静态局部变量被修饰为0
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    -3.静态局部变量存储于进程的静态存储区(全局性质,)只会被初始一次,即使函数返回,他的值也会保持不变

    案例:

    #include 
    
    
    void fn(void){//普通函数
        int n=0;//普通变量
        printf("n=%d\n",n);
        n++;
        printf("n++=%d\n",n);
    }
    void fn_static(void){
        static int n=10;//静态局部变量,放在静态存储区,全局性质空间
        printf("static n=%d\n",n);
        n++;
        printf("n++=%d\n",n);
    }
    void main8(){
    
        fn();//0 1
        fn();//0 1
    
        printf("===============\n");
    
        fn_static();//10 11
        fn_static();//11 12
    
    
        /*
         static int n;//n就是静态局部变量
         printf("%d",n);//结果为0,静态局部变量被修饰为0
         */
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    3)全局变量使用static修饰

    -1普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为他们是同一个变量),静态全局变量仅对当前文件可见,其他文件不可访问,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响

    1.创建一个file02.c的文件
    int num=10;//普通全局变量
    int num2=20;//静态全局变量,只能再本文件中使用,不能再其他文件中使用
    2.创建一个file01.c的文件
    #include 
    //在一个文件中使用另外一个全局变量,使用extern 引入即可
    extern int num;
    extrn int num2;
    void main(){
    printf("\nnum=%d",num);//输出为:10
    printf("\nnum2=%d",num2);//错误
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    -2.定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低1程序模块之间地耦合,避免不同文件同名变量的冲突,且不会误使用。

    4)函数使用static修饰

    -1.函数的使用方式与全局变量类似,在函数的返回类型前加上static,就是静态函数

    #include 
    void fun1(){//普通函数(非静态函数)
        printf("helo from fun.1\n");
    }
    static void fun2(){//静态函数,只能在本文件中使用
        printf("helo from fun2.\n");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    -2.非静态函数可以在另一个文件中通过extern引用

    #include 
    extern void fun1();
    extern void fun2();
    
    • 1
    • 2
    • 3

    -3.静态函数只能在声明它的文件中可见,其他文件中不能引用该函数

    #include 
    extern void fun1();
    extern void fun2();
    
    void main(){
        fun1();//成功执行
       // fun2();//报错
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    -4不同的文件可以使用相同名字的静态函数,互不影响

    #include 
    extern void fun1();
    extern void fun2();
    void fun2(){//定义一个和静态函数同名的函数
        printf("this is another function with the same name of fun2 in another world");
    }
    void main(){
        fun1();
      fun2();//顺利通过
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    9.字符串常用的系统函数

    1)说明:

    字符串(即 字符数组)在我们程序开发中,使用的是非常多的,常用的函数需要我们掌握头文件

    2)举例说明

    -1.得到字符串的长度

    size_tstrlen(char *str)
    //计算字符串的长度,直到空结束字符,但不包括空结束字符
    
    • 1
    • 2

    -2拷贝字符串

    char *strcpy(char *dest,const char *src)
    //把src指向的字符串复制到dest
    
    • 1
    • 2

    -3连接字符串

    char *strcat(char *dest,const char *src)
    //把src所指向的字符串追加到dest所指向的字符串的结尾
    
    • 1
    • 2

    综合:

    #include 
    #include 
    void main(){
        char src[50]="abc",dest[50]=" ";//定义两个字符数组(字符串)
        char *str ="abcdff";
        printf("str.len=%d\n",strlen(str));//统计字符串的大小
        //表示将hello拷贝到src中
        //注意,拷贝字符串会将原来的内容覆盖掉
        strcpy(src,"hello");
    
        printf("\s src=%s\n",src);
    
        strcpy(dest,"C语言");
    //strcat是将src字符串的内容连接到dest,但是不会覆盖dest原来的内容,而是来连接
        strcat(dest,src);
    
        printf("最终目标字符串:dest=%s",dest);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    10.时间和日期相关函数

    1)说明:在编程中,程序员会经常使用到日期相关的函数,比如统计某段代码执行花费的时间等等。头文件是

    2)举例说明

    -1获取时间

    char *ctime(const time_t *timer)
    //返回一个表示当地时间的字符串,当地时间是基于参数timer
        
        #include 
    #include //此头文件包含了与日期时间相关的函数
    void main(){
        time_t curtime;//time_h是一个结构体类型
        time(&curtime);//time()可以获取到当前时间完成初始化任务
        //ctime返回一个表示当地时间的字符串,当地时间是基于参数timer
        printf("当前时间=%s",ctime(&curtime));
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    -2.编写一段代码来统计函数test执行的时间

    double difftime(time_t ,time1,time_ttime2)
    //返回time1和time2之间相差的秒数(time1-time2)
    
    • 1
    • 2

    -3综合案例

    #include 
    #include //此头文件包含了与日期时间相关的函数
    
    void testsss(){//运行test函数,看看执行花费时间
        int i=0;
        int sum=0;
        int j=0;
        for(i=0;i<77778799;i++){
            sum=0;
            for(j=0;j<10;j++){
                sum+=j;
               // printf("%d\n",j);
            }
        }
    }
    void main(){
        /*
        time_t curtime;//time_h是一个结构体类型
        time(&curtime);//time()可以获取到当前时间完成初始化任务
        //ctime返回一个表示当地时间的字符串,当地时间是基于参数timer
        printf("当前时间=%s",ctime(&curtime));*/
    
    /*
     * //自己写的
        //先得到执行testsss前的时间
        time_t curtime;
        time(&curtime);
        testsss();
        //再得到执行testsss后的时间
        //然后得到两个时间差耗用的时间差
        time_t aftime;
        time(&aftime);
       double s= difftime(  aftime,curtime);
       printf("%fl\n",s);
    
    */
    time_t start_t,end_t;
    double diff_t;//存放时间差
    printf("running------\n");
    
    time(&start_t);//初始化得到当前的时间差
    
    testsss();//执行测试函数
    
    time(&end_t);//得到当前时间
    
    diff_t=difftime(end_t,start_t);//得到时间差
    
    printf("执行了函数耗时:%.2f\n秒",diff_t);//将时间差输出
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    10.数学相关的函数

    1)介绍

    math.h头文件定义了各种数学函数和一个宏。在这个库中所有可用的功能都带有一个double类型的参数,且都返回了double类型的参数

    2)举例说明

    1.double exp(double x)
    //返回e的x次幂的值
    2.double log(double x)
    //返回x的自然对数(基数为e的对数)
    3.double pow(double x,double y);
    //返回x的y次幂
    4.double sqrt(double x)
    //返回x的平方根
    5.double fabs(double x)
    //返回x的绝对值。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    #include 
    #include 
    void main(){
        double d1=pow(2.0,3.0);//求2的3次幂
        printf("幂%.2f\n",d1);
        double d2=sqrt(25.0);//求平方根
        printf("%.2f\n",d2);
        double d3=fabs(-3);//求绝对值
        printf("该书的绝对值为:%.2f",d3);
    
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    11.基本数据类型和字符串类型的转换

    1)介绍

    在程序开发中,我们经常需要将基本数据类型转成字符串类型(即char数组)或者将字符串类型转成基本数据类型。

    2)sprintf函数的用法

    -1.sprintf和平时我们常用的printf函数的功能很相似。sprintf函数打印到字符串当中,而printf函数打印到输出到屏幕当中。sprintf函数在我们完成其他数据类型转换成字符串类型的操作中应用广泛

    -2.该函数包含在当中。

    案例演示:

    小案例1:

    #include 
    void main(){
        char str1[20];//字符数组,也可以叫字符串。使用字符数组表示
        char str2[20];
        char str3[20];
        int a=20984,b=48090;
        double d=14.309948;
        //说明:
        //1.sprintf是一个系统函数,可以将结果存放在字符串中
        //2.格式化的结果,会存放到str1中
        sprintf(str1,"%d%d",a,b);//将a和b转成字符串存放在str1
        sprintf(str2,"%.2f",d);
        sprintf(str3,"%8.2f",d);//小数点占用两位,前面不够用空格来补
        printf("str1=%s str2=%s str3=%s",str1,str2,str3);
        
        //结果:str1=2098448090 str2=14.31 str3=   14.31
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    小案例2:

    #include 
    #include 
    void main(){
       //字符数组
       char str[10]="123456";
       char str2[10]="12.67423";
       char str3[2]="ab";
       char str4[4]="111";
    
       //说明:
       //1.atoi(str)将str转换成整数
    //将上述字符数组转换为各类型的数
       int num1=atoi(str);
       short s1=atoi(str4);
       //说明
       //1.atof(str2),将str2转成一个小数(double类型的)
       double d=atof(str2);
       //提取出str3的第一个参数
       char c=str3[0];
       printf("num1=%d d=%f c=%c s1=%d",num1,d,c,s1);
       //结果:num1=123456 d=12.000000 c=a s1=111
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    -3.注意事项

    • 再将char数组类型转成基本数据类型时,要确保能够转换成有效的数据。比如我们可以把“123”转换成一个整数,但是不能把“hello”转成一个整数
      char str2[20];
      char str3[20];
      int a=20984,b=48090;
      double d=14.309948;
      //说明:
      //1.sprintf是一个系统函数,可以将结果存放在字符串中
      //2.格式化的结果,会存放到str1中
      sprintf(str1,“%d%d”,a,b);//将a和b转成字符串存放在str1
      sprintf(str2,“%.2f”,d);
      sprintf(str3,“%8.2f”,d);//小数点占用两位,前面不够用空格来补
      printf(“str1=%s str2=%s str3=%s”,str1,str2,str3);

      //结果:str1=2098448090 str2=14.31 str3= 14.31
      }

    
    小案例2:
    
    ```C
    #include 
    #include 
    void main(){
       //字符数组
       char str[10]="123456";
       char str2[10]="12.67423";
       char str3[2]="ab";
       char str4[4]="111";
    
       //说明:
       //1.atoi(str)将str转换成整数
    //将上述字符数组转换为各类型的数
       int num1=atoi(str);
       short s1=atoi(str4);
       //说明
       //1.atof(str2),将str2转成一个小数(double类型的)
       double d=atof(str2);
       //提取出str3的第一个参数
       char c=str3[0];
       printf("num1=%d d=%f c=%c s1=%d",num1,d,c,s1);
       //结果:num1=123456 d=12.000000 c=a s1=111
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    -3.注意事项

    • 再将char数组类型转成基本数据类型时,要确保能够转换成有效的数据。比如我们可以把“123”转换成一个整数,但是不能把“hello”转成一个整数
    • 如果格式不正确,会默认转成0.
  • 相关阅读:
    打击勒索病毒:防御.kat6.l6st6r勒索病毒的最佳策略
    基于Durid解析SQL语法树获取单查询该查询的最终输出字段
    d域参数通过闭包逃逸
    pytorch基础语法问题
    postgreSQL中的高速缓存
    Java版CRM客户管理系统源码 CRM小程序源码
    easyExcel快速入门
    Halon 模板匹配流程
    Oracle中i列定义int类型对应Java中java.math.BigDecimal类型
    CTyunOS安装MySQL8.0
  • 原文地址:https://blog.csdn.net/weixin_55418082/article/details/126206467