C语言利用_Generic() 泛型实现函数重载功能(以简单计算器为例)

806 阅读2分钟

_Generic() 泛型

_Generic(),是C11 添加的特性,用于泛型开发 。

_Generic()语法

_Generic(<var>, <type1> : <exp1>, <type2> : <exp2>, ...)

例子

以下是一个简单计算器的例子,在计算器中整数的运算除了加减乘除还有求余,但是小数是没有求余的,因此我们这里用这个_Generic()实现函数重载

#include <stdio.h>
#include <math.h>

// 整数的加减乘除求余
void calculateResInt(int *num1, char oper, int num2)
{
    switch (oper) {
        case '+': {
            printf("结果: %d\n", *num1 + num2);
            *num1 += num2;    // num1中存放上次计算的结果
            break;
        }
        case '-': {
            printf("结果: %d\n", *num1 - num2);
            *num1 -= num2;
            break;
        }
        case '*': {
            printf("结果: %d\n", *num1 * num2);
            *num1 *= num2;    // num1中存放上次计算的结果
            break;
        }
        case '/': {
            printf("结果: %d\n", *num1 / num2);
            *num1 /= num2;
            break;
        }
        case '%': {
            if (num2 == 0) {
                printf("除数不可为0,请重新输入!!!\n");
                break;
            }
            printf("结果: %d\n", *num1 % num2);
            *num1 %= num2;
            break;
        }
        default: {
            printf("数据格式有误,请重新输入!!!\n");
            break;
        }
    }
    return;
}

// 浮点数的加减乘除
void calculateResDou(double *num1, char oper, double num2)
{
    switch (oper) {
        case '+': {
            printf("结果: %lf\n", *num1 + num2);
            *num1 += num2;    // num1中存放上次计算的结果
            break;
        }
        case '-': {
            printf("结果: %lf\n", *num1 - num2);
            *num1 -= num2;
            break;
        }
        case '*': {
            printf("结果: %lf\n", *num1 * num2);
            *num1 *= num2;    // num1中存放上次计算的结果
            break;
        }
        case '/': {
            if (fabs(num2) <= 1e-15) {
                printf("除数不可为0,请重新输入!!!\n");
                break;
            }
            printf("结果: %lf\n", *num1 / num2);
            *num1 /= num2;
            break;
        }
        default: {
            printf("数据格式有误,请重新输入!!!\n");
            break;
        }
    }
    return;
}

// _Generic泛型,其中参数a是int*类型时,调用calculateResInt函数,参数a是double*类型时调用calculateResDou函数,如果不是int*也不是double*则调用默认的calculateResDou函数
#define cal(a, c, b) _Generic(a, int*: calculateResInt, double*: calculateResDou, default: calculateResDou)(a, c, b)

int main()
{
    double num1 = 0.0;
    double num2 = 0.0;
    int num3 = 0;
    int num4 = 0;
    char oper = 0;
    int isInt = 0;

    while (printf("请输入是整数计算还是浮点数计算(整数输入1,浮点数输入2,退出输入0):")) {
        scanf("%d", &isInt);
        if (isInt == 0) {    // 直接退出程序
            return 0;
        }
        while (printf("请输入(以空格隔开): ")) {
            if (isInt == 1) {
                scanf("%d %c %d", &num3, &oper, &num4);
                cal(&num3, oper, num4);
            } else {
                scanf("%lf %c %lf", &num1, &oper, &num2);
                cal(&num1, oper, num2);
            }
            
            oper = 0;
            num2 = 0;
        }
    }
    return 0;
}