计算器使用C中的堆栈 [英] Calculator in C using stack

查看:286
本文介绍了计算器使用C中的堆栈的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建在C计算器,它可以与优先级计算得到正确的结果像这些例子:

I'm trying to create a calculator in c, which can calculate with priority and get right results for examples like these:

((5 + 5)/ 3)* 3) - > 9

((1 + 2)* 3) - > 9

这些例子我在下面code可以计算。但是,对于这样的事情

These examples my code below can calculate. But for something like this

(2 + 5)*(2 + 5),我的程序给出错误的答案。

(2+5) * (2+5), my program gives wrong answer.

我使用2堆栈。一个用于操作员和一个用于数字。它的主要原理是:结果
如下:

I'm using 2 stacks. One for operators and one for numbers. It works on this principle:
follows:

((4 - 2)* 5)+ 3 - >的正常缀前pression:的结果
+ * - 4 2 5 3

((4 - 2) * 5) + 3 --> normal infix expression:
+ * - 4 2 5 3

伪code:

Read + (an operation), push it onto the stack,  
Read * (an operation), push it onto the stack,  
Read - (an operation), push it onto the stack,  
Read 4 (a number), the top of the stack is not a number, so push it onto the     stack.  
Read 2 (a number), the top of the stack is a number, so pop from the stack     twice, you get 4 - 2, calculate it (2), and push the result (2) onto the stack.      
Read 5 (a number), the top of the stack is a number, so pop from the stack twice, you get 2 * 5, push the result (10) onto the stack.  
Read 3 (a number), the top of the stack is a number, so pop from the stack twice, you get 3 + 10, push the result (13) onto the stack.  
Nothing left to read, pop from the stack and return the result (13).  

实际code:

#include <stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 102

typedef struct
{
    char stk[MAXSIZE];
    int top;
}STACK;

typedef struct stack
{
    int stk[MAXSIZE];
    int itop;
}INT_STACK;

STACK s;
INT_STACK a;
void push(char);
char  pop(void);
void display(void);

int main()
{
  a.itop = 0;
  char string[MAXSIZE],vyb,vyb2;
  int cislo1,cislo2,vysledok;

  while (gets(string) != NULL){
    for(int j = strlen(string); j > 0; j--){
      if(string[j] == '*' || string[j] == '/' || string[j] == '+' || string[j] == '-')
        push(string[j]);
    }

    //display();
    for(int j = 0; j < strlen(string); j++){
      if(isdigit(string[j])&&!(a.itop)){
        //display();
        char pomoc[2];
        pomoc[0] = string[j];
        pomoc[1] = '\0';
        int_push(atoi(pomoc));
      }
      else if(isdigit(string[j])&&(a.itop)){
         cislo1 = int_pop();
         vyb2 = pop();
         char pomoc[2];
         pomoc[0] = string[j];
         pomoc[1] = '\0';
         cislo2 =  atoi(pomoc);
         if(vyb2 == '+')
            vysledok = cislo1+cislo2;
         else if(vyb2 == '-')
            vysledok = cislo1-cislo2;
         else if(vyb2 == '*')
            vysledok = cislo1*cislo2;
         else if(vyb2 == '/')
            vysledok = cislo1 / cislo2;
         //printf("  v   %d",vysledok);
         int_push(vysledok);
      }
    }
    printf("%d\n",int_pop());
  }
}

/*  Function to add an element to the stack */
void push (char c)
{
    s.top++;
    s.stk[s.top] = c;
    //printf ("pushed element is = %c \n", s.stk[s.top]);
}

/*  Function to delete an element from the stack */
char pop ()
{
    char num = s.stk[s.top];
   // printf ("poped element is = %c\n", s.stk[s.top]);
    s.top--;
    return(num);
}

int empty()
{
    if (s.top == - 1)
    {
        printf ("Stack is Empty\n");
        return (s.top);
    }
    return 1;
}

