Калькулятор с десятичными, восьмеричными и шестнадцатеричными числами - PullRequest
0 голосов
/ 27 ноября 2018

Я хочу создать калькулятор, способный вычислять с десятичными числами и возвращать десятичные значения в соответствующих двоичных, восьмеричных или шестнадцатеричных представлениях.

Пока что в основном методе программа читаеткомандная строка, и я могу вызвать программу двумя способами.

Первый путь будет с 3 значениями:

"number1" "operator" "number2".

А второй путь будет с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';
}

Фактическое уравнение решается в методе решения, где правильная операция для числа 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 голосов
/ 27 ноября 2018

Я хотел бы предложить другой подход к этой проблеме.

Многие выполняемые вами разборы могут выполняться непосредственно с помощью функции sscanf, единственный случай - двоичный случай, который необходимо реализовать по-другому..

Реализация состоит из 3 основных этапов:

  1. Анализировать ввод с помощью функции sscanf (или ConvCharToBin для двоичных значений) и сохранять значения в переменных a и b;
  2. Выполните операцию и сохраните результат в переменной res;
  3. Распечатайте выходной результат, используя синтаксический анализ printf (или цикл для двоичного файлаcase).

Реализация будет выглядеть следующим образом:

#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 для восьмеричного.

К сожалению, не существует стандарта C для разбора двоичного файла.используя sscanf, так что это делается отдельно, используя stdout.

Я также хотел бы отметить, что эта реализация имеет два ограничения:

  • Вход / выход ограничен 32-битным беззнаковым(от 0 до 4294967295), но с некоторыми незначительными изменениями его можно расширить;
  • Нет проверки ошибок для входных значений, это также может быть легко реализовано.
0 голосов
/ 27 ноября 2018

Похоже, вам нужно всего лишь добавить две строки, чтобы сделать это:

#include "stdlib.h"

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

Или еще лучше заменить эти вызовы stringTOint() с соответствующими strtol() вызовами (и, конечно, с добавлением #include).

strtol() использует те же префиксы, что и для литералов C: 0 для восьмеричного, 0x для шестнадцатеричного, без префиксаявляется десятичным.

...