简体   繁体   English

带有堆栈和链表的 C 计算器

[英]Calculator in C with Stack and Linked List

im trying to write a simple postfix calculator that reads the line and performs the calculation using a Stack.我正在尝试编写一个简单的后缀计算器,它读取行并使用堆栈执行计算。 I was wondering if somebody coudl check if is struct's and push function are correnctly implmented.我想知道是否有人可以检查是否正确实现了结构和推送功能。 I would by very greatful for any advice or clues what I need to take in consideration.我会非常感谢我需要考虑的任何建议或线索。 Im a Student of Informatics and that one of my first programms that i'd love to finish before Christmas :)我是信息学的学生,这是我希望在圣诞节前完成的第一个程序之一:)

Can somebody tell me how to pull out just two elements form the top of the stack and not to traverse though whole 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
        }
    }
}

The StackElement堆栈元素

First, I think you meant to begin with a typedef your definition of the StackElement structure like:首先,我认为您打算以 typedef 开始您对 StackElement 结构的定义,例如:

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

Then, the next pointer which is a member of the StackElement structure type points to a StackElement itself: The next node in this singly-linked list.然后,作为StackElement结构类型成员的next指针指向StackElement本身:这个单向链表中的下一个节点。 By the way, this self-referencing declaration is exactly why you cannot omit the structure's tag name and simplifying like this:顺便说一下,这个自引用声明正是你不能省略结构的标签名称并像这样简化的原因:

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

By the way, we can see int data;顺便说一下,我们可以看到int data; chosen here but a float value assigned to it later.此处选择但稍后分配给它的浮点值。

The stack_top pointer stack_top 指针

Next, something doesn't seem right with the following:接下来,以下内容似乎不正确:

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

    }stack_top;

I believe what you intended to do, also supported by your comment above the code, is declare a pointer to a StackElement , specifically one that will be used to always point to the top of the stack.我相信你打算做的,也得到你在代码上方的评论的支持,是声明一个指向StackElement的指针,特别是一个将用于始终指向堆栈顶部的指针。 In that case, since the StackElement type is already declared, you can simply do:在这种情况下,由于已经声明了 StackElement 类型,您可以简单地执行以下操作:

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

If you really want to have another alias for the StackElement* type you can do: typedef StackElement* stackPtr;如果你真的想要StackElement*类型的另一个别名,你可以这样做: typedef StackElement* stackPtr; and then declare the actual variable thus:然后这样声明实际变量:

stackPtr stack_top;

The process function过程函数

The process function has some obvious problems: process函数有一些明显的问题:

  • It is a void function returning the value of an undeclared result variable.它是一个返回未声明result变量值的void函数。 Considering specifying an int or float (whichever you really meant to use) as the return type of the function.考虑指定intfloat (无论您真正打算使用哪个)作为函数的返回类型。

  • In the condition part of the if statement, you need to surround the operator char values between single quotes like this: if (*token == '+') , etc.if语句的条件部分,您需要将运算符字符值括在单引号之间,如下所示: if (*token == '+')等。

  • There is a problem with the curly braces in the if statement. if语句中的花括号有问题。 On the true part, you don't really need to open a brace (which you forgot to close) since you have a single statement to be executed.实际上,您实际上并不需要打开一个大括号(您忘记关闭了),因为您只有一个要执行的语句。 Consider removing the { or closing it before the else part.考虑在else部分之前删除{或关闭它。

  • You declare char &token a few times in the if condition part.您在if条件部分声明char &token几次。 I think you really just meant to use it like my example on the second bullet, above.我认为你真的只是想像我在上面的第二个项目符号中的例子一样使用它。 Likewise, you declare int a twice, when you should only say a = *token;同样,你声明int a两次,而你应该只说a = *token; in the else section.在其他部分。 By the way, if you really meant to declare a char reference (on the function parameter list), you should have probably tagged this question as C++ .顺便说一句,如果您真的想声明一个字符引用(在函数参数列表上),您可能应该将此问题标记为C++ Then you would do a = token , respectively.然后你会分别做a = token EDIT: While I was writing this up a comment on your question appeared explaining more on the difference between &token and *token .编辑:在我写这篇文章的时候,对你的问题的评论出现了,更多地解释了&token*token之间的区别。

  • In fact, having else {} the aforementioned statement and the switch statement that follows it are actually executed even if the token was not an operator.事实上,即使令牌不是运算符,也实际执行了上述语句和后面的 switch 语句的else {}

  • You are dynamically allocating memory for a StackElement but then never doing something with that pointer, temp , while it is in scope.您正在为StackElement动态分配内存,但是在该指针temp处于范围内时,您永远不会对该指针执行任何操作。 After the function returns you have no way to refer to that memory again and it won't be freed until the program terminates.函数返回后,您将无法再次引用该内存,并且在程序终止之前它不会被释放。

This is but a part of the story...这只是故事的一部分……

These were some quick (or that was the idea for my first answer) observations on your code.这些是对您的代码的一些快速(或者这是我的第一个答案的想法)观察结果。 I trust our community will be able to help even more and point out any other mistakes / improvements in your code (and probably mine, too).我相信我们的社区将能够提供更多帮助,并指出您代码中的任何其他错误/改进(也可能是我的)。 Good luck with your implementation of the calculator!祝您使用计算器好运! :-) :-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM