C语言 十进制、八进制和十六进制计算器

643ylb08  于 2022-12-03  发布在  其他
关注(0)|答案(2)|浏览(212)

我想做一个计算器,能够计算十进制数,并能够返回十进制值在各自的二进制,八进制或十六进制表示。
到目前为止,在main方法中,程序读取命令行,我可以通过两种方式调用程序。
第一种方法是使用3个值:
“数字1”“操作员”“数字2”。
第二种方法是使用4个值:
“输出”“number1”“运算符”“number2””所需的数字系统。
其中,对于所需的数制,输出B代表二进制,o代表八进制,h代表十六进制。在这两种方式中,用户应该能够为输入number1和number2输入十进制、八进制和十六进制数。

#include "zahlen.h"
#include <stdio.h>
#include "stringTOint.h"   

int main(int argc, char *argv[]) {
    char o,op,sx[DIGITS+1],sy[DIGITS+1],sz[DIGITS+1];
    int x,y,z;
    char flag_x,flag_y;

    /* 1) Read Commandline */
    if (argc != 4 && argc != 5) {
        printf("Aufruf: %s -o <x> <op> <y> \n",argv[0]);
        return 1;
    } else if(argc == 4) {
        x = stringTOint(argv[1]);
        op = argv[2][0];
        y = stringTOint(argv[3]);
    } else if(argc == 5) {
        o = argv[1][0];
        x = stringTOint(argv[2]);
        op = argv[3][0];
        y = stringTOint(argv[4]);
        if(o != 'b' && o != 'o' && o != 'h') {
            printf("Wrong Operation\n");
            return 1;
        }
    }

    /* 2) Solve the equation */
    if(argc==4) {
        printf("solve: %s %c %s \n", argv[1], op, argv[3]);
        z = solve(x, op, y);
    } else if(argc==5) {
        printf("solve: %s %c %s \n", argv[2], op, argv[4]);
        z = solve(x, op, y);
    }

    /* 3) Calculate the Representation of the wished Numeral System */
    switch(o) {
        case 'b':
            intTObinaer(x, sx);
            intTObinaer(y, sy);
            intTObinaer(z, sz);
            break;

        case 'o':
            intTOoctal(x,sx);
            intTOoctal(y,sy);
            intTOoctal(z,sz);
            break;

        case 'h':
            intTOhexal(x,sx);
            intTOhexal(y,sy);
            intTOhexal(z,sz);
            break;

        default:
            intTObinaer(x, sx);
            intTObinaer(y, sy);
            intTObinaer(z, sz);
            break;
    }

    /* 4) Return the results */
    printf("\n  %s %d\n%c %s %d\n= %s %d\n", sx,x,op,sy,y,sz,z);

    return 0;
}

方法intTObinaer、intTOoctal和intTOhexal的区别仅在于小数被除的基数。

intTObinaer(int i, char str[]) {
    unsigned int zahl = i;
    int j;

    /* Fill Array with zeros */
    int x = 0;
    for (x; x < DIGITS+1; x++) {
        str[x] = '0';
    }

    /*Calculate the Binary representation of the given Decimal integer */
    for (j = DIGITS-1; j > 0; j--) {
        /* This base gets changed to 8 or 16 for octal and hexal representation */
        str[j] = (char) (zahl % 2) + '0';
        zahl = zahl / 2;
        if (zahl == 0) {
            break;
        }
    }

    /* Set the end of the Array */
    str[DIGITS] = '\0';
}

实际的方程在solve方法中求解,其中number1和number2的正确运算由switch case选择,在switch case中,可以通过用户在两个数字之间输入的char op选择不同的情况。

#include <stdio.h>

int solve(int x, char op, int y) {
    int ergebnis = 0;
    switch(op) {
        case '+':
            ergebnis = x + y;
            break;

        case '-':
            ergebnis = x - y;
            break;

        case '*':
            ergebnis = x * y;
            break;

        case '/':
            ergebnis = x / y;
            break;

        case '&':
            ergebnis = x & y;
            break;

        case '|':
            ergebnis = x | y;
            break;

        default:
            printf("Wrong input\n");
    }

    return ergebnis;
}

