0

演算子 +、-、*、/、および括弧を含む算術式が与えられます (演算子の自然な優先順位が変わる場合と変わらない場合があります)。例は次のようになります: a / b + f – (c + d) * e – a * c. そして、オペランドと演算子を追跡するためにスタック (リンクされたリストとして実装) を使用するように求められます: 私のプログラムがどのように動作するかの例は次のとおりです。

  • a を読み取り、オペランド スタックにプッシュする
  • / を読み取り、オペレーター スタックにプッシュする
  • b を読み取り、オペランド スタックにプッシュする
  • Read +: は / よりも優先順位が低いため、次のようになります。
    • オペランド スタックから 2 つのオペランド (a と b) をポップする
    • pop / オペレータ スタックから
    • サブツリーを作成し、オペランド スタックにプッシュする
    • オペレータ スタックは空なので、+ を押します
  • f を読み取り、オペランド スタックにプッシュする
  • 読み取り - : + と同じ優先順位を持つため、次のようになります。
    • オペランド スタックから 2 つのオペランドをポップする
    • pop operator + オペレータ スタックから
    • 演算子 + をルートとし、2 つのオペランドを左右の子とするツリーを作成します。
    • 作成されたツリーのルートをオペランド スタックにプッシュします。
    • オペレータ スタックが空なので、push - オンにします

私が理解するのが難しい問題は、オペランドの優先順位をどのように区別できるかです!

私が書いたコードの不完全なバージョンは次のとおりです。

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

typedef struct btnode Btree;
typedef struct node s_Node;

struct btnode {
    char info; 
    Btree *left; 
    Btree *right;
};


struct node {
    char element;
    s_Node*next;
}; 

typedef struct{
    s_Node *top_stack;
} stack_t; 

int IsOperator(char c);

main () {
    FILE* fp;
    stack_t operands;
    stack_t operators;
    char c;
    operands=NewStack();
    operators=NewStack();
    fp= fopen ("Myfile.txt", "r");
    if (fp== NULL)
        printf ("   FILE COULD NOT BE OPENED");
    else
    {
        c=getc(fp);
        while (!feof (fp))
        {
            if ( c== ' ');
            else 
            {
                printf ("Here is your character: %c\n", c);
                if (IsOperator (c))
                    Push (c, &operands);
                else if ( isalpha (c))


            }
        c=getc(fp);
        }
    }
}

int IsOperator(char c)
{   
    switch(c)
    {
        case '+':
        case '-':
        case '/':
        case '*':
        return 1;
        default:
        return 0;
    }
} 

stack_t NewStack()
{
    stack_t *n_stack;
    n_stack=(stack_t*)malloc(sizeof(stack_t));
    n_stack->top_stack=NULL;
    return (*n_stack);  
}

int Push(char e, stack_t *q)
{       
    s_Node *nn;
    nn= (s_Node*)malloc(sizeof(s_Node));

    if(Full(*q))
    {
        printf("\n\t Stack is Full !! \n\n");
        return 0;   // return 0 if enstack NOT successful
    }
    else 
    { 
        nn->element=e; // Storing the elemnt read inside the the new node
        nn->next=q->top_stack; // Pointing the new node to the top of the stack
        q->top_stack=nn; // Changing the top of the stack
        return 1;
    }
}

前もって感謝します!

4

1 に答える 1

5

使用しているアルゴリズムでは、オペランドに優先順位はありません。ただし、ボトムアップ シフトリデュース パーサーでは、@WhozCraig が以下のこの投稿のコメントで述べたように優先順位があります。

オペランドは常にオペランド スタックにプッシュされ、ポップ アウト 2 され、演算子で計算されてから、単一のオペランドとしてオペランド スタックに再度プッシュされます。

数式の場合: a / b + f – (c + d) * e – a * c

  • a
  • pushオペランドスタックへ
  • オペランド: a
  • オペレーター:

  • /

  • pushオペレータースタックへ
  • オペランド: a
  • 演算子: /

  • b

  • pushオペランドスタックへ
  • オペランド:ab
  • 演算子: /

  • +

  • +<= /-> pop /, a & b -> a / b -> オペランド スタックにプッシュ
  • +オペレータースタックにプッシュ
  • オペランド: (a / b)
  • 演算子: +

  • オペランド スタックへのプッシュ
  • オペランド: (a/b) f
  • 演算子: +

  • -

  • -<= +-> pop +, (a/b) & f -> (a/b) + f -> オペランド スタックにプッシュ
  • オペランド: ((a/b)+f)
  • オペレーター: -

  • (

  • オペレータースタックにプッシュ
  • オペランド: ((a/b)+f)
  • 演算子: - (

  • c

  • オペランド スタックへのプッシュ
  • オペランド: ((a/b)+f) c
  • 演算子: - (

  • +

  • オペレータースタックにプッシュ
  • オペランド: ((a/b)+f) c
  • 演算子: - ( +

  • d

  • オペランド スタックへのプッシュ
  • オペランド: ((a/b)+f) cd
  • 演算子: - ( +

  • )

  • 「(」がポップされるまで、スタック内のすべての演算子を 1 つずつポップし、2 つのオペランドで計算します
  • -> pop +, c & d -> c + d -> オペランド スタックにプッシュ
  • オペランド: ((a/b)+f) (c+d)
  • 演算子: - (
  • -> pop (, オペレータ スタックのポップを停止
  • オペランド: ((a/b)+f) (c+d)
  • オペレーター: -

  • *

  • *>-オペレータースタックにプッシュ
  • オペランド: ((a/b) + f) (c + d)
  • 演算子: - *

  • e

  • *>-オペランド スタックにプッシュ
  • オペランド: ((a/b) + f) (c + d) e
  • 演算子: - *

  • -

  • -<= *pop *, (c + d) & e -> (c + d) * e -> オペランド スタックにプッシュ
  • オペランド: ((a/b)+f) ((c+d)*e)
  • オペレーター: -
  • -<= -pop -, ((a/b)+f) & ((c+d)*e) -> ((a/b)+f) - ((c+d)*e) -> オペランドにプッシュスタック
  • プッシュ - オペレータ スタックへ
  • オペランド: (((a/b)+f)-((c+d)*e))
  • オペレーター: -

  • a

  • オペランド スタックへのプッシュ
  • オペランド: (((a/b)+f)-((c+d)*e)) a
  • オペレーター: -

  • *

  • *>-オペレータースタックにプッシュ
  • オペランド: (((a/b)+f)-((c+d)*e)) a
  • 演算子: - *

  • c

  • オペランド スタックへのプッシュ
  • オペランド: (((a/b)+f)-((c+d)*e)) ac
  • 演算子: - *

  • 行の終わり

  • スタック内のすべての演算子を 1 つずつポップする
  • pop *, a & c -> (a*c) -> オペランド スタックにプッシュ
  • オペランド: (((a/b)+f)-((c+d)*e)) (a*c)
  • オペレーター: -
  • pop -, (((a/b)+f)-((c+d)*e)) & (a*c) -> (((a/b)+f)-((c+d)* e)) - (a*c) -> オペランド スタックにプッシュ
  • オペランド: ((((a/b)+f)-((c+d)*e))-(a*c))
  • オペレーター:

結果: ((((a/b)+f)-((c+d)*e))-(a*c))

于 2012-12-08T14:10:39.803 に答える