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

时间:2018-11-27 13:00:31

标签: c binary hex octal

我想制造一个能够使用十进制数字进行计算并能够以其各自的二进制,八进制或六进制表示形式返回十进制值的计算器。

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

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

  

“数字1”“运算符”“数字2”。

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

  

“用于输出的伪数字系统”“ number1”“运算符”“ number2”。

对于希望的数字系统,输出b代表二进制,o代表八进制,h代表六进制。通过两种方式,用户都应该能够为输入数字1和数字2输入十进制,八进制和十六进制数字。

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

实际的方程式通过求解方法求解,其中数字1和数字2的正确运算由一个切换用例选择,其中用户可以在两个数字之间输入的字符操作选择不同的大小写。

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

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

2 个答案:

答案 0 :(得分:1)

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

#include "stdlib.h"

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

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

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

答案 1 :(得分:0)

我想提出另一种解决此问题的方法。

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

实施过程分为三个主要步骤:

  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可以分开解析。

我还要指出,此实现有两个局限性

  • 输入/输出限制为32位无符号(因此从04294967295),但是可以进行一些细微的修改来扩展它;
  • 无需对输入值进行错误检查,这也可以轻松实现。