我现在的问题是,由于用户应该能够输入不同的数字系统(例如十进制、八进制或十六进制),我如何识别不同的数字系统,然后将它们转换成十进制,以便我可以计算结果。然后,这些十进制数字必须转换回用户想要的数字系统。

fjaof16o

fjaof16o1#

看起来您只需要添加两行就可以做到这一点:
#include "stdlib.h"
#define stringTOint(arg) ((int)strtol(arg,NULL,0))
或者更好的方法是,用相应的strtol()调用替换那些stringTOint()调用(当然,还要添加#include)。
strtol()使用与C文字相同的前缀:0为八进制,0x为十六进制,没有十进制前缀。

au9on6nz

au9on6nz2#

我想提出解决这个问题的另一种方法。
您执行的许多解析都可以直接由sscanf函数执行,唯一的情况是二进制情况,需要以不同的方式实现。
该实施遵循3个主要步骤:
1.使用sscanf函数(或二进制值的ConvCharToBin)解析输入,并将值存储在变量ab中;
1.执行运算并将结果存储在res变量中;
1.使用printf解析(或二进制情况下的循环)打印输出结果。
实现如下:

#include<stdio.h>
#include<string.h>

typedef struct stack {
    unsigned char data[32];
    int size;
} stack_t;

int ConvCharToBin(char* input);

int main(int argc, char *argv[]) {

    char numSys = 'd', op;
    char** param = argv;
    int a, b, res;

    param++;

    //error case
    if(argc != 4 && argc != 5) {
        //not a valid input
        printf("Not a valid input");
        return -1;
    }

    if(argc == 5) {
        numSys = param[0][0];
        param++;
    }

    op = param[1][0];

    switch(numSys) {
        case 'b':
            a = ConvCharToBin(param[0]);
            b = ConvCharToBin(param[2]);
            break;

        case 'd':
            sscanf(param[0], "%d", &a);
            sscanf(param[2], "%d", &b);
            break;

        case 'h':
            sscanf(param[0], "%x", &a);
            sscanf(param[2], "%x", &b);
            break;

        case 'o':
            sscanf(param[0], "%o", &a);
            sscanf(param[2], "%o", &b);
            break;

        default:
            //no viable number system
            return -1;
    }

    switch(op) {
        case '+':
            res = a + b;
            break;

        case '-':
            res = a - b;
            break;

        case '/':
            res = a / b;
            break;

        case '*':
            res = a * b;
            break;

        case '&':
            res = a & b;
            break;

        case '|':
            res = a | b;
            break;

        default:
            //no valid operand
            printf("invalid operation\n");
            return -1;
    }

    stack_t tmp;
    tmp.size = 0;
    int i;

    switch(numSys) {
            case 'b':
                while (res) {
                    if (res & 1) {
                        tmp.data[tmp.size] = '1';
                        tmp.size++;
                    } else {
                        tmp.data[tmp.size] = '0';
                        tmp.size++;
                    }
                    res >>= 1;
                }
                for(i = tmp.size - 1; i >= 0; i--) {
                    printf("%c", tmp.data[i]);
                }
                printf("\n");
                break;

            case 'd':
                printf("%d\n", res);
                break;

            case 'h':
                printf("%x\n", res);
                break;

            case 'o':
                printf("%o\n", res);
                break;
        }

    return 0;

}

int ConvCharToBin(char* input) {
    char* idx;
    int res = 0x00000000;

    for(idx = input; idx < input + strlen(input); idx++) {
        res <<= 1;
        if(*idx == '1') {
            res |= 0x00000001;
        }
    }

    return res;
}

sscanf从一个字符串中读取格式化数据(在您的例子中是argv字符串)
可以使用以下语句对此进行解析:

  • %d为十进制;
  • %x为十六进制;
  • %o表示八进制。

不幸的是,没有使用sscanf解析二进制的C标准,所以这是使用stdout单独完成的。
我还要指出,这种实现有两个限制,

  • 输入/输出限制为32位无符号(因此从04294967295),但稍加修改即可扩展;
  • 无需对输入值进行错误检查,这也很容易实现。

相关问题