C语言学习笔记---函数

C语言学习笔记

函数


子函数在主函数之后,须在主函数开头部分声明子函数。

定义

无参函数
类型标识符 函数名() {
    函数体
}
类型标识符 函数名(void) {
    函数体
}
- void表示空类型,无函数值(返回值)
- 函数体包括'声明部分''语句部分'
有参函数
类型标识符 函数名(形式参数表列) {
    函数体
}

类型标识符 函数名(类型标识符 形式参数, 类型标识符 形式参数, .....) {
    函数体
}
例如:
int max(int x,int y) {
    int z;                      // 声明部分
    z = x>y ? x : y;            // 执行部分
    return z;
}
空函数
类型标识符 函数名() {

}

C语言中,若未说明函数的类型,则系统默认该函数的类型是int型。

调用

格式
格式: 函数名(实参表列)
- 函数调用语句,针对无返回值的函数
    printf("hello");
- 函数表达式,针对有返回值的函数
    c = 2 * max(1,2);
- 函数参数,作为另一个函数的实参
    m = max(1,max(2,3));
    printf("max:%d",max(5,11)); 
形参与实参

在有参函数中,定义函数时函数名后面括号里的是形参,在主函数中调用时,被调用函数名后面括号里的是实参。实参可以是常量,变量,表达式。实参要求必须是确定的值。

数组作为函数参数

数组元素作为函数实参,其用法与变量相同,向形参传递数组元素的

数组名也可以作为实参和形参,传递的是数组第一个元素的地址

数组元素作为函数实参

可做实参,不可做形参,因为形参是在函数被调用处临时分配存储单元的,不可能为一个数组元素单独分配存储空间。是 ”值传递“ 方式,数据传输方向是从实参传递到形参,单向传递。

一维数组名作为函数参数

用数组元素作为实参时,向形参彻底的是数组元素的值。数组名作为函数实参时,向形参(数组名或指针变量)传递的是数组首元素的地址。

当用数组名作为函数的参数时,如果形参数组中的元素值发生改变时 实参元素的值也发生改变。

  • 用数组名作为函数的参数时,应在主调用函数和被调用函数分别定义数组

  • 实参数组与形参数组应类型一致

  • 在定义函数时,指定数组大小时不起任何作用,因为C语言编译器不检查形参数组大小,只是将实参数组的首元素的地址传递给形参数组名

  • 形参数组可以不知道大小

    void foo(int a[]){......}
    

编译系统会把形参数组处理为指针变量,例如把float a[]转化为float *a,二者是等价的

多维数组名作为函数参数

可省略第一维大小

void foo(int a[][10]){......}
嵌套调用

C语言的函数定义是互相平行的、独立。在定义函数时,一个函数内不能在定义另一个函数,即不能嵌套定义

可以嵌套调用函数

递归调用

直接或间接地调用该函数本身,称为函数的递归调用。

int foo(int x) {
    int y,z;
    z=foo(y);
    return 2*z;
}

声明

来源

函数的来源有两种:1. 用户自定义的函数,2. 库函数。

  • 被调用的函数必须是已定义的函数。

  • 使用库函数,需要在本文件开头用#include指令将所需要的信息添加到本文件中。

    #include <math.h>
    .h是头文件所用的后缀,表示头文件
    
  • 如果用户自定义的函数在主函数后面定义,需要在主函数开头声明该函数。以便编译器能够正确识别到。因为编译器是自上向下进行的。

  • 如果已在文件的开头(在所有函数之前),对本文件中所调用的函数进行声明,则在个函数中不必对其所调用的函数再做声明。

    int max(int,int);
    int add(int,int);
    int main() {......}        // 在main函数中就无需对max和add函数进行声明
    int max(int x,int y){......}
    int add(int x,int y){......}
    

格式

一般形式:
    - 函数类型 函数名(参数类型1 参数名1, 参数类型2 参数名2, ...)
    - 函数类型 函数名(参数类型1, 参数类型2, ...)
例如:
float add(float,float);
float add(float x,float y);

返回值

  • 函数的返回值通过函数中的return语句获得

  • 在定义函数时必须指定函数的类型

  • 在定义函数指定的函数类型一般应该和return语句中的表达式一致,即函数类型觉得返回值类型

  • 对于不带回值的函数,应当定义函数为 “void类型”

变量的作用域

在函数开头定义的变量,只在该函数中使用。引申到变量的作用域问题,每个变量都有一个作用域。

