带十进制、八进制和十六进制数的计算器

Calculator with Decimal, Octal and Hexal Numbers

我想制作一个计算器,它能够用十进制数进行计算,并且能够 return 十进制值各自的二进制、八进制或十六进制表示形式。

到目前为止,程序在 main 方法中读取命令行,我可以通过两种方式调用程序。

第一种方式是使用 3 个值:

"number1" "operator" "number2".

第二种方式是使用 4 个值:

"wished numeral system for the output" "number1" "operator" "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] = '[=11=]';
}

实际方程在 solve 方法中求解,其中 number1 和 number2 的正确操作由 switchcase 选择,其中不同的情况可以通过用户在两个数字之间输入的字符操作来选择。

#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;
}

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

看来您只需要添加两行即可:

#include "stdlib.h"

#define stringTOint(arg) ((int)strtol(arg,NULL,0))

或者更好的是,将 stringTOint() 的那些调用替换为相应的 strtol() 调用(当然还要添加 #include)。

strtol() 使用与 C 文字相同的前缀:0 表示八进制,0x 表示十六进制,没有前缀是十进制。

我想建议另一种方法来解决这个问题。

您执行的许多解析都可以直接由 sscanf 函数执行,唯一的情况是需要以不同方式实现的二进制情况。

实施遵循 3 个主要步骤:

  1. 使用 sscanf 函数(或 ConvCharToBin 二进制值)解析输入并将值存储在变量 ab;
  2. 执行运算并将结果存储在res变量中;
  3. 使用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.

分开完成的

我还要指出这个实现有两个限制

  • Input/output 限制为 32 位无符号(因此从 04294967295),但稍作修改就可以扩展;
  • 没有对输入值进行错误检查,这也很容易实现。