目录

前文列表

程序编译流程与 GCC 编译器
C 语言编程 — 基本语法
C 语言编程 — 基本数据类型
C 语言编程 — 变量与常量
C 语言编程 — 运算符
C 语言编程 — 逻辑控制语句
C 语言编程 — 函数
C 语言编程 — 高级数据类型 — 指针
C 语言编程 — 高级数据类型 — 数组
C 语言编程 — 高级数据类型 — 字符串
C 语言编程 — 高级数据类型 — 枚举
C 语言编程 — 高级数据类型 — 结构体与位域
C 语言编程 — 高级数据类型 — 共用体
C 语言编程 — 高级数据类型 — void 类型
C 语言编程 — 数据类型的别名
C 语言编程 — 数据类型转换
C 语言编程 — 宏定义与预处理器指令
C 语言编程 — 异常处理
C 语言编程 — 头文件
C 语言编程 — 输入/输出与文件操作
C 语言编程 — 堆栈内存管理
C 语言编程 — 指令行参数
C 语言编程 — GDB 调试工具
C 语言编程 — 代码规范

程序示例

键入5个学生的名称、语文成绩、数学成绩和英语成绩,输出各个学生的成绩等级和各科成绩的排名。

#include <stdio.h>

/* 宏定义要在后面注释说明含义 */
#define STUDENT_NUM	5  // 统计总人数
#define SCORE_NUM	3  // 科目总数

/* score 为各科成绩分数.
 * 	score[0] 为语文成绩,
 * 	score[1] 为数学成绩,
 * 	score[2] 为英文成绩.
 * grade 为各科成绩的分数等级
 * 	grade[0] 为语文成绩等级,
 * 	grade[1] 为数学成绩等级,
 * 	grade[2] 为英文成绩等级.
 * name 为 student name
 */
struct student {
    int score[SCORE_NUM];
    char grade[SCORE_NUM];
    char name[20];
};

/* 定义 student 结构体数组全局变量,数组元素就是结构体本身,作用域是整个程序 */
struct student s_array[STUDENT_NUM];

/* 在文件首部编写函数声明是为了便于阅读 */
void input_message(void);
void printf_grade(struct student *stu_pc);
void bubble_method(int *score_buf, char **stuname_buf);


/*
 * Function: 键入每个学生的信息,包括:姓名、语文成绩、数学成绩和英语成绩
 * Note:
 * 	先键入学生名称,再键入语文成绩,再键入数学成绩,最后键入英语成绩
 * 	信息键入需要注意空格!
 */
void input_message(void) {
    int i = 0;

    /* 为了可读性,条件表达式中也要重新为 i 进行赋值 */
    for (i = 0; i < STUDENT_NUM; i++) {
        printf("Enter the num %d student's message:\r\n", i);

        /* s_array[i].name 是一个字符串数据类型变量,变量名本身就是一个指针,所以不需要额外使用取地址运算符 & */
        scanf("%s %d %d %d", s_array[i].name, &(s_array[i].score[0]), &(s_array[i].score[1]), &(s_array[i].score[2]));
        printf_grade(&s_array[i]);
    }
}

/* Function: 将单个学生的各科的成绩结果划分等级, 输出各科的成绩等级
 * Note:
 * 	[0 , 60) 为 D
 * 	[60, 75) 为 C
 * 	[75, 85) 为 B
 * 	[85, 100] 为 A
 * 	其余输入值会被认为是错误值,显示 E
 */
void printf_grade(struct student *stu_pc) {
    int i = 0;

    for (i = 0; i < SCORE_NUM; i++) {
        /* 形参 stu_pc 是 student 结构体指针变量,所以使用指针成员访问符 -> */
        if ((0 <= stu_pc->score[i]) && (60 > stu_pc->score[i])) {
            stu_pc->grade[i] = 'D';
        }
        else if ((60 <= stu_pc->score[i]) && (75 > stu_pc->score[i])) {
            stu_pc->grade[i] = 'C';
        }
        else if ((75 <= stu_pc->score[i]) && (85 > stu_pc->score[i])) {
            stu_pc->grade[i] = 'B';
        }
        else if ((85 <= stu_pc->score[i]) && (100 >= stu_pc->score[i])) {
            stu_pc->grade[i] = 'A';
        }
        else {
            stu_pc->grade[i] = 'E';  // ERROR
        }
        printf("%c ", stu_pc->grade[i]);
    }
    printf("\n");
}

