精品案例-用C语言实现成绩与等级相互转换

精品案例-用C语言实现成绩与等级相互转换

编码文章call10242025-05-04 13:30:531A+A-

题目要求:

用C语言编写代码,完成成绩与等级,等级与成绩范围的转换,具体要求如下:

  1. 设计和实现函数,输入成绩,给出成绩对应的等级
  2. 设计和实现函数,输入等级,给出等级对应的成绩范围
  3. 编写测试代码,完成测试

成绩与等级的对应关系如下表:

成绩范围

对应的等级

90 <= 成绩 <=100

A

80 <= 成绩 < 90

B

70 <= 成绩 < 80

C

60 <= 成绩 < 70

D

成绩 <60

E

补充说明:

假设成绩是整数,不考虑成绩带小数的情况。

实现

入门级实现

咋一看这个题目,太简单了,if-else或switch-case直接就能解决问题,放到《企业级C语言精品案例》中这也太搞笑了吧。于是乎有了如下代码实现:

  • 成绩转等级
int main()
{
    int score;
    
    printf("成绩转等级,请输入成绩(0~100)\n");
    scanf("%d", &score);
    if (score < 60) {
        printf("成绩%d对应的等级为E\n", score);
    }
    else if (score < 70) {
        printf("成绩%d对应的等级为D\n", score);
    }
    else if (score < 80) {
        printf("成绩%d对应的等级为C\n", score);
    }
    else if (score < 90) {
        printf("成绩%d对应的等级为B\n", score);
    }
    else if (score < 101) {
        printf("成绩%d对应的等级为A\n", score);
    }
    else {
        printf("成绩%不在合理的范围\n");
    }
    
    return 0;
}
  • 等级转成绩区间
int main()
{
    char grade;
    
    printf("等级转成绩区间,请输入等级(A~E):\n");
    scanf("%c", &grade);
    switch(grade) {
        case 'A':
        case 'a':
            printf("等级%c对应的成绩区间为:90 ~ 100", grade);
            break;
        case 'B':
        case 'b':
            printf("等级%c对应的成绩区间为:80 ~ 89", grade);
            break;
        case 'C':
        case 'c':
            printf("等级%c对应的成绩区间为:70 ~ 79", grade);
            break;
        case 'D':
        case 'd':
            printf("等级%c对应的成绩区间为:60 ~ 69", grade);
            break;
        case 'E':
        case 'e':
            printf("等级%c对应的成绩区间为:0 ~ 59", grade);
            break;
        default:
            printf("输入不合法:%c", grade);
            break;
    }
    
    return 0;
}

中级实现

初级实现,实现了功能但不易复用,代码全写在main()函数中在本项目或其他需要该算法的项目中无法直接使用;另外,如果A项目与用户交互的界面是命令行,B项目与用户交互通过GUI界面,这段代码做不到在2个项目中通用。

代码片段要做到易复用,需要与输入函数和输出函数解耦,简单讲就是其中不要调用类似printf和scanf之类的函数,可以通过参数和返回值来做数据传递,参数从哪里来,返回值怎么使用,完全由函数调用方决定,这样就可以实现代码的高复用。第二版代码:

  • 成绩转等级
char score_to_grade(uint8_t score, char *grade)
{
    char grade;

    if (score < 60) {
        grade = 'E';
    }
    else if (score < 70) {
        grade = 'D';
    }
    else if (score < 80) {
        grade = 'C';
    }
    else if (score < 90) {
        grade = 'B';
    }
    else if (score < 101) {
        grade = 'A';
    }
    else {
    }

    return grade;
}
  • 等级转成绩区间

由于等级对应的成绩区间包括开始分数和结束分数,但一个函数只能有1个返回值,因此考虑使用指针做函数参数,返回值通过指针传递给函数调用方,代码如下:

void grade_to_score(char grade, uint8_t *score_start, uint8_t *score_end)
{
    switch(grade) {
        case 'A':
        case 'a':
            *score_start = 90;
            *score_end = 100;
            break;
        case 'B':
        case 'b':
            *score_start = 80;
            *score_end = 89;
            break;
        case 'C':
        case 'c':
            *score_start = 70;
            *score_end = 79;
            break;
        case 'D':
        case 'd':
            *score_start = 60;
            *score_end = 69;
            break;
        case 'E':
        case 'e':
            *score_start = 0;
            *score_end = 59;
            break;
        default:
            break;
    }
}

企业级实现

中级实现,同样完成了功能,但还存在一些考虑不周到的地方,还可以继续“进化”:

  1. 输出参数超范围怎么办,转换函数调用方无法得知
  2. 如果等级与分数的对应关系发生变化,需要改2个函数,漏改一处就产生一个缺陷

针对上述2个问题,我们给出解决方案:

  1. 转换函数的输入,通过参数传入,转换函数的输出通过指针传出,函数的返回值用来表示转换是否成功
  2. 我们抽象地思考一下这个问题,等级与成绩区间存在对应关系,我们能否通过一个结构体来描述这种对应关系呢?结构体配合算法完成相互转换的逻辑

企业级实现是这样的:

  • 头文件:
