Lỗi khi cài đặt stack bằng con trỏ

chào mọi người. đoạn code dưới đây mô tả việc chuyển biểu thức trung tố sang hậu tố. em cài đặt stack bằng con trỏ (em chưa học link list) và khi chạy đến dòng stack[top]=value trong hàm Push thì bị báo lỗi “program received signal SIGSEGV, Segmentation fault”. mọi người cho em hỏi đây là lỗi gì, nguyên nhân lỗi và cách sửa. em cảm ơn.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
short IsEmpty(int *top){
    if (*top==-1) return 1;
    return 0;
}
short IsFull(int *top, int capacity){
    if (*top == capacity-1) return 1;
    return 0;
}
void Push(int *top, int capacity, char *stack, char value){
    if (IsFull(top, capacity)==1) printf("stack overflow\n");
    else{
        ++*top;
        stack[*top]=value;
    }
}
char Pop(int *top, int capacity, char *stack){
    if (IsEmpty(top)==1) printf("stack underflow\n");
    else{
        char c=stack[*top];
        --*top;
        return c;
    }
}
char pick(int *top, char *stack){
    return stack[*top];
}
void delete(char *expression, int *capacity, int k){
    --*capacity;
    for (int i = k; i < *capacity; i++)
    {
        expression[i]=expression[i+1];
    }
    
}
void add(char *expression, int *capacity, int k, char item){
    ++*capacity;
    for (int i = *capacity; i > k; i--)
    {
        expression[i]=expression[i-1];
    }
    expression[k]=item;
    
}
void convert_to_postfix(char *expression, char *stack, int capacity, int *top){

    for (int i = 0; i < strlen(expression); i++)
    {
        if (expression[i] == '+'||'-'||'*'||'/'||'('){
            capacity++;                                       
            stack=(char *)realloc(stack, capacity);           
            Push(&top, capacity, stack, expression[i]);
            delete(expression, &capacity, i); 
        }
        else if (expression[i] == ')'){
            while (stack[i] != '(')
            {
                printf("%c",Pop(top, capacity, stack));
            }
            --*top;
        }
        else printf("%c",expression[i]);
        
        
    }
}
int main(){
    int top=-1;
    int capacity=0;
    char *stack=NULL;
    char *expression=(char *)malloc(100*sizeof(char));
    
    printf("import expression: "); fgets(expression, 101, stdin);
    
    convert_to_postfix(expression, stack, capacity, &top);
    
    free(stack);
    free(expression);
    return 0;
}
3 Likes

like cái code nhìn đẹp nhỉ :rofl:

5 Likes

Qua thớt ta thấy được giá trị của encapsulation :smiley:

Đầu tiên là stack bạn ko có mem :smiley:NULL. Vả lại câu này không như bạn nghĩ.

5 Likes

hàm IsEmpty IsFull ko thay đổi giá trị của top, đừng truyền tham chiếu vào :V Nên trả về int thay vì short cho đỡ rắc rối.

thay vì viết if (…) return 1; return 0; thì viết return … luôn.

if (IsFull(top, capacity)==1) ko cần == 1

có thể viết gộp thành stack[++*top]=value;

trong hàm Pop có thể viết thành else return stack[(*top)–];

pick cũng ko cần truyền tham chiếu top

1 lỗi ở trong hàm while (stack[i] != '(') :V Trước tiên là stack[i] có gọi được ko? i thì liên quan gì tới stack mà gọi stack[i] được? Stack chỉ truy cập được phần tử cuối cùng, ko truy cập được phần tử ngẫu nhiên. Nếu em muốn truy cập phần tử ngẫu nhiên thì nó có tên là mảng rồi chứ ko có tên là stack nữa :V Lỗi khác (?) ở trong hàm while này: khi em đã pop rồi tại sao còn --*top chi nữa nhỉ :V

khoan làm stack “động” có thể thay đổi số phần tử được, em viết stack “tĩnh” trước đã: capacity là hằng số, ví dụ 100 chẳng hạn, khỏi mất công thay đổi capacity :V

5 Likes

encapsulation là em gộp những gì liên quan với nhau lại thành 1. Ví dụ ở đây là stack. top, stack, capacity đều thuộc về stack, em có thể gộp 3 cái này lại thành 1 struct. Ngoài ra còn có hàm push, pop, pick, is_full, is_empty đều thuộc về stack. em nên “gộp” nó thành 1 bằng cách thêm prefix stack_ cho nó :V

ví dụ stack tĩnh có thể khai báo như sau:

#define STACK_CAPACITY 100
struct stack_t {
    char data[STACK_CAPACITY];
    char* top;
};
int stack_is_full(struct stack_t*);
int stack_is_empty(struct stack_t*);
char stack_top(struct stack_t*);
void stack_push(struct stack_t*, char);
char stack_pop(struct stack_t*);
5 Likes

đoạn này ý em là khi pop gặp đến dấu ( thì không pop nữa nên --*top để xóa dấu ( ra khỏi stack. có cách nào khác không ạ?

1 Like

à nếu vậy thì em cứ viết pop lần nữa, đừng viết --*top ko khó hiểu lắm :V Sửa stack[i] lại xài pick đi :V

5 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?