Основная проблема заключается в использовании ненужных глобальных переменных, которые, кажется, вызывают путаницу. В push
параметр имеет тип struct stackNode *
, но он обрабатывается так, как если бы он ссылался на глобальный root
. Но root = new
является чисто локальным и не оказывает влияния на глобальный root
. Однако size++
влияет на глобальную область действия . Это портит логическое состояние стека, и ваш обработчик ошибок в начале pop
считает, что size == 3
, и не жалуется. Затем функция должным образом разыменовывает root
, вызывая сбой программы.
Правильный класс стека не должен использовать глобальные данные. Он должен заключать в себе все необходимое состояние в структурах. Это делает его многоразовым, позволяя создавать несколько стеков (свойство, которое я хотел бы использовать в большинстве классов, которые я использую).
Несколько других предложений:
- Избегать побочные эффекты , где это возможно. Отпечатки в порядке для целей временной отладки, но в противном случае их следует полностью отделить от логики программы.
- Если вы планируете писать обработчики ошибок, печатайте в
stderr
и избегайте магических значений, таких как return '\0';
, которые могут быть ошибочно приняты зафактические данные узла. - Не приводите результат
malloc
. Это может подавить ошибки и визуально зашумить. - Жесткое кодирование
capacity
выглядит довольно произвольно. Я не уверен, есть ли смысл иметь это (но если есть, добавьте его в структуру). Если в каждом узле слишком много метаданных о стеке (в идеале их не должно быть), создайте структуру Stack
, содержащую эти метаданные, и укажите ее на фактическую цепочку stackNode
. - Еще одна точка проектирования стека:
malloc
/ free
медленные. Для символьных данных простой массив с указателем top
будет быстрее и проще в реализации. Вы можете амортизировать вызовы выделения с периодическим удвоением массива при top >= capacity
и сокращением при top < capacity / 2
.
Вот быстрая перезапись (без предложения для структуры оболочки Stack
или массива):
#include <stdio.h>
#include <stdlib.h>
struct stackNode {
char letter;
struct stackNode *next;
int size;
};
void push(char data, struct stackNode **root) {
struct stackNode *new = malloc(sizeof(*new));
new->size = *root ? (*root)->size + 1 : 1;
new->letter = data;
new->next = *root;
*root = new;
}
char pop(struct stackNode **root) {
if (!*root || !(*root)->size) {
fprintf(stderr, "pop from empty stack\n");
exit(1);
}
char popped = (*root)->letter;
struct stackNode *cull = *root;
*root = (*root)->next;
free(cull);
return popped;
}
int main() {
struct stackNode *root = NULL;
push('c', &root);
push('v', &root);
push('n', &root);
while (root) {
printf("%c ", pop(&root));
}
puts("");
return 0;
}