void display ()
{
    int i;
    if (!empty)
    {
        printf ("Stack is empty\n");
        return;
    }
    else
    {
        printf ("\n The status of the stack is \n");
        for (i = s.top; i >= 0; i--)
        {
            printf ("%c\n", s.stk[i]);
        }
    }
    printf ("\n");
}

void int_push (int c)
{
    a.itop++;
    a.stk[a.itop] = c;
    //printf ("pushed element is = %d \n", a.stk[a.itop]);
}

/*  Function to delete an element from the stack */
int int_pop ()
{
    int num = a.stk[a.itop];
   // printf ("poped element is = %d\n", a.stk[a.itop]);
    a.itop--;
    return(num);
}

有没有其他的方法来创建优先计算器,它可以提供良好的答案?结果
感谢您回应

Is there any other way to create a calculator with priority, which can give good answers?
Thanks for your respond

推荐答案

把断点 - 你会得到下面的前pression:
+ + * 2 5 2 5 。这样做的问题,是你的跨preTER被interpeting这是(2 + 5 + 2)* 5 而不是(2 + 5 )*(2 + 5)

Put breakpoints - you'll get the following expression: + + * 2 5 2 5. The problem with that, is your interpreter is interpeting this as (2+5+2)*5 instead of (2+5) * (2+5).

那么,你可能想知道如何解决这个问题。有没有简单的单一解决方案 - 你既可以解决自己的内部preTER或建立一个全新的技工,因为你的方式建立的前pressions只是不能处理更多然后一对parthesises的

Well then, you might be wondering how to solve this. There's no simple single solution - you could either fix your own interpreter or build a whole new mechanic, because the way you build expressions just can't handle more then one pair of parthesises.

例如,您可能希望甚至建设前pression seperatley,可能使用递归的parenthesiseception的情况下才来计算parnthesises所有的值 - 但是如果你真的选择使用这种方法,你可能想改变你完全除权pressions的工作方式,因为这是一种不同的方法。

For example, you may want to calculate all the values in parnthesises before even building the expression seperatley, possibly using recursion in the case of parenthesiseception - however if you actually choose to use that method, you might want to change the way you work with the expressions entirely, because that's a different approach.

如果你需要我展示实际code的例子来解释这个进一步的使用所做的code的部分,只要求它,我会编辑,并提供你所需要的。

If you need me to show actual code examples to explain this further using parts of the code you made, just ask for it and i'll edit and provide what you need.

无论哪种方式,我真的劝你查找与一般的跨preters工作 - 你真的可以学到很多有关分析字符串,并与不同的输入工作,人们甚至没有类似的东西给你用计算器<一个HREF =htt​​p://groups.engin.umd.umich.edu/CIS/course.des/cis400/java/calc.html相对=nofollow> 之前

Either way, I really advise you to look up working with interpreters in general - you could really learn a lot about analysing strings and working with different inputs, and people even did similar stuff to yours with calculators before

修改:你问的例子,所以在这里你去 - 这是使用递归完全不同的方法的例子。这样一来,你处理一对parenthesises的同时,这样的话你不会有你现在做的问题。注 - 我在(pretty多复制粘贴从线程编辑和一些个人意见)立足这个来源是从codereview堆栈交换,你可以看到它的here
 如果你intrested。

EDIT: you asked for examples, so here you go - this is an example of a completely different method using recursion. This way, you handle a single pair of parenthesises at a time, and thus you won't have the problem you currently do. Note - the source i'm basing this on ( pretty much copy-pasted with edits from the thread and some personal comments ) is from codereview on stack exchange, you can see it here if you're intrested.

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

void getInput(char * in) {
 printf("> ");
 fgets(in, 256, stdin);
}

int isLeftParantheses(char p) {
if (p == '(') return 1;
else return 0;
}

int isRightParantheses(char p) {
if (p == ')') return 1;
else return 0;
}

int isOperator(char p) {
if (p == '+' || p == '-' || p == '*' || p == '/') return p;
else return 0;
}

