2012-05-09 2 views
0

대학 과제물의 경우 스택을 구현해야합니다. 스택을 구현해야만 제대로 작동 할 수 있다고 생각합니다. 자체적으로 스택을 테스트 할 때 제대로 작동하는 것처럼 보이지만 솔루션의 일부로 사용하면 다르게 작동합니다. 이유는 알 수 없습니다. 누군가 내 실수를 지적 할 수 있습니까? 감사.C로 스택을 구현하면 혼란스러운 결과가 발생합니다.

편집 : "어떻게 다르게 동작합니까?" 덧글이 오는 중이므로 여기 제가 알아 차 렸습니다. 테스트 스택 섹션을 main으로 실행하면 모든 작업이 완벽하게 실행되어 인쇄되지만 main의 두 번째 부분을 실행하고 대신 테스트 부분을 주석 처리하면 프로그램을 강제 실행하려고 할 때 프로그램이 중단됩니다. 스택 - 이전에 실패하지 않은 것.

main.c를 내가 볼

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

struct stackNode { 
    char data; 
    struct stackNode *nextPtr; 
}; 
typedef struct stackNode StackNode; 
typedef StackNode *StackNodePtr; 

typedef enum { 
    false, true 
} t_bool; 

void* emalloc(size_t s) { 
    void* p = malloc(s); 
    if (NULL == p) { 
     fprintf(stderr, "Memory allocation failed.\n"); 
     exit(EXIT_FAILURE); 
    } 
    return p; 
} 

void print_array(char* array, size_t n){ 
    int i; 
    printf("["); 
    for(i = 0; i < n - 1; i++){ 
     printf("%c, ", array[i]); 
    } 
    printf("%c]\n", array[i]); 
} 


// Determine if c is an operator. 
int isOperator(char c) { 
    char ops [6] = {'+', '-', '*', '/', '%', '^'}; 
    int i; 
    for (i = 0; i < 6; i++) 
     if (ops[i] == c) return true; 
    return false; 
} 

int op_priority(char c) { 
    if (c == '+' || c == '-') return 0; 
    else if (c == '*' || c == '/') return 1; 
    else if (c == '^' || c == '%') return 2; 
    return -1; 
} 


// Determine if the precedence of operator1 is less than, equal to, or greater than 
// the precedence of operator2. The function returns -1, 0 and 1, respectively. 
int precedence(char op1, char op2) { 
    int op1_p = op_priority(op1); 
    int op2_p = op_priority(op2); 
    if (op1_p < op2_p) return -1; 
    else if (op1_p > op2_p) return 1; 
    else return 0; 
} 





// Push a value on the stack. 
void push(StackNodePtr *topPtr, char value) { 
    StackNodePtr temp = (StackNodePtr) emalloc(sizeof (StackNode)); 
    temp->data = value; 
    temp->nextPtr = *topPtr; 
    *topPtr = temp; 
} 

// Pop a value off the stack. 
char pop(StackNodePtr *topPtr) { 
    StackNodePtr t = *topPtr; 
    if (NULL != *topPtr) { 
     char c = t->data; 
     *topPtr = t->nextPtr; 
     free(t); 
     return c; 
    } else { 
     printf("Stack is empty.\n"); 
     return '\0'; 
    } 
} 

// Return the top value of the stack without popping the stack. 
char peek(StackNodePtr topPtr) { 
    if (NULL != topPtr) { 
     return topPtr->data; 
    } else { 
     printf("Stack is empty.\n"); 
    } 
} 

// Determine if the stack is empty. 
int isEmpty(StackNodePtr topPtr) { 
    if (NULL == topPtr) return true; 
    return false; 
} 

// Prints the stack 
void printStack(StackNodePtr topPtr) { 
    if (!isEmpty(topPtr)){ 

    StackNodePtr t = topPtr; 
    while (NULL != t) { 
     printf("%c\t", t->data); 
     t = t->nextPtr; 
    } 
    printf("NULL\n"); 
    } else { 
     printf("Stack is empty.\n"); 
    } 
} 

