2016-02-03 11 views
0

Я написал программу, которая преобразует выражения из арифметической нотации infix в постфикс. Нет проблем с этой частью программы. После преобразования программа должна оценить выражение и дать числовой ответ, используя стек.Ошибка сегментации в C: Оценка Infix для Postfix

Проблема возникает в строке 232 при ссылке на push2, что дает ошибку сегментации (SIGSEGV).

Как я могу это решить?

#include <stdio.h> 
#include <stdbool.h> 
#include <ctype.h> 
#include <stdlib.h> 
#include <string.h> 
#define MAX 100 // maximum number of input characters 

bool open_close(char opening, char closing); 
bool check_balanced_par(char * exp, int length); 

struct stack 
{ 
    char my_stack[MAX]; 
    int pointer; 
}; 

struct stack2 
{ 
    float my_stack[MAX]; 
    int pointer; 
}; 

int precedence(char x); 
void push(struct stack *S, char *x); 
char pop(struct stack *S); 
void push2(struct stack2 *S, float *x); 
char pop2(struct stack2 *S); 

int precedence(char x) 
{ 
    if(x == '#') 
     return 0; 
    if(x == '(') 
     return 1; 
    if(x == '+' || x == '-') 
     return 2; 
    if(x == '*' || x == '/') 
     return 3; 
    else 
     return 4; 
} 

void push(struct stack *S, char *x) 
{ 
    S->pointer++; 
    S->my_stack[S->pointer] = *x; 
} 

char pop(struct stack *S) 
{ 
    char data = S->my_stack[S->pointer]; 
    S->pointer--; 
    return data; 
} 

void push2(struct stack2 *S, float *x) 
{ 
    S->pointer++; 
    S->my_stack[S->pointer] = *x; 
} 

char pop2(struct stack2 *S) 
{ 
    char data = S->my_stack[S->pointer]; 
    S->pointer--; 
    return data; 
} 

// checks to see if()/[]/{} is the case 
bool open_close(char opening, char closing) 
{ 
    if (opening == '(' && closing == ')') return true; 
    if (opening == '{' && closing == '}') return true; 
    if (opening == '[' && closing == ']') return true; 
    return false; 
} 

bool check_balanced_par(char * exp, int length) 
{ 
    struct stack S; 
    S.pointer = 0; 
    int i; 
    for(i=0; i<length; i++) 
    { 
     if (exp[i] == '(' || exp[i] == '{' || exp[i] == '[') 
     { 
      S.pointer = S.pointer +1; 
      S.my_stack[S.pointer] = exp[i]; 
     } 
     else if (exp[i] == ')' || exp[i] == '}' || exp[i] == ']') 
     { 
      if(S.pointer == 0 || !open_close(S.my_stack[S.pointer],exp[i])) 
        return false; 
      else 
       S.pointer = S.pointer-1; 
     } 
     else if (exp[i] == '*' || exp[i] == '/' || exp[i] == '+' || exp[i] == '-' || isdigit(exp[i])) 
     { 
      continue; 
     } 
     else 
      return false; // if input is not as expected 
    } 
    if (S.pointer == 0) // checks if stack is empty 
     return true; 
    else 
     return false; 
} 


int main(void) 
{ 
    char c; 
    int size = 0; 
    char arr[MAX]; 
    int o=0; // counter for arr[] 

    printf("Enter an expression to check:\n"); 
    fflush(stdout); 
    fgets(arr, MAX, stdin); 
    arr[strlen(arr)-1] = '\0'; // clears \n from array 
    while((c=arr[o++]) != '\0') 
    { 
     size++; 
    } 

    if(check_balanced_par(arr, size)) 
    { 
     printf("Balanced.\n"); 
     printf("Postfix notation is: "); 

      struct stack S; 
      struct stack *ptr; // pointer to stack 
      ptr = &S; // setting the pointer 
      S.pointer = -1; 
      int z = 0; // counter to traverse input array 
      char output[MAX]; // stores output 
      int out_count = 0; // stores no. of characters of output 

      char x = ' '; 
      char y = '#'; 
      push(ptr, &y); 

      while('\0' != arr[z]) // going through the input array and incrementing z everytime 
      { 
       if(isdigit(arr[z])) // if an operand is found print to screen 
       { 
        output[out_count] = arr[z]; 
        out_count++; 
       } 
       else if(arr[z] == '(') // if (is found push on stack 
       { 
        push(ptr, &arr[z]); 
       } 
       else if(arr[z] == ')') // if) is found pop stack until (is found 
       { 
        while(!(S.my_stack[S.pointer] == '(')) 
        { 
         output[out_count] = pop(ptr); 
         out_count++; 
        } 
        S.pointer--; // pop the extra (
       } 
       else if(arr[z] == '*' || arr[z] == '/' || arr[z] == '+' || arr[z] == '-') 
       { 
        push(ptr, &x); // used for correct output layout 
        while(precedence(S.my_stack[S.pointer]) >= precedence(arr[z])) 
        { 
         // pop stack 
         if(arr[z] == '(' || arr[z] == ')') 
          continue; 
         output[out_count] = pop(ptr); 
         out_count++; 
        } 

        // push arr[z] on stack 
        push(ptr, &arr[z]); 

       } 
       z++; 
      } 

      int j = S.pointer; 
      while(S.my_stack[j] != '#') 
      { 
       if(S.my_stack[j] == '(') 
        continue; 
       output[out_count] = S.my_stack[j]; 
       out_count++; 
       j--; 
      } 

      output[out_count] = '\0'; 
      int k=0; 
      while(output[k] != '\0') // go through output array and print 
      { 
       printf("%c", output[k]); 
       k++; 
      } 

      // start evaluating the postfix format [THIS IS WHERE THE ISSUE IS] 
      struct stack2 T; 
      struct stack2 *ptr2; // pointer to stack 
      ptr2 = &T; // setting the pointer 
      int i=0, l, g; // i counter for output[], l counter for nums[] 
      float a,b; 
      float toPush; 
      float *ptr_toPush; 
      char nums[MAX]; 
      char operator; 
      float total; 

      while(output[i++] != '\0') 
      { 
       if(isdigit(output[i])) 
       { 
        l=0; 
        int y=i; 
        while(output[y] != ' ') // if character is not a space 
        { 
         nums[l] = output[y]; // place character in nums[] 
         y++; 
         l++; 
        } 
        i=y; // setting the counter for output[] to the character we have reached 

        toPush = atof(nums); 
        for(g=0; g<k; g++) 
         nums[g] = '\0'; 

        ptr_toPush = &toPush; 
        push2(ptr2, ptr_toPush); 
       } 
       else if(output[i] == ' ') // if a space is found continue 
       { 
        continue; 
       } 
       else // operator 
       { 
        a = pop(ptr); 
        b = pop(ptr); 
        operator = output[i]; 
        switch(operator) 
        { 
         case '+': 
          total = a+b; 
          push2(ptr2,&total); 
          break; 
         case '-': 
          total = a-b; 
          push2(ptr2,&total); 
          break; 
         case '*': 
          total = a*b; 
          push2(ptr2,&total); 
          break; 
         case '/': 
          total = a/b; 
          push2(ptr2,&total); 
          break; 
         default: printf("Error.\n"); 
        } 
       } 
      } 
      printf("Result is: %d", pop2(ptr2)); 
    } 
    else 
     printf("Not balanced."); 

    return 0; 
} 
+0

Вы никогда не инициализируете стек 'T', прежде чем пытаться нажать на него. –

+0

Это означает, что один из ваших указателей недействителен во время вызова. Вам необходимо выделить память для вашего стека. –

+0

Пожалуйста, смотрите, как создать [mcve]. Нам не нужно видеть весь этот код. Например, вы можете использовать жесткий кодированный вход; в настоящее время мы не знаем, какой ввод вы используете. – user694733

ответ

0

После того, как вы определили ptr2 (и любой другой указатель стека), используйте malloc для правильной настройки. Также держите указатель на вершине стека, чтобы при появлении вы делали ошибку, чтобы убедиться, что вы слишком далеко не выскочили. и чтобы вы могли бесплатно его освободить, когда вам это больше не нужно.