int performOperator(int a, int b, char p) {
 switch(p) {
    case '+': return a+b;
    case '-': return a-b;
    case '*': return a*b;
    case '/':
        if (b == 0) { printf("Can't divide by 0, aborting...\n"); exit(1); }  // now we dont want the world to expload here do we.
        return a/b;
    default:
       puts("Bad value in switch.\n"); // A replacement which was mentioned in the thread- better have a default response just in case something goes wrong.
       break;
 }
return 0;
 }


char isDigit(char p) {
if (p >= '0' && p <= '9') return 1;
else return 0;
}

int charToDigit(char p) {
if (p >= '0' && p <= '9') return p - '0';
else return 0;
}

int isNumber(char * p) {
while(*p) {
    if (!isDigit(*p)) return 0;
    p++;
}
return 1;
}

int len(char * p)
{
 return (int) strlen(p); // This was bugged in the source, so I fixed it like the thread advised.
}

int numOfOperands(char * p) {
int total = 0;
while(*p) {
    if (isOperator(*p)) total++;
    p++;
}
return total+1;
}

int isMDGRoup(char *p)
{

for(; *p; p++) // used to be a while loop in the source, but this is better imho. more readable, also mentioned on the thread itself.
{
    if (!isDigit(*p) && *p != '/' && *p != '*') return 0;
}
return 1;
}
int getLeftOperand(char * p, char * l) {
// Grab the left operand in p, put it in l,
//and return the index where it ends.
int i = 0;

// Operand is part of multi-*/ group
if (isMDGRoup(p)) {
    while(1) {
        if (*p == '*' || *p == '/') break;
        l[i++] = *p++;
    }
    return i;
}

// Operand is in parantheses (so that's how you write it! sorry for my bad english :)
if(isLeftParantheses(*p)) {
    int LeftParantheses = 1;
    int RightParantheses= 0;
    p++;
    while(1) {
        if (isLeftParantheses(*p))  LeftParantheses++;
        if (isRightParantheses(*p)) RightParantheses++;

        if (isRightParantheses(*p) && LeftParantheses == RightParantheses)
            break;
        l[i++] = *p++;
    }
    // while (!isRightParantheses(*p)) {
    //  l[i++] = *p++;
    // }
    l[i] = '\0';
    return i+2;
}

// Operand is a number
while (1) {
    if (!isDigit(*p)) break;
    l[i++] = *p++;
}
l[i] = '\0';
return i;
}

int getOperator(char * p, int index, char * op) {
*op = p[index];
return index + 1;
}

int getRightOperand(char * p, char * l) {
// Grab the left operand in p, put it in l,
//and return the index where it ends.
while(*p && (isDigit(*p) || isOperator(*p) ||
             isLeftParantheses(*p) || isRightParantheses(*p))) {
    *l++ = *p++;
}
*l = '\0';

return 0;
}

int isEmpty(char * p) {
// Check if string/char is empty
if (len(p) == 0) return 1;
else return 0;
}

int calcExpression(char * p) {
// if p = #: return atoi(p)
//
// else:
//  L = P.LeftSide
//  O = P.Op
//  R = P.RightSide
//  return PerformOp(calcExpression(L), calcExpression(R), O)

// ACTUAL FUNCTION

// if p is a number, return it
if (isNumber(p)) return atoi(p);

// Get Left, Right and Op from p.
char leftOperand[256] = ""; char rightOperand[256]= "";
char op;

int leftOpIndex   = getLeftOperand(p, leftOperand);
int operatorIndex = getOperator(p, leftOpIndex, &op);
int rightOpIndex  = getRightOperand(p+operatorIndex, rightOperand);

printf("%s, %c, %s", leftOperand, op, rightOperand);
getchar();

if (isEmpty(rightOperand)) return calcExpression(leftOperand);

return performOperator(
    calcExpression(leftOperand),
    calcExpression(rightOperand),
    op
);
}

int main()
{
char in[256];
while(1) {
    // Read input from user
    getInput(in);
    if (strncmp(in, "quit", 4) == 0) break;

    // Perform calculations
    int result = calcExpression(in);
    printf("%d\n", result);
}
}

这篇关于计算器使用C中的堆栈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