2016-06-21 2 views
2

Рассмотрите стек, в котором не более 100 int. Определяется как:Stack in C. Сохранение результатов pop ant top

#define MAX 100 

typedef struct stack { 
    int size; 
    int values[MAX];  
} STACK; 

У меня есть эта поп-функция:

int pop(STACK *s, int *x){ 
    if (s->size == 0) return 1; 

    int *p = s->values + s->size--; 
    *x = *p; 

    return 0; 
} 

который должен удалить значение [MAX] последний элемент, сохранить это значение в точке х адресов, а затем возвращает 0, если успех;

Другие функции:

int top(STACK *s, int *x){ 
    if (s->size == 0) return 1; 

    int *p = s->values + s->size; 
    *x = *p; 

    return 0; 
} //like pop function, it should store top element at address x. 


void initStack(STACK *s){ 
    s->size = 0; 
} 

int push(STACK *s, int x){ 
    if (s->size >= MAX) return 1; 

    int *p = (s->values); 
    *(p + s->size++) = x; 

    return 0; 
} 

Это мой главный. В нем не только на первый поп-вызов:

int main(){ 
    struct stack s; 
    STACK *p = &s; 
    int i; 
    int x,y,z,w,t; 

    initStack(p); 

    for(i = 0; i < MAX; i++) 
     push(p,i); 

    int res = push(p,MAX); 

    for(i = 0; i < MAX; i++) 
     printf("%d|", p->values[i]); 

    printf("\nLast insertion: %d",res); 

    pop(p,&x); 
    pop(p,&y); 
    pop(p,&z); 
    pop(p,&w); 
    top(p,&t); 

    printf("\nThe elements %d|%d|%d|%d were removed. Current stack size: %d . Top element: %d.",x,y,z,w,p->size,t); 

    return 0; 
} 

Результаты (только последняя Printf):

The elements 1|99|98|97 were removed.Current stack size: 96 .Top element: 96. 

По какой-то причине, первый поп вызов неудачен, который осуждает не только список удаленных элементов, но также результат верхнего элемента. Любые предложения по поводу почему?

+0

насчет 'push'? –

+4

И * не делайте этого: 'int * p = s-> values ​​+ s-> size -' пожалуйста. –

+0

Возникает ли проблема только при полном заполнении стека? (Пожалуйста, отправьте 'push' и' initStack'.) – molbdnilo

ответ

0

Я второй, кто прокомментировал ясность кода. Если вы используете массивы, у вас гораздо меньше шансов иметь проблемы, если вы используете индексирование [] вместо арифметики указателя.

Это, я думаю, проблема в том, что pop имеет проблему вне пределов. После нажатия MAX элементов в main, s->size==MAX. Поэтому pop обращается к *(s->values + MAX) == s->values[MAX], что на самом деле является элементом после конец массива. Массив работает от 0 до MAX-1, а не от 1 до MAX. Например, если size==1, вы действительно хотите s->values[0], первый элемент, а не несуществующий s->values[1].

Минимальное изменение будет int *p = s->values + --s->size;, но я согласен, что это неправильный способ устранить проблему. Вместо этого следует использовать что-то вроде *x = s->values[s->size-1]; --s->size;

+0

Почему второе решение лучше первого? –

+0

Мое мнение: потому что (1) он использует операторы индекса массива '[]' для массивов, которые яснее, чем операции с указателями; (2) он отделяет индекс от декремента, который также более ясен (и проще для одного шага в отладчике!); и (3) он более четко связывает код с тем, что вы на самом деле хотите сделать: получить элемент ('[]') и изменить размер ('--'). – cxw

2
  1. Нажимаешь MAX+1 элементы в стек, так как цикл толкает MAX элементов и есть еще один push вызов после цикла.
  2. Ваш pop реализация некорректными из линии:

    int *p = s->values + s->size--; 
    

    Указатель p будет указывать на s->values[s->size] вместо s->values[s->size-1], так как декремент s->size будет происходить после оценки и присвоения p.

  3. Использование операторов инкремента/декремента внутри выражений по праву считается плохой практикой и сильно обескуражен именно из-за таких ошибок.

  4. Когда это возможно, гораздо более удобным для чтения и меньше ошибок использовать оператор индекса [] вместо арифметики указателей следующим образом:

    int 
    pop(STACK *s, int *x) { 
        if (s->size == 0) { 
        return 1; 
        } 
    
        s->size--; 
        *x = s->values[s->size]; 
    
        return 0; 
    } 
    
+0

Последнее нажатие, похоже, проверяет ошибку, поэтому оно здесь специально. – ElderBug

+1

Да, я думал, что это может быть так, но я хотел указать на это, если бы это было не так. – s7amuser

Смежные вопросы