在函数内定义的变量是局部变量;在函数外定义的变量是全局变量。

定义变量的三种情况:

  • 在函数开头的位置定义

  • 在函数内的复合语句内定义

  • 在函数外部定义

局部变量
  • 主函数定义的变量只在主函数中有效

  • 不同函数可以使用相同名的变量,他们代表不同的对象,互不干扰

  • 形式参数也是局部变量

  • 复合语句中定义的变量只在复合语句中有效

全局变量

为了便于区分全局变量和局部变量,有一个习惯将全局变量第一个字母大写

建议不在必要时不要使用全局变量,理由如下:

  • 全局变量在程序的全部执行中占用内存

  • 使函数的通用性降低

  • 使用全局变量过多,会降低程序的清晰性

举例
// 变量的作用域
#include<stdio.h>

int G = 123;

int add(int x, int y) {
    printf("add中打印g:%d\n", G);
    return x + y;
}
char M = 'M';            // 编译器自上向下执行语句,虽然M和G都是全局作用域,但m的作用域比g小,不包含add函数


int main() {
    int a = 0;
    int sum=0;
    for (int i = 0; i < 10 ;i++) {
        int c=10;
        sum = sum + add(a, i);
    }
    G = 321;
    //G = G + i + c;            // 未定义标识符 "i" 和 "c"
    //printf("G:%d; a:%d; sum:%d; c:%d; i:%d\n",G,a,sum,c,i);    // c和i无效
    printf("g:%d; a:%d; sum:%d;\n", G, a, sum);
}

若全局变量与局部变量同盟,分析结果

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告

#include<stdio.h>

int a = 3, b = 5;

int main() {
    int max(int a, int b);
    int a = 8;
    printf("main里的a:%d; b:%d\n", a, b);    // a:8(局部变量) b:5(全局变量)
    printf("max=%d\n", max(a, b));
    return 0;
}

int max(int a, int b) {
    int c;
    printf("max里的a:%d; b:%d\n", a, b);        // a,b为局部变量
    c = a > b ? a : b;
    return c;
}

// max=8

变量的存储方式和生存期

存储方法

变量的存储方式有两种:

  1. 静态存储方式

  2. 动态存储方式

静态存储方式:指程序运行期间由系统分配固定的存储空间的方式。

动态存储方式:指在程序运行期间根据需要进行的动态分配存储空间的方式。