/******************************************************************************
 *  Copyright 2022
 *
 *  @file    grade_score.h
 *
 *  @brief   
 *
 *=============================================================================
 *  Revision History
 *  Version     Date        Author      Content
 *  -------     ----------  ---------   ---------------------------------------
 *  V1.00       2022/09/16  yangyf      Create.
 *
 *****************************************************************************/
#ifndef __GRADE_SCORE_H__
#define __GRADE_SCORE_H__

#include <stdint.h>

extern int32_t score_to_grade(uint8_t score, char *grade);
extern int32_t grade_to_score(char grade, uint8_t *score_start, uint8_t *score_end);

#endif /* __GRADE_SCORE_H__ */
  • 源文件
/******************************************************************************
 *  Copyright 2015-2022
 *
 *  @file    grade_score.c
 *
 *  @brief   
 *
 *=============================================================================
 *  Revision History
 *  Version     Date        Author      Content
 *  -------     ----------  ---------   ---------------------------------------
 *  V1.00       2022/09/16  yangyf      Create.
 *
 *****************************************************************************/
/* 定义结构体,描述等级与成绩区间的对应关系 */
typedef struct {
    char grade;
    uint8_t score_start;
    uint8_t score_end;
} grade_score_item_t;

/* 定义结构体数组,描述具体等级与具体成绩区间的对应关系 */
/* 这里注意static和const的使用 */
static const grade_score_item_t grade_score_map[] = {
    {'E', 0, 59},
    {'D', 60, 69},
    {'C', 70, 79},
    {'B', 80, 89},
    {'A', 90, 100}
};

/* 为方便扩展,定义一个自动计算数组元素数量的宏 */
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
/******************************************************************************
 *
 * FUNCTIONS
 *
 *****************************************************************************/
/******************************************************************************
 *  @fn      int32_t score_to_grade(uint8_t score, char *grade)
 *
 *  @brief   成绩转等级
 *
 *  @param   uint8_t score [I/] 成绩
 *           char *grade   [/O] 成绩对应的等级
 *
 *  @return  0: 转换成功; 非零值:转换失败
 */
int32_t score_to_grade(uint8_t score, char *grade)
{
    int32_t ret = -1;

    for (int i = 0; i < ARRAY_SIZE(grade_score_map); ++i) {
        if ((grade_score_map[i].score_start <= score)
                && (score <= grade_score_map[i].score_end)) {
            *grade = grade_score_map[i].grade;
            ret = 0;
            break;
        }
    }

    return ret;
}

/******************************************************************************
 *  @fn      int32_t grade_to_score(char grade, uint8_t *score_start, uint8_t *score_end)
 *
 *  @brief   等级转成绩区间
 *
 *  @param   char grade [I/] 等级
 *           uint8_t *score_start [/O] 成绩区间开始值
 *           uint8_t *score_end   [/O] 成绩区间结束值
 *
 *  @return  0: 转换成功; 非零值:转换失败
 */
int32_t grade_to_score(char grade, uint8_t *score_start, uint8_t *score_end)
{
    int32_t ret = -1;

    if (('a' <= grade) && (grade <= 'z')) {
        grade = grade - 0x20;   /* a=>A, b=>B, ..., z=>Z */
    }
    for (int i = 0; i < ARRAY_SIZE(grade_score_map); ++i) {
        if (grade == grade_score_map[i].grade) {
            *score_start = grade_score_map[i].score_start;
            *score_end = grade_score_map[i].score_end;
            ret = 0;
            break;
        }
    }

    return ret;
}

/* - End Of File - */

企业级实现的代码,严格遵守了《企业级C语言精品案例》中“C语言编码规范”章节中的各项规则;做到了输入函数输出函数与主体算法的分离;体现了“程序 = 数据结构 + 算法”的思想,做到了易复用,易维护。

  • 算法测试代码
/******************************************************************************
 *  Copyright 2015-2022
 *
 *  @file    grade_score_test.c
 *
 *  @brief   
 *
 *=============================================================================
 *  Revision History
 *  Version     Date        Author      Content
 *  -------     ----------  ---------   ---------------------------------------
 *  V1.00       2022/09/16  yangyf      Create.
 *
 *****************************************************************************/
#include "grade_score.h"

/******************************************************************************
 *
 * FUNCTIONS
 *
 *****************************************************************************/
int main()
{
    int32_t ret;
    uint8_t score;
    char grade;

    printf("Please input score(0 ~ 100):");
    scanf("%d", &score);
    getchar();
    ret = score_to_grade(score, &grade);
    if (0 == ret) {
        printf("score: %d, grade: %c\n", score, grade);
    }
    else {
        printf("score %d not between 0 and 100\n");
    }

    uint8_t score_start, score_end;
    printf("Please input grade(A ~ E):");
    scanf("%c", &grade);
    getchar();
    ret = grade_to_score(grade, &score_start, &score_end);
    if (0 == ret) {
        printf("grade: %c, score: from %d to %d\n", grade, score_start, score_end);
    }
    else {
        printf("grade %c not between A and E\n");
    }

    return 0;
}

/* - End Of File - */

~ END ~

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4