C中的计算器与堆栈和链接列表

时间:2014-12-17 22:01:08

标签: c list stack calculator

我试着编写一个简单的后缀计算器来读取该行并使用Stack执行计算。我想知道是否有人可以检查是否结构和推送功能是完全实现的。我非常感谢任何建议或线索我需要考虑的事项。 我是信息学学生,也是我喜欢在圣诞节前完成的第一个程序之一:)

有人可以告诉我如何从堆栈顶部拉出两个元素,而不是遍历整个堆栈:/

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <malloc.h>
#include <string.h>
#include <math.h>   // Definnes special Float - NAN ("Not A Number")

struct StackElement{
    int data;
    struct element *next;
  }StackElement;


    /*
   Typ stack_top is pointer to the StackElement
*/
typedef struct StackElement* stack_top{
    StackElement* first;

    }stack_top;


/*
    starc
   Lay Element on Stack

   If *stacktop points to NULL, there is no element in the Stack 
*/
void stack_push(stack_top *stacktop, float value)
{
    if(stacktop->first == NULL){
      StackElement->data = value;
      StackElement->next= NULL;
      stack_top->first= *StackElement;
      }

    else{
        StackElement->next = stack_top-> first;
        stack_top->first= *StackElement;  // New first element
        StackElement->data= value;
        }





/*
   Take one element from the stack

   If Stack is empty than set *stacktop = NULL

   , give float NAN back
*/
float stack_pop(stack_top *stacktop)
{
    if(&stacktop==NULL){
       printf("Stack ist leer \n")

    }
    // Hier Code einfügen
    return NAN;
}

/*
   Identyfy Token. Difference few cases:
   - Token is a nummber : lay it on the Stack.
   - Token is an Operator (+, -, *):
       1. Take the two elements from the top of the Stack.
       2. Use the operator.
       3. Lay the result back on the top of the stack.

   Implementiere hier die Rechenoperationen (+, -, *) und lege das
   Ergebnis zurück auf den Stack. Beachte, dass du mit Floatingpointwerten
   arbeitest, z.B. auch negative Kommazahlen.
*/
void process(stack_top *stacktop, char* token)
{   int a, operand1, operand2;
    assert(token != NULL);
    StackElement* temp = malloc(sizeof(StackElement));
    if ( char &token == + ||char &token== - || char &token == * ) == 0 )
    {
        stack_push(stacktop, token)

    else{}
        int a= &token;
       switch(a)
        {

            case '+':
                    result = operand1 + operand2;
                    break;
            case '-':
                    result = operand1 - operand2;
                    break;
            case '*':
                    result = operand1 * operand2;
                    break;

        }
    return result;
  }
}


const int MAX_LINE_LENGTH=1024;
/*
 main() reads the Input line by line and divides it single separate Tokens (linked list).
 Diese Funktion muss nicht geändert werden.
*/
int main(int argc, char** args)
{
    stack_top stacktop = NULL;
    char line[MAX_LINE_LENGTH]; // Input line
    char* token;                // Pointer the current token;

    while ( fgets(line, MAX_LINE_LENGTH, stdin) ) {
        token = strtok(line, " ");

        while (token != NULL) {
            process(&stacktop, token);  // perform Stackoperationen 
            token = strtok(NULL, " ");  // Read new Token
        }

        float result = stack_pop(&stacktop);    // Take Last result from Stack .

        if (stacktop != NULL) { // Mehr Operanden als benötigt angegeben. Fehler.
            while (stacktop != NULL) {
                stack_pop(&stacktop);   //Clean Stack 
            }
            printf("Error\n");
        } else if (result != result) {  // result ist NAN: Berechnung fehlgeschlagen  (z.b. zu wenig Operanden)
            printf("Error\n");
        } else {
            printf("%4.3f\n", result); // Gib Resultat aus
        }
    }
}

1 个答案:

答案 0 :(得分:2)

StackElement

首先,我认为你的意思是从typedef开始,你的StackElement结构定义如下:

typedef struct StackElement {
    int data;
    struct StackElement *next;
} StackElement;

然后,作为 StackElement 结构类型成员的 next 指针指向 StackElement 本身:此单独的下一个节点链接列表。顺便说一下,这个自引用声明正是为什么你不能省略结构的标签名称并简化如下:

typedef struct { /* Unnamed structure here, no "StackElement" this time */
    int data;
    struct StackElement *next; /* Error here, StackElement tag name was never defined */
} StackElement;

顺便说一句,我们可以在此处看到int data;,但稍后会为其分配 float 值。

stack_top指针

接下来,以下情况似乎不对:

    /*
   Typ stack_top is pointer to the StackElement
*/
typedef struct StackElement* stack_top{
    StackElement* first;

    }stack_top;

我相信你想要做的事情,也是你的代码上面的评论所支持的,是声明指向 StackElement 的指针,特别是用于始终指向堆栈顶部的指针。在这种情况下,由于已经声明了StackElement类型,您只需执行:

StackElement *stack_top; /* ... or StackElement *first;     */

如果你真的想要为 StackElement * 类型设置另一个别名,你可以这样做:     typedef StackElement * stackPtr; 然后声明实际变量:

stackPtr stack_top;

过程功能

过程功能有一些明显的问题:

  • 这是一个 void 函数,返回未声明的值 result变量。考虑指定 int float (无论你真正想要的是什么) use)作为函数的返回类型。

  • if语句的条件部分中,您需要包围运算符 char 值 在这样的单引号之间:if (*token == '+')等等

  • 如果if语句,大括号出现问题。在真实的部分,你并不是真的 因为你有一个要执行的语句,所以需要打开一个大括号(你忘了关闭)。 请考虑删除{或在其他部分之前将其关闭。

  • 您在char &token条件部分中声明if几次。我想你真的只是想要 像上面第二个子弹中的例子一样使用它。同样,当你时,你要声明int a两次 应该只在else部分说a = *token;。顺便说一句,如果你真的要宣布一个 char引用(在函数参数列表中),您应该已经标记了这个问题 作为 C ++ 。然后你会分别做a = token。 编辑:当我写这篇文章时,你的问题的评论似乎解释了更多关于 &token*token之间的差异。

  • 实际上,else {}前面提到的语句和后面的switch语句 即使令牌不是运营商,也会被执行。

  • 您正在为 StackElement 动态分配内存,但之后却从不执行某些操作 指针temp,当它在范围内时。函数返回后,您无法引用 再次访问该内存,直到程序终止才会释放它。

这只是故事的一部分......

这些是对您的代码的一些快速(或者我的第一个答案的想法)观察。我相信我们的社区将能够提供更多帮助,并指出代码中的任何其他错误/改进(也可能是我的)。祝你实施计算器好运! : - )