C语言函数使用教程,函数定义、调用、参数传递与递归函数详解

​C语言函数详如何自定函数实现代码复用与模块化编程?​本文将带你进行详细的学习。​

C语言函数的使用入门,深入了解函数的定义、调用、参数传递机制,包含返回值、作用域、递归函数等高级特性,助你实现代码模块化。​

随着程序变得越来越复杂,将所有代码都写在main函数中会变得难以维护和理解。C语言通过函数将代码划分为独立的模块,让每个函数完成特定功能。这种模块化编程方法大大提高了代码的可读性、可维护性和复用性。

1. 什么是函数?

函数是完成特定任务的独立代码块,可以接收输入参数,返回处理结果。

函数的优势:​

  • 代码复用​:一次定义,多次调用
  • 模块化​:将复杂问题分解为小问题
  • 易于维护​:修改只需在函数内部进行
  • 提高可读性​:通过函数名理解功能

2. 函数的定义和调用

函数定义语法:​

返回类型 函数名(参数列表) {
    // 函数体
    return 返回值; // 如果返回类型不是void
}

基本示例:​

#include <stdio.h>

// 函数声明(函数原型)
void printHello();
int add(int a, int b);

// 主函数
int main() {
    printHello();  // 函数调用
    
    int result = add(5, 3);  // 函数调用并接收返回值
    printf("5 + 3 = %d\n", result);
    
    return 0;
}

// 函数定义:打印问候语
void printHello() {
    printf("Hello, World!\n");
}

// 函数定义:两数相加
int add(int a, int b) {
    return a + b;
}

3. 函数参数:传值调用

C语言默认使用传值调用,函数接收的是参数的副本,不会影响原始变量。

#include <stdio.h>

// 交换两个数的值(错误版本)
void swapWrong(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
    printf("函数内: a=%d, b=%d\n", a, b);
}

// 计算阶乘
int factorial(int n) {
    int result = 1;
    for (int i = 1; i <= n; i++) {
        result *= i;
    }
    return result;
}

int main() {
    int x = 5, y = 10;
    
    printf("交换前: x=%d, y=%d\n", x, y);
    swapWrong(x, y);  // 传值调用
    printf("交换后: x=%d, y=%d\n", x, y);  // x,y的值未改变
    
    // 计算阶乘
    int num = 5;
    printf("%d! = %d\n", num, factorial(num));
    
    return 0;
}

4. 函数返回值

函数可以通过return语句返回结果,返回类型必须与函数声明一致。

#include <stdio.h>
#include <stdbool.h>

// 返回最大值
int max(int a, int b) {
    return (a > b) ? a : b;
}

// 判断是否为偶数
bool isEven(int num) {
    return num % 2 == 0;
}

// 多个返回语句
char getGrade(int score) {
    if (score >= 90) return 'A';
    if (score >= 80) return 'B';
    if (score >= 70) return 'C';
    if (score >= 60) return 'D';
    return 'F';
}

int main() {
    printf("最大值: %d\n", max(10, 20));
    printf("15是偶数吗? %s\n", isEven(15) ? "是" : "否");
    printf("成绩等级: %c\n", getGrade(85));
    
    return 0;
}

5. 函数原型声明

函数原型告诉编译器函数的接口信息,通常放在文件开头。

#include <stdio.h>

// 函数原型声明
double calculateCircleArea(double radius);
double calculateCircleCircumference(double radius);
void displayCircleInfo(double radius);

int main() {
    double r = 5.0;
    displayCircleInfo(r);
    return 0;
}

// 函数定义
double calculateCircleArea(double radius) {
    return 3.14159 * radius * radius;
}

double calculateCircleCircumference(double radius) {
    return 2 * 3.14159 * radius;
}

void displayCircleInfo(double radius) {
    printf("半径: %.2f\n", radius);
    printf("面积: %.2f\n", calculateCircleArea(radius));
    printf("周长: %.2f\n", calculateCircleCircumference(radius));
}

6. 变量的作用域

变量的作用域决定了它在程序中的可见范围。

#include <stdio.h>

int globalVar = 100;  // 全局变量

void testFunction() {
    int localVar = 50;  // 局部变量
    static int staticVar = 0;  // 静态局部变量
    
    localVar++;
    staticVar++;
    
    printf("局部变量: %d, 静态变量: %d\n", localVar, staticVar);
}

int main() {
    printf("全局变量: %d\n", globalVar);
    
    testFunction();  // 局部变量: 51, 静态变量: 1
    testFunction();  // 局部变量: 51, 静态变量: 2
    testFunction();  // 局部变量: 51, 静态变量: 3
    
    // printf("%d", localVar);  // 错误!局部变量不可见
    
    return 0;
}

7. 数组作为函数参数

数组作为函数参数时,传递的是数组首元素的地址。

#include <stdio.h>

// 打印数组
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

// 修改数组元素
void doubleArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;  // 会修改原始数组
    }
}

// 查找数组最大值
int findMax(int arr[], int size) {
    int max = arr[0];
    for (int i = 1; i < size; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    return max;
}

int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int n = sizeof(numbers) / sizeof(numbers[0]);
    
    printf("原始数组: ");
    printArray(numbers, n);
    
    printf("最大值: %d\n", findMax(numbers, n));
    
    doubleArray(numbers, n);
    printf("加倍后的数组: ");
    printArray(numbers, n);
    
    return 0;
}

8. 递归函数

递归函数是直接或间接调用自身的函数。

#include <stdio.h>

// 递归计算阶乘
int factorial(int n) {
    if (n <= 1) return 1;        // 基线条件
    return n * factorial(n - 1);  // 递归调用
}

// 递归计算斐波那契数列
int fibonacci(int n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

// 递归显示数字位数
void displayDigits(int n) {
    if (n < 10) {
        printf("%d ", n);
        return;
    }
    displayDigits(n / 10);
    printf("%d ", n % 10);
}

int main() {
    printf("5! = %d\n", factorial(5));
    
    printf("斐波那契数列前10项: ");
    for (int i = 0; i < 10; i++) {
        printf("%d ", fibonacci(i));
    }
    printf("\n");
    
    printf("12345的各位数字: ");
    displayDigits(12345);
    printf("\n");
    
    return 0;
}

9. 实战案例:学生成绩管理系统

#include <stdio.h>
#define MAX_STUDENTS 100

// 函数原型
void inputScores(int scores[], int n);
void displayScores(int scores[], int n);
float calculateAverage(int scores[], int n);
int findMaxScore(int scores[], int n);
int findMinScore(int scores[], int n);
void sortScores(int scores[], int n);

int main() {
    int scores[MAX_STUDENTS];
    int numStudents;
    
    printf("请输入学生人数: ");
    scanf("%d", &numStudents);
    
    if (numStudents > MAX_STUDENTS) {
        printf("人数超过限制!\n");
        return 1;
    }
    
    inputScores(scores, numStudents);
    displayScores(scores, numStudents);
    
    printf("平均分: %.2f\n", calculateAverage(scores, numStudents));
    printf("最高分: %d\n", findMaxScore(scores, numStudents));
    printf("最低分: %d\n", findMinScore(scores, numStudents));
    
    sortScores(scores, numStudents);
    printf("排序后的成绩: ");
    displayScores(scores, numStudents);
    
    return 0;
}

void inputScores(int scores[], int n) {
    printf("请输入%d个学生的成绩:\n", n);
    for (int i = 0; i < n; i++) {
        printf("学生%d: ", i + 1);
        scanf("%d", &scores[i]);
    }
}

void displayScores(int scores[], int n) {
    printf("成绩列表: ");
    for (int i = 0; i < n; i++) {
        printf("%d ", scores[i]);
    }
    printf("\n");
}

float calculateAverage(int scores[], int n) {
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += scores[i];
    }
    return (float)sum / n;
}

int findMaxScore(int scores[], int n) {
    int max = scores[0];
    for (int i = 1; i < n; i++) {
        if (scores[i] > max) {
            max = scores[i];
        }
    }
    return max;
}

int findMinScore(int scores[], int n) {
    int min = scores[0];
    for (int i = 1; i < n; i++) {
        if (scores[i] < min) {
            min = scores[i];
        }
    }
    return min;
}

void sortScores(int scores[], int n) {
    // 冒泡排序
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (scores[j] > scores[j + 1]) {
                int temp = scores[j];
                scores[j] = scores[j + 1];
                scores[j + 1] = temp;
            }
        }
    }
}

10. 常见错误与最佳实践

常见错误1:忘记返回值

int add(int a, int b) {
    int result = a + b;
    // 忘记写 return result;
}

常见错误2:函数原型不匹配

// 原型声明
void display(int num);

// 函数定义
int display(int num) {  // 错误!返回类型不匹配
    printf("%d", num);
}

最佳实践:​

  1. 为函数起有意义的名称
  2. 每个函数只完成一个明确的任务
  3. 使用函数原型声明
  4. 合理使用注释说明函数功能
  5. 避免过长的函数(通常不超过50行)

11. 总结

在本篇教程中,你学到了:

  • 函数的定义、调用和原型声明
  • 参数传递的传值机制
  • 返回值的使用方法
  • 变量的作用域规则
  • 数组作为函数参数的用法
  • 递归函数的原理和实现
  • 模块化编程的实战应用

12. 动手练习

  1. 基础练习​:编写函数判断一个数是否为素数。
  2. 进阶练习​:编写递归函数计算两个数的最大公约数(GCD)。
  3. 挑战练习​:使用函数模块化重构之前的成绩管理系统,添加成绩统计、等级评定等功能。

发表评论