常量的存储方式取决于常量的类型和存储类别。一般来说,C语言中的常量存储方式有以下特点:

  1. 字面常量(Literal Constants):字符串常量和数值常量(包括整型、浮点型和字符型)通常存储在程序的静态存储区(Static Memory),也被称为常量存储区(Constant Pool)。这个区域在程序运行期间始终存在,不会随函数调用结束而消失。字符串常量尤为特殊,它们在内存中以只读形式存储,不可修改。

  2. const修饰的变量(Const Variables):当使用const关键字定义一个常量变量时,虽然它在概念上被视为常量,但在内存中仍可能分配存储空间,且存储在静态存储区。一旦初始化,其值就不能再改变。

  3. 编译时常量(Compile-Time Constants):对于整型和指针类型的编译时常量(如用#define预处理器定义的宏或者枚举常量),它们在编译阶段就被替换成了具体的值,不会在运行时占用内存空间。

简而言之,在C语言中,大多数常量在内存中的存储是静态的,并且在程序的整个生命周期内保持不变。字符串常量具有额外的只读属性,防止它们在运行时被修改。而用const修饰的变量虽然名义上是常量,但在内存中仍有其专属的存储空间。

内存中供用户使用的存储空间,可分为三部分:

  1. 程序区

  2. 静态存储区

  3. 动态存储器

数据分别存放在静态存储区和动态存储区中,全局变量全部存放在静态存储区中,在整个程序执行期间一直存在,程序开始时分配存储空间,程序结束时释放。

一般静态存储区存放全局变量,常量等。

在动态存储区中存放下列数据:

  1. 函数形式参数。在调用函数时给形参分配存储空间。

  2. 函数中定义没有用关键字static声明的变量,即自动变量。

  3. 函数调用时的现场包含和返回地址等。

存储类别

每一个变量和函数有两个属性:数据类型数据的存储类别

C语言的存储类别包括4种:autostaticregisterextern;前三种用于局部变量,extern用于全局变量

局部变量的存储类别

  1. auto—自动局部变量
    使用关键字auto作为自动变量的存储列表声明。
    函数中的局部变量,如果没有专门用static(静态)声明存储类别,都是动态分配存储空间的。
    关键字auto可省略,不写auto则隐含指定为 ”自动存储类别“

    int foo(int a){
        auto int b=2;
        return a+b;
    }
    
  2. static—静态局部变量
    使用关键字static声明。
    函数调用结束后不会消失,而继续保留原值,即其占用的存储空间不释放,在下一次调用该函数时,该变量的值是上一次函数调用结束的值。
    非必要情况下不要使用静态局部变量,会多占用内存空间。
    建议定义静态局部变量时,同时初始化值,以免每次调用时重新赋值。

    // 考虑静态变量的
    #include<stdio.h>
    
    int main() {
        int foo(int);
        int a = 2, i;
        for ( i = 0; i < 3; i++) {
            printf("%d\n", foo(a));
        }
        return 0;
    }
    
    int foo(int a) {
        auto int b = 0;                // auto可省略,默认局部变量为自动变量
        static int c = 3;            // static 静态局部变量,每次调用时替换成上一次调用结束后的值
        printf("foo c:%d\n", c);
        b = b + 1;
        c = c + 1;
        return a + b + c;
    }
    
    # input
    foo c:3
    7
    foo c:4
    8
    foo c:5
    9
    
    

对于静态局部变量来说,编译时会自动赋初值0(对数值类型)或空字符 ‘\0’ ,而对于自动局部变量来说,他的值是不确定的。

  1. register—寄存器变量
    局部变量存放在寄存器中,需要时直接从寄存器中取出参加运算,不必到内存中存取。常用于使用频繁的变量。
    编译器能够识别到频繁的编码,从而自动优化它们,放在寄存器上

    register int f=0;
    

全局变量的存储类别

全局变量存放在静态存储区中,它们的生存周期固定,存在于程序的整个运行过程。

一般来说,外部变量是在函数的外部定义的全局变量,它的作用域是从变量的定义处开始到本程序文件的结束

  • 在一个文件中内扩展外部变量的作用域

    在全局变量之前的函数需要引用该外部变量时,则应该在该变量引用处前添加extern关键字对该变量作 外部声明

    调用函数,求3个整数中的较大者

    #define _CRT_SECURE_NO_WARNINGS 1
    #pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
    #pragma warning(disable:6031) // 禁止显示未经检查的返回值警告
    
    #include<stdio.h>
    
    int main() {
        int max();
        extern int A, B, C;                    // 把外部变量扩展到从此处开始; 扩展尝试去掉extern关键字,看结果是否一样
        printf("please enter three interger numbers:");
        scanf("%d %d %d", &A, &B, &C);
        printf("max is %d\n", max());
        return 0;
    }
    
    int A, B, C;                            // 定义外部变量,编译系统会自动将外部(全局)变量赋初值0
    
    int max() {
        int m;
        printf("A:%d B:%d C:%d\n",A,B,C);
        m = A > B ? A : B;
        if (C > m) {
            m = C;
        }
        return m;
    }
    
    输入1 2 3
    - 添加extern 关键字时 max=3
    - 未添加extern关键字时 max=0,因为编译系统会自动将外部(全局)变量赋初值0,而且main函数中的A,B,C是局部变量
    
  • 将外部变量的作用域扩展到其他文件

    两个程序文件需要同一个外部变量时,在任意一个文件里定义外部变量,另一个文件里用extern关键字声明该变量。

    给定b的值,输入a和m,求a*b和 a m a^m am的值

    :文件file1.c
    #include<stdio.h>
    
    int A;
    
    int main() {
        int power(int);
        int b = 3, c, d, m;
        printf("enter the numbers a and its power m:\n");
        scanf("%d %d", &A, &m);
        c = A * b;
        printf("%d * %d=%d\n", A, b, c);
        d = power(m);
        printf("%d * * %d=%d\n", A, m, d);
        return 0;
    }
    
    :文件file2.c
    extern A;
    
    int power(int n) {
        int i, y = 1;
        for ( i = 1; i <= n; i++) {
            y *= A;
        }
        return y;
    }
    

    不需要在file1.c中用#include导入file2.c文件,因为编译系统给会自动从别处寻找已定义的外部变量。在个文件经过编译后,将个目标文件连接成一个可执行文件

  • 将外部变量的作用域限制在本文件中
    在定义外部变量时添加static关键字声明。

    file1.c
    static int A;            // 静态外部变量
    int main() {......}
    
    file2.c
    extern A;            // 不能使用file1.c中全局变量A, 对于其他文件来说,file1.c中的这个静态外部变量是看不见的,不能用的
    void foo() {......}
    

用static声明一个变量的作用:

  1. 对局部变量用static声明时,把该变量分配到静态存储区,在整个程序执行期间不释放,其所分配的空间始终存在。

  2. 对全局变量用static声明时,则该变量只限于本文件模块(即被声明的文件中)

用auto、static、register声明变量时,是在定义变量的基础上加上这些关键字的,而不能单独使用,extern是单独使用的

static int a=1;
extern a;

下面做法是错误的
int a;            // 先定义整型变量
static a;         // 企图再将变量a声明为静态变量,编译时会被认为重新定义

变量的声明与定义

在函数中出现的对变量的声明(除了用extern声明意外)都是定义,在函数中对其他函数的声明不是函数的定义

内部函数和外部函数

函数本质上是全局的,可以被本文件或其他文件所调用

内部函数

一个函数只能被本文件中的其他函数所调,又称静态函数,通常把本文件所使用的函数和外部变量放在文件的开头,前面都加上关键词static使之局部化,其他文件不能引用,提供程序的可靠性。

static 类型名 函数名(形参表列) {......}

外部函数

定义函数时,在函数首部的最左端加关键词extern,则该函数是外部函数,可供其他文件调用,C语言规定,在定义函数省略extern,则默认为外部函数。

在需要调用此函数的其他文件中,需要对此函数作声明,要加关键字extern,表示该函数是在其他文件中定义的外部函数

extern 类型名 函数名(形参表列) {......}


其他文件调用该函数时,要用extern声明该函数
extern 类型名 函数名(形参表列);

举例

输出下列效果

***************
How do you do!
***************
#include <stdio.h>

void print_message() {
    printf("How do you do!\n");
}

int main() {
    void print_star();        // 位于主函数之后的函数需要在主函数中声明
    print_star();
    print_message();        
    print_star();
    return 0;

}

void print_star() {
    printf("***************\n");
}

输入两个整数,要求输出其中较大者

#define _CRT_SECURE_NO_WARNINGS 1
#pragma waring(disable:6031)

#include <stdio.h>


int max(int x, int y) {
    int z;                            // 零时变量
    z = x > y ? x : y;
    return z;
}

int main() {
    int max(int x, int y);            // 对max函数的声明,这里可以不用声明
    int a, b, c;
    printf("please enter two integer numbers:");
    scanf("%d,%d", &a, &b);
    c = max(a, b);
    printf("max is %d\n", c);
    return 0;

}

输入两个实数,用一个函数求出它们的和

#define _CRT_SECURE_NO_WARNINGS 1
#pragma waring(disable:6031)
#include <stdio.h>

int main() {
    float add(float x, float y);
    float a, b, c;
    printf("please enter a and b: ");
    scanf("%f,%f", &a, &b);
    c = add(a, b);
    printf("sum is %f", c);
    return 0;
}

float add(float x, float y) {
    float z;
    z = x + y;
    return z;
}

输入4个整数,找出其中最大的数,用函数的嵌套调用来处理

#define _CRT_SECURE_NO_WARNINGS 1
#pragma waring(disable:6031)
#include <stdio.h>

int max4(int a, int b, int c, int d);        // 对max4函数进行声明

int main() {
    int a, b, c, d, max;
    printf("please enter 4 interger numbers: ");
    scanf("%d,%d,%d,%d", &a, &b, &c, &d);
    max = max4(a, b, c, d);
    printf("max=%d\n", max);
    return 0;
}

int max4(int a, int b, int c, int d) {    // 定义max4函数
    int max2(int a, int b);                // 对max2函数进行声明
    int m;
    m = max2(a, b);
    m = max2(m, c);
    m = max2(m, d);
    return m;
    //return max2(max2(max2(a, b), c), d);
}

int max2(int a, int b) {
    if (a >= b) {
        return a;
    }
    else {
        return b;
    }
    // return (a >= b) ? a : b;
}


有5个学生坐在一起,问第5个学生多少岁,他说比第4个学生大2岁。问第4个学生岁数,他说比第3个学生大2岁。问第3个学生,又说比第2个学生大2岁。问第2个学生,说比第1个学生大2岁。最后问第1个学生,他说是10岁。请问第5个学生多大。

a g e ( n ) = 10 , ( n = 1 ) age(n)=10,(n=1) age(n)=10,(n=1)

a g e ( n ) = a g e ( n − 1 ) , + 2 ( n > 1 ) age(n)=age(n-1),+2(n>1) age(n)=age(n1),+2(n>1)

#include <stdio.h>

int age(int n) {
    int c;
    if (n == 1) {
        c = 10;
    }
    else {
        c = age(n - 1) + 2;
    }
    return c;
}


int main() {
    printf("NO.5,age:%d\n", age(5));
    return 0;
}

用递归方法求 n ! n! n!

#define _CRT_SECURE_NO_WARNINGS 1
#pragma waring(disable:6031)
#include<stdio.h>

int main() {
    int fac(int n);                                // fac函数的声明
    int n, y;
    printf("input an interger number: ");
    scanf("%d", &n);
    y = fac(n);                                    // fac函数的调用
    printf("%d!=%d\n", n, y);
    return 0;
}

int fac(int n) {                                // fac函数的定义
    int f=-1;
    if (n < 0) {
        printf("n<0,data error!");
    }
    else if (n == 0 || n == 1) {
        f = 1;
    }
    else {
        f = fac(n - 1) * n;
    }
    return f;
}

如果输入13,求13! 会得不到预期的结果,因为超出int最大表示范围。使用float或double类型

汉诺塔问题

问题描述: 有三根柱子A、B、C,A柱上从下到上堆叠着若干个大小不等的盘子,盘子的直径从下往上逐渐减小(不允许大盘子压在小盘子之上)。任务是将所有盘子从柱子A经过柱子B,最终全部移到柱子C上,并且遵守任何时候大盘子都不能在小盘子之上这一规则。

解决方法: 解决汉诺塔问题的基本思路是采用递归策略,步骤如下:

  1. 将A柱上除了最下面的一个盘子之外的所有盘子借助C柱移动到B柱上。
  2. 将A柱底部的盘子直接移动到C柱上。
  3. 将B柱上的所有盘子借助A柱移动到C柱上,此时所有盘子都在C柱上按照原来的顺序排列。

用递归算法表示,假设n表示盘子的数量,函数hanoi(n, A, B, C)表示将n个盘子从A柱移动到C柱,借助B柱。函数主体可以写作:

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告

#include<stdio.h>

int main() {
    void hanoi(int n, char one, char two, char three);
    int m;
    printf("input the number of diskes: ");
    scanf("%d",&m);
    printf("The step to move %d diskes:\n", m);
    hanoi(m, 'A', 'B', 'C');
    return 0;
}

void hanoi(int n, char one, char two, char three) {
    // 将 n个盘从one座借助two座,移动three座
    void move(char x, char y);
    if (n == 1) {
        move(one, three);
    }
    else {
        hanoi(n - 1, one, three, two);
        move(one, three);
        hanoi(n - 1, two, one, three);
    }
}

void move(char x, char y) {
    printf("%c->%c\n",x,y);
}

输入10个数,要求输出其中值最大的元素和该数是第几个数

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告

#include<stdio.h>

int main() {
    int max(int x, int y);
    int a[10], m, n, i;
    printf("enter 10 interger numbers: ");
    for (i = 0; i < 10; i++) {
        scanf("%d", &a[i]);
    }
    printf("\n");
    for (i = 1, m = a[0], n = 0; i < 10; i++) {
        if (max(m, a[i]) > m) {
            m = max(m, a[i]);
            n = i;
        }
    }
    printf("the largest number is %d\nit is the %dth number.\n", m, n + 1);
    return 0;
}

int max(int x, int y) {
    return (x > y) ? x : y;
}

用一个数组存放10个学生成绩,求平均成绩

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告

#include<stdio.h>

int main() {
    float average(float array[10]);
    float score[10], aver;
    int i;
    printf("input 10 scores:\n");
    for (i = 0; i < 10; i++) {
        scanf("%f", &score[i]);
    }
    printf("\n");
    aver = average(score);                  // 一维数组名作为实参
    printf("average score is %5.2f\n", aver);
    return 0;
}

float average(float array[10]) {        // 可以不指定数组大小
    int i;
    float aver, sum = array[0];
    for (i = 1; i < 10; i++) {
        sum = sum + array[i];
    }
    aver = sum / 10;
    return aver;
}

有两个班级,分别有5名和10学生,调用一个average函数分别求这两个班的平均成绩

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告

#include<stdio.h>

int main() {
    float average(float array[], int n);
    float score1[5] = { 98.5,97,91.5,60,55 };
    float score2[10] = { 67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5 };
    printf("the average of class A is %6.2f\n", average(score1, 5));
    printf("the average of class B is %6.2f\n", average(score2, 10));
    return 0;
}

float average(float array[],int n) {
    int i;
    float aver, sum = array[0];
    for (i = 1; i < n; i++) {
        sum = sum + array[i];
    }
    aver = sum / n;
    return aver;
}

选择排序—对数组中10个整数由小到大排序

每趟选择一个最小的元素放在最终位置,n个元素第i趟比较n-i次

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告

#include<stdio.h>

int main() {
    void sort(int array[], int n);
    int a[10], i;
    printf("enter array:\n");
    for (i = 0; i < 10; i++) {
        scanf("%d", &a[i]);
    }
    sort(a, 10);
    printf("the sorted array: \n");
    for (i = 0; i < 10; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
}

void sort(int array[], int n) {
    int i, j, k, t;
    for ( i = 0; i < n-1; i++) {
        k = i;
        for ( j = i+1; j < n; j++) {
            if (array[j] < array[k]) {
                k = j;
            }
        }
        t = array[k];                            // 交换元素
        array[k] = array[i];
        array[i] = t;
    }
}

有一个 3x4 的矩阵,求所有元素最大值

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告

#include<stdio.h>

int main() {
    int max_value(int array[][4]);
    int a[3][4] = { {1,2,3,4} ,{5,7,6,8},{10,9,12,11} };
    printf("max value is %d\n", max_value(a));
    return 0;
}

int max_value(int array[][4]) {
    int i, j, max;
    max = array[0][0];
    for ( i = 0; i < 3; i++) {
        for ( j = 0; j < 4; j++) {
            if (array[i][j] > max) {
                max = array[i][j];
            }
        }
    }
    return max;
}

有一个一维数组存放10名学生的成绩,要求编写一个函数求出平均分、最高分和最低分

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告

#include<stdio.h>

float Max = 0, Min = 0;

int main() {
    float average(float array[], int n);
    float ave, score[10] = { 67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5 };
    ave = average(score,10);
    printf("max=%6.2f\nmin=%6.2f\naverage=%6.2f\n", Max, Min, ave);
    return 0;
}

float average(float array[], int n) {
    float aver, sum = array[0];
    Max = Min = array[0];
    for (int i = 0; i < n; i++) {
        if (array[i] > Max) {
            Max = array[i];
        }
        else if (array[i] < Min) {
            printf("aa\n");
            Min = array[i];
        }
        sum = sum + array[i];
    }
    aver = sum / n;
    return aver;
}

输出1到5的阶乘值

// 输出1到5的阶乘
#include<stdio.h>

int main() {
    int fac(int n);
    int i;
    for ( i = 1; i <=5; i++) {
        printf("%d!=%d\n", i, fac(i));
    }
    return 0;
}

int fac(int n) {
    static int r = 1;
    r = r * n;
    return r;
}

用外部函数实现,有一个字符串,内有若干个字符,现输入一个字符,要求程序将字符串中该字符删去

file1.c
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996) // 禁止显示strcpy等不安全函数的警告
#pragma warning(disable:6031) // 禁止显示未经检查的返回值警告

#include<stdio.h>

int main() {
	extern void enter_string(char str[]);                    // 声明外部函数
	extern void delete_string(char str[], char ch);
	extern void print_string(char str[]);

	char c, str[80];
	enter_string(str);
	printf("please input delete char: ");
	scanf("%c",&c);
	delete_string(str, c);
	print_string(str);
	return 0;
}

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

void enter_string(char str[80]) {
	printf("please input string: ");
	gets(str);
}

void delete_string(char str[], char ch) {
	int i, j;
	for (i = j = 0; str[i] != '\0'; i++) {
		if (str[i] != ch) {
			str[j++] = str[i];
		}
	}
	str[j] = '\0';
}

extern void print_string(char str[]) {
	printf("%s\n", str);
}

引申:不用extern声明外部变量,用#include "file2.c"导入

  • 13
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

childish_tree

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值