C 程序制作一个可以执行简单算术运算并在 int 和 double 变量之间切换的计算器

C program to make a calculator that can perform simple arithmetic and toggle between int and double variables

我对 c 编程有点陌生。对于我的项目,我的任务是开发一个简单的计算器,要求用户输入一个选项,然后该选项声明要执行的操作(即,如果用户输入 1,这对应于选择加法选项,然后允许用户添加他们选择的两个数字。我已经完成了大部分代码,但问题是我需要计算器在 int 和 double 变量之间切换。当用户输入 5 时,计算器现在应该使用整数,然后如果用户再次点击 5,只要您想来回切换,计算器就会切换回双精度,反之亦然。计算器会自动使用双精度。所以,更具体地说,如果我想使用整数变量,我会输入 5,然后假设我想切换回双打,我应该输入 5 并收到消息 "Calculator now works with doubles." 所以这是我到目前为止的代码:

#include<stdio.h>
#include<math.h>
#include<stdbool.h>
int main()
{
    int integermode, doublemode, m, a, b, sum2, difference2, product2, 
    quotient2;
    double i, j, sum1, difference1, product1, quotient1;

    printf("This program implements a calculator.");

    while(m !=6) {
        printf("Options:\n");
        printf("1 - addition\n2 - subtraction\n3 - multiplication\n4 - division\n5 - toggle calculator type\n6 - exit program\n");
        printf("Please enter your option: ");
        scanf("%d", &m);
        if(m > 6) {
            printf("Invalid option.\n");
            printf("Options:\n");
            printf("1 - addition\n2 - subtraction\n3 - multiplication\n4 - division\n5 - toggle calculator type\n6 - exit program\n");
            printf("Please enter your option: ");
            scanf("%d", &m);
        }
        switch (m) {

            case 1: 
                if (integermode == true) {
                    printf("Enter first term: ");
                    scanf("%d", &a);    
                    printf("Enter second term: ");
                    scanf("%d", &b);
                    printf("The sum is: %d\n", a+b);
                    break;
                }
                if (integermode == false) {
                    printf("Enter first term: ");
                    scanf("%lf", &i);   
                    printf("Enter second term: ");
                    scanf("%lf", &j);
                    printf("The sum is: %.15lf\n", i+j);
                }
                break;  

            case 2: 
                if (integermode == true) {
                    printf("Enter first term: ");
                    scanf("%d", &a);    
                    printf("Enter second term: ");
                    scanf("%d", &b);
                    printf("The difference is: %d\n", a-b);
                    break;
                }
                if (integermode == false) {
                    printf("Enter first term: ");
                    scanf("%lf", &i);   
                    printf("Enter second term: ");
                    scanf("%lf", &j);
                    printf("The difference is: %.15lf\n", i-j);
                }
                break;  

            case 3: 
                if (integermode == true) {
                    printf("Enter first term: ");
                    scanf("%d", &a);    
                    printf("Enter second term: ");
                    scanf("%d", &b);
                    printf("The product is: %d\n", a*b);
                    break;
                }
                if (integermode == false) {
                    printf("Enter first term: ");
                    scanf("%lf", &i);   
                    printf("Enter second term: ");
                    scanf("%lf", &j);
                    printf("The product is: %.15lf\n", i*j);
                }
                break;  

            case 4: 
                if (integermode == true) {
                    printf("Enter first term: ");
                    scanf("%d", &a);    
                    printf("Enter second term: ");
                    scanf("%d", &b);
                    if (b != 0) printf("The quotient is: %d\n", a/b);
                    if (b == 0) printf("Cannot divide by zero!\n");
                    break;
                }
                if (integermode == false) {
                    printf("Enter first term: ");
                    scanf("%lf", &i);   
                    printf("Enter second term: ");
                    scanf("%lf", &j);
                    if(j != 0) printf("The quotient is: %.15lf\n", i/j);
                    if(j == 0) printf("Cannot divide by zero!\n");
                    break;
                }

            case 5: 
            if (m = 5) {
                integermode = true;
                printf("Calculator now works with integers.\n");
            }
            if (m != 5) integermode = false;
        }
    } 

    return 0;
}

一般改进

首先,您应该注意到您的 main 函数对于它需要完成的事情来说是巨大的,并且需要大量的缩进级别(当正确缩进时)。这主要是因为您有大量重复的功能。您可以轻松地将要求输入数字的代码提取到一个函数中并重新使用它,只更改在每种情况下执行的操作。或者甚至更好,您可以要求输入数字作为主 while 循环的一部分,然后根据您所处的操作模式对它们执行不同的操作。

您没有使用 <math.h>,因此您可以忽略它。

我注意到的另一件事是,在 while 循环中使用 m 变量之前,您没有对其进行初始化。这可能会导致很多问题,因此您应该将其初始化为某个不是有效模式的值,例如 0 或 -1。

当可以使用 if/else 时,您还使用了两个连续的 if 语句。

if (integermode == true) {
    .....
}
if (integermode == false) {
    .....
}

相同
if (integermode == true) {
    .....
} else {
    .....
}

但更难阅读且效率较低,因为您要进行两次比较而不是一次比较。


实施 double/integer 模式

关于您要实现的功能,您可以很好地定义一个具有可能模式的枚举:

typedef enum _datamode {
    INTEGER_MODE,
    DOUBLE_MODE
} data_mode;

然后有一个变量保存当前模式:

data_mode datamode = INTEGER_MODE /* Initializing this to the default mode */

然后根据变量的当前值在计算和输出期间使用整数或双精度数。当然,这可以使用整数而不是 enumtypedef 以更短的方式完成,但我发现这是一种更冗长的方式。

对于输入和结果,您可以使用 union C 类型,它为您在其中指定的最大类型保留内存,并允许您将它们中的任何一个存储在其中。例如:

union io {
    int i;
    double d;
} a, b, result;

声明了三个具有 io 联合类型的变量。这样,您可以根据需要将它们用作整数或双精度数(只要您不混合类型,例如,存储一个整数并将其作为双精度数读取)


完整的工作实施

下面是我对你要做的程序的实现。它可以用更短的方式完成(考虑到处理枚举的开关占总数的相当一部分space),但我认为这是更优雅和冗长的方式。

我尊重你的打印语句和应用程序的流程,尽管我认为它们可能会更好(也许这是你的任务强加给你的东西?)

请借此机会学习,而不仅仅是 copy-paste 代码。

#include <stdio.h>
#include <stdlib.h>

typedef enum _datamode {
    INTEGER_MODE,
    DOUBLE_MODE
} data_mode;

typedef enum _operationmode {
    ADDITION,
    SUBSTRACTION,
    MULTIPLICATION,
    DIVISION,
    TOGGLE,
    EXIT
} operation_mode;

operation_mode ask_mode () {
    int input = -1;
    while (1) {
        printf("Options:\n");
        printf("1 - addition\n2 - subtraction\n3 - multiplication\n4 - division\n5 - toggle calculator type\n6 - exit program\n");
        printf("Please enter your option: ");
        scanf("%i", &input);
        if (input < 1 || input > 6) {
            printf("Invalid option.\n");
        } else {
            switch (input) {
                case 1:
                    return ADDITION;
                case 2:
                    return SUBSTRACTION;
                case 3:
                    return MULTIPLICATION;
                case 4:
                    return DIVISION;
                case 5:
                    return TOGGLE;
                case 6:
                    return EXIT;
                default:
                    exit(EXIT_FAILURE); /* Error must've occurred in order for a different value to be present */
            }
        }
    }
}

union _io {
    int i;
    double d;
};

void get_inputs_integer (int *a, int *b) {
    printf("Enter first term: ");
    scanf("%i", a);    
    printf("Enter second term: ");
    scanf("%i", b);
}

void get_inputs_double (double *a, double *b) {
    printf("Enter first term: ");
    scanf("%lf", a);    
    printf("Enter second term: ");
    scanf("%lf", b);
}

int main (int argc, char **argv) {
    union _io operand1, operand2, result;

    operation_mode o_mode;
    data_mode d_mode = INTEGER_MODE;

    printf("This program implements a calculator.");
    do {
        o_mode = ask_mode();
        if (o_mode == TOGGLE) {
            if (d_mode == INTEGER_MODE) {
                d_mode = DOUBLE_MODE;
                printf("Calculator now on double mode\n");
            } else {
                d_mode = INTEGER_MODE;
                printf("Calculator now on integer mode\n");
            }
        } else if (o_mode != EXIT) {
            if (d_mode == INTEGER_MODE) {
                get_inputs_integer(&operand1.i, &operand2.i);
                switch (o_mode) {
                    case ADDITION:
                        result.i = operand1.i + operand2.i;
                        break;
                    case SUBSTRACTION:
                        result.i = operand1.i - operand2.i;
                        break;
                    case MULTIPLICATION:
                        result.i = operand1.i * operand2.i;
                        break;
                    case DIVISION:
                        result.i = operand1.i / operand2.i;
                        break;
                    default:
                        exit(EXIT_FAILURE); /* Error must've occurred in order for a different value to be present */
                }
                printf("The result is %i\n", result.i);
            } else {
                get_inputs_double(&operand1.d, &operand2.d);
                switch (o_mode) {
                    case ADDITION:
                        result.d = operand1.d + operand2.d;
                        break;
                    case SUBSTRACTION:
                        result.d = operand1.d - operand2.d;
                        break;
                    case MULTIPLICATION:
                        result.d = operand1.d * operand2.d;
                        break;
                    case DIVISION:
                        result.d = operand1.d / operand2.d;
                        break;
                    default:
                        exit(EXIT_FAILURE); /* Error must've occurred in order for a different value to be present */
                }
                printf("The result is %lf\n", result.d);
            }
        }
    } while (o_mode != EXIT);
}