/*
 * Function: 使用冒泡法,对单科成绩进行排名
 * Note:
 * 	因为字符串指针数组变量的变量名是一个指向指针的指针所以形参使用 char **stuname_buf 类型
 */
void bubble_method(int *score_buf, char **stuname_buf) {
    int i = 0;
    int j = 0;
    int score_temp = 0;
    char *stuname_temp = NULL;

    for (i = 0; i < STUDENT_NUM; i++) {
        for (j = 0; j < STUDENT_NUM - i - 1; j++) {
            score_temp = score_buf[j];
            stuname_temp = stuname_buf[j];

            /* 前后比较学习分数,以此进行排序,同时也对学生名字进行排序 */
            if (score_buf[j] > score_buf[j + 1]) {
                score_buf[j] = score_buf[j + 1];
                stuname_buf[j] = stuname_buf[j + 1];

                score_buf[j + 1] = score_temp;
                stuname_buf[j + 1] = stuname_temp;
            }
        }
    }
}

int main(void) {
    int k = 0;
    int i = 0;
    int score_temp[STUDENT_NUM];      // 定义整型数组变量,存储学生成绩,用于成绩排序
    char *stuname_temp[STUDENT_NUM];  // 定义字符串指针数组变量,存储学生姓名,用于跟踪成绩排序结果

    input_message();

    for (k = 0; k < SCORE_NUM; k++) {
        for (i = 0; i < STUDENT_NUM; i++) {
            score_temp[i] = s_array[i].score[k];
            /* 字符串指针数组存放字符串的指针(字符串变量名就是一个字符串类型指针) */
            stuname_temp[i] = s_array[i].name;
        }

        bubble_method(score_temp, stuname_temp);

        switch (k) {
            case 0:
                printf("Chinese Ranking:\r\n");
                break;
            case 1:
                printf("ath Ranking:\r\n");
                break;
            case 2:
                printf("English Ranking:\r\n");
                break;
            default:
                printf("Error\r\n");
        }

        for (i = STUDENT_NUM - 1; i >= 0; i--) {
            printf("Num %d is %s, score = %d\r\n", STUDENT_NUM - i, stuname_temp[i], score_temp[i]);
        }
    }
    return 0;
}

运行:

$   ./main
Enter the num 0 student's message:
Astu 90 90 90
A A A
Enter the num 1 student's message:
Bstu 80 80 80
B B B
Enter the num 2 student's message:
Cstu 70 70 70
C C C
Enter the num 3 student's message:
Dstu 60 60 60
C C C
Enter the num 4 student's message:
Estu 50 50 50
D D D
Chinese Ranking:
Num 1 is Astu, score = 90
Num 2 is Bstu, score = 80
Num 3 is Cstu, score = 70
Num 4 is Dstu, score = 60
Num 5 is Estu, score = 50
ath Ranking:
Num 1 is Astu, score = 90
Num 2 is Bstu, score = 80
Num 3 is Cstu, score = 70
Num 4 is Dstu, score = 60
Num 5 is Estu, score = 50
English Ranking:
Num 1 is Astu, score = 90
Num 2 is Bstu, score = 80
Num 3 is Cstu, score = 70
Num 4 is Dstu, score = 60
Num 5 is Estu, score = 50

C 语言编程 — 编程实践_C 语言

  • 为追求更快的执行速度和效率,示例中的 printf_grade 和 bubble_method 函数都使用指针作为传参。相对于将整个数组变量拷贝到函数,采用指针作为传参的执行速度更快、效率更高。
  • 示例中的 input_message、printf_grade 和 bubble_method 函数的类型均是空类型,这意味着这 3 个函数均是没有返回值。其中,input_message 的传参为 void,也就是说 input_message 是不需要传入参数。