/* * This program builds a linked stack in plain C much as the C++ example. * There are many differences, since plain C does not have templates or classes, * plus there's a couple of details I'm trying to avoid. So, we're putting * it all in one program. Our stack will be of integers, not generic. */ #include #include #include #include // Integer stack node. struct node { int data; struct node *next; }; // Represents a stack. struct stack { struct node * head; // Head of the linked list. int size; // Size of the stack. }; /* * Methods on stack. */ // Initialize a new stack. Call after declaring a stack. void stack_init(struct stack *stk) { stk->head = NULL; stk->size = 0; } // Clean up a stack. This should be called after using a stack to make // no garbage remains. void stack_clear(struct stack *stk) { struct node *scan = stk->head; while(scan != NULL) { struct node *zombie = scan; scan = scan->next; free(zombie); } stk->size = 0; } // Push the argument item. void stack_push(struct stack *stk, int itm) { // Create the node and fill it in. struct node *newnode = malloc(sizeof (struct node)); newnode->data = itm; newnode->next = stk->head; // Add the node to the stack. stk->head = newnode; ++stk->size; } // Pop the argument item, and return it. Return 0 if the stack is empty. // If zero is a valid data item, you should probably use the empty method // before you pop. int stack_pop(struct stack *stk) { // Bail on empty. if(stk->head == NULL) return 0; // Remove the node from the list. struct node *zombie = stk->head; stk->head = stk->head->next; --stk->size; // Extract the data and free the node. int itm = zombie->data; free(zombie); return itm; } // Tell if empty. int stack_empty(struct stack *stk) { return stk->head == NULL; } // Report the size int stack_size(struct stack *stk) { return stk->size; } int main() { // Stack of integers. struct stack is; stack_init(&is); // Read the input. char op; while(scanf(" %c", &op) == 1) { // See what we got. if(op == '.') { // Halt char. break; } else if(isdigit(op)) { // Digit. Unget it, read the number, and push it // on the stack. ungetc(op, stdin); int val; scanf("%d", &val); stack_push(&is, val); continue; } else if(strchr("+-*/", op) != NULL) { // Operator, pop the operands. if(stack_empty(&is)) break; int b = stack_pop(&is); if(stack_empty(&is)) break; int a = stack_pop(&is); // Push the operation result in place of the operands. switch(op) { case '+': stack_push(&is,a+b); break; case '-': stack_push(&is,a-b); break; case '*': stack_push(&is,a*b); break; case '/': stack_push(&is,a/b); break; } } else { // Just what it says. printf("Bad char %c.\n", op); } } // If there's a result, print it. If the stack is empty, just // whine about it. if(!stack_empty(&is)) printf("Value: %d\n", stack_pop(&is)); printf("Stack has %d elements at exit.\n", stack_size(&is)); stack_clear(&is); }