// Convert the infix expression to postfix notation. 
void convertToPostfix(char infix [], char postfix [], int expression_length) { 
    printf("At top of cnvToPostfix\n"); 
    int infix_count = 0; 
    int postfix_count = 0; 

    //////////////////////////////////////////// 
    StackNodePtr *stack; 
    push(stack, '('); 
    printStack(*stack); 
    //////////////////////////////////////////// 

    infix[expression_length] = ')'; 
    while (isEmpty(*stack)) { 
     char current = infix[infix_count++]; 
     if (isdigit(current)) { 
      postfix[postfix_count++] = current; 
     } else if (current == '(') { 
      push(stack, current); 
     } else if (isOperator(current)) { 
      while (true) { 
       char top = peek(*stack); 
       if (isOperator(top) && precedence(current, top) >= 0) { 
        postfix[postfix_count++] = pop(stack); 
       } else { 
        break; 
       } 
      } 
      push(stack, current); 
     } 
     else if (current == ')') { 
      while (true) { 
       char top = peek(*stack); 
       if (top == '(') { 
        pop(stack); 
        break; 
       } else { 
        postfix[postfix_count++] = pop(stack); 
       } 
      } 
     } 
    } 
} 


int main() { 

    printf("Testing stack\n"); 
    printf("Pushing 1, 2, and 3 onto stack, peeking and popping.\n"); 
    StackNodePtr *stack; 
    push(stack, '1'); 
    push(stack, '2'); 
    push(stack, '3'); 
    printf("Printing stack\n\n"); 
    printStack(*stack); 
    printf("Peek: %c\n", peek(*stack)); 
    printf("Pop: %c\n", pop(stack)); 
    printf("Printing stack\n"); 
    printStack(*stack); 


/* 
    printf("Enter the infix expression.\n"); 

    char c; 
    char infix [1024]; 
    int count = 0; 
    while ((scanf("%c", &c)) == 1) { 
     if ((int) c == 10) break; 
     infix[count++] = c; 
    } 

    printf("The original infix expression is:\n"); 
    print_array(infix, count); 


    char postfix [count]; 

    convertToPostfix(infix, postfix, count); 
    printf("The expression in postfix notation is:\n"); 
    print_array(postfix, count); 
*/ 
    return 0; 
} 
+1

어떻게 작동 방식이 다릅니 까? –

+1

예, 모든 질문에 대해 세 가지 중요한 구성 요소 (1) 문제를 나타내는 완전한 컴파일 가능한 샘플, (2) 예상되는 동작 및 (3) 실제 동작. – paxdiablo

+0

답변을 제공하는 방식에 대해 더 자세히 알려면 – MrWuf

답변

4

적어도 하나의 즉각적인 문제 :

당신의 스택의 초기화이다
StackNodePtr *stack; 
push(stack, '1'); 

? 초기화되지 않은 포인터의 사용은 인스턴트 "정의되지 않은 동작"영역입니다.

push 코드를 자세히 보면 현재 항목 앞에 새 항목이 삽입되지만 새로운 항목의 nextPtr 포인터는 이전 (초기화되지 않은) 값으로 포인터가 설정됩니다.

즉, 스택의 마지막 항목은 실제로 NULL을 가리 키지 않습니다.

StackNodePtr *stack; 
push(stack, '('); 

또한 포인터 타입 인 StackNodePtr을 가진 잠재적 혼란, 그리고 stack 해당 유형에 대한 포인터 인 :

+0

어떻게 포인터를 초기화합니까? 또한 왜 그때 그것은 differenly ('main'의 블록을'convertToPostfix'의'push'에 대한 첫 번째 호출과 비교할 것인가?)? – rtheunissen

+0

'StackNodePtr * stack = NULL;'은 당신이 그것을하는 것과 같습니다. –

+0

@ paranoid-android, 다른 변수를 초기화하는 것과 같은 방식으로 포인터를 초기화합니다 :'StackNodePtr * stack = VALUE;'. 'VALUE' 비트를 알아 내면됩니다. 왜 그것이 때때로 작동하는지에 관해서는 UB의 아름다움입니다 :-) – paxdiablo

2

당신은 정말 당신의 스택을 초기화하는 아닙니다. 가능한 많은 수준의 간접 참조가 적용되어야한다는 것을 명확히 밝혀야합니다.

시작하려면, isEmpty에 먼저 새로운 스택을 통과 상상 :

isEmpty 그것이 전달되는 값에 할 무슨
StackNodePtr *stack; 
printf("%d\n", isEmptypush(*stack)); 

? 그 함수에서 stack

StackNodePtr stack = NULL; 
push(&stack, '('); 

다른 용도가 유사 &stackstack, 또는 stack*stack 변경해야합니다

나는 당신이 대신 원하는 것은 생각합니다.

관련 문제