Делаем калькулятор на c, как рассчитать более 2 чисел - PullRequest
0 голосов
/ 02 января 2019

Мне нужно сделать калькулятор на языке c, в котором программа читает математическую операцию в первой строке и печатает результат ее в следующей строке.Также сообщение об ошибке должно быть написано, если в математической операции есть символы, которые не являются числами.Сейчас моя программа читает только одну математическую операцию в одной строке (например, 2 + 5).Любые идеи, как он может читать больше операций в одну строку?(напр. 2 + 5 + 7 + 8) Мой код следующий:

#include <stdio.h>

int main(void) {
    int ch;
    int input1 = 0, input2 = 0, flag = 0, flag1 = 0;
    char oper;
    int i = 1;
    while ((ch = getchar()) != EOF){
        int result = 0;
        if (ch != '\n'){ /* If user didnt change line */
            if (ch >= '0' && ch <= '9'){ /* Checks if ch is a number */
                if(flag == 0) /* flag is used to change to the second number */
                    input1 = input1*10 + ch - '0'; /* Converts ASCII to decimal */
                else
                    input2 = input2*10 + ch - '0';  /* Converts ASCII to decimal*/
            }
            if (ch == '+' || ch == '-' || ch == '*'){ /* Operator has been detected */
                oper = ch;
                flag = 1;
            }
            if (ch >= 'A'){
                flag1 = 1; /* flag1 is used to determine if a non-number character was written */
            }   
        }
        else{
            switch(oper){
                case '+': /* if operator is "+" add the numbers */
                    result = input1 + input2;
                break;
                case '-': /* if operator is "-" subtract the numbers */
                    result = input1 - input2;
                break;
                case '*': /* if operator is "*" multiply the numbers */
                    result = input1 * input2;
                break;      
            }
            if (flag1 == 0){
                printf("Result %d: %d\n", i, result);
                i++;
                input1 = 0;
                input2 = 0;
                flag = 0;
            }
            else if (flag1 == 1){
                printf("Result %d: Error!\n", i);
                i++;
                input1 = 0;
                input2 = 0;
                flag = 0;
                flag1 = 0;
            }
        }
    }
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 02 января 2019

Я нашел это хорошее упражнение для себя = D Части предложений:

  • Конечный автомат может помочь с получением ввода
  • В этом случае (калькулятор) связанного списка должно быть достаточно для облегчения нескольких операций
  • заполнять список по мере сбора входных данных, а затем очищать список в порядке приоритета оператора

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

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

#define MAX_INPUT_SIZE 1000;
struct Node
{
    char operator;
    int result;
    struct Node* left;
    struct Node* right;
};

enum InputState{
    START = 0,
    NUMBER,
    OPERATOR
    };

void pushNodeToList( struct Node**head, struct Node**tail, char op, int result)
{
    struct Node* nodePtr = malloc(sizeof(*nodePtr));
    nodePtr->operator = op;
    result = result;
    if(!head)
    {
        *head = nodePtr;
        *tail = nodePtr;
        nodePtr->left = 0;
        nodePtr->right = 0;
    }
    else{
        nodePtr->left = *tail;
        (*tail)->right = nodePtr;
        *tail = nodePtr;
    }
}

void calculateNode( struct Node* nodePtr)
{
    if(nodePtr->left != 0 && nodePtr->right != 0)
    {
        if(nodePtr->left->operator == 'n' && nodePtr->right->operator == 'n' )
        {
            //calculate result
            switch(nodePtr->operator)
            {
                case '+':
                    nodePtr->result = nodePtr->left->result + nodePtr->right->result;
                    break;
                case '-':
                    nodePtr->result = nodePtr->left->result - nodePtr->right->result;
                    break;
                case '*':
                    nodePtr->result = nodePtr->left->result * nodePtr->right->result;
                    break;
                default:
                    printf("Calculation Error: %d \n", 5);
                    return;

            }
            //change type of node to 'n'
            nodePtr->operator == 'n';

            //reduce the numbers consumed
            struct Node* tempLeft = nodePtr->left;
            struct Node* tempRight = nodePtr->right;
            nodePtr->left = tempLeft->left;
            nodePtr->right = tempRight->right;
            free(tempLeft);
            free(tempRight);
        }
        else
        {
            printf("Calculation Error: %d \n", 4);
            return;
        }
    }
    else{
        printf("Calculation Error: %d \n", 3);
        return;
    }
}

int main(void) {

int ch;
struct Node* head = 0;
struct Node* tail = 0;

//have a state machine to handle the logics related to parsing input
int num = 0;
enum InputState mState = START;

int i = 1;
while ((ch = getchar()) != EOF)
{
    switch(mState)
    {
        case START:
            if (ch >= '0' && ch <= '9'){
                mState = NUMBER;
                num = 0;
                //initialize state to number
            }
            else if(ch == '+' || ch == '-' || ch == '*'){
                mState = OPERATOR;
                //initilize state to operator
            }
            else{
                //your error code
                printf("Input Error: %d \n", 1);
                return 0;
            }
        break;
        case NUMBER:
            if (ch >= '0' && ch <= '9'){
                num = num * 10 + ch - '0';
            }
            else if(ch == '+' || ch == '-' || ch == '*'){
                mState = OPERATOR;
                //we just got a number recorded
                pushNodeToList(&head,&tail,'n',num);//'n' for number
            }
            else{
                printf("Input Error: %d \n", 2);
                return 0;
            }
        break;
        case OPERATOR:
            if (ch >= '0' && ch <= '9'){
                mState = NUMBER;
                num = ch - '0';
            }
            else if(ch == '+' || ch == '-' || ch == '*'){
                pushNodeToList(&head,&tail,ch,0);//push in operator
            }
            else{
                printf("Input Error: %d \n", 3);
                return 0;
            }
        break;
    }
}
//terminal condition to push-in last number
if(mState == NUMBER)
{
    pushNodeToList(&head,&tail,'n',num);//'n' for number
}

//higher prioriety operation
struct Node* workingPtr = head;
while(workingPtr !=tail)//assuming the last input is number (not operator)
{
    if(workingPtr->operator == '*')
    {
        calculateNode(workingPtr);
    }
}
//lower prioriety operations
workingPtr = head;
while(workingPtr !=tail)
{
    if(workingPtr->operator == '+' || workingPtr->operator == '-' )
    {
        calculateNode(workingPtr);
    }
}
//print result
if(head == tail && head->operator == 'n')
{
    printf("Result : %d\n", head->result);
}
else
{
    printf("Error: %d \n", 7);
    return 0;
}


return 0;
}
0 голосов
/ 02 января 2019

Вы можете использовать префиксную нотацию для облегчения расчета.
У вас есть много онлайн-материалов и код для обозначения префикса инфикса.
Основная идея заключается в том, что ваш ввод (например, (1 + 2) * (3 * 4)), который представляет инфиксную запись, может быть преобразован в префиксную запись (* + 12 * 34). Используйте Структура данных стека для расчета заданной структуры префикса.

EVALUATE_PREFIX (STRING):

Допустим, у вас есть: * + 12 * 34 , как в нашем предыдущем примере.

  1. Поместите указатель в конец выражения, чтобы он указывал на число 4 в нашем примере, а затем прочитайте символ.
  2. Если символ указателя является операндом, переместите его в стек.
  3. Если символ в указателе является оператором, извлекает два элемента из стека. Управляйте этими элементами в соответствии с оператором и возвращайте результат обратно в стек.
  4. Уменьшить указатель на 1 и перейти к шагу 2., если в выражении остались отсканированные символы.
  5. Когда больше не осталось символов результат сохраняется в верхней части стека, поэтому просто верните его.

Я предлагаю вам взглянуть на префиксные, инфиксные и постфиксные выражения. Это не займет много времени, чтобы понять это, и это должно обеспечить хорошее решение вашей проблемы. Надеюсь, поможет. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...