#include #include #define BUFFER_SIZE 1024 // Represents an area of memory being used to store part of the stack. struct frame { // Pointer to the previous stack frame. struct frame *previous; // The buffer for storing data. char buffer[BUFFER_SIZE]; }; // Current frame of the stack. // This will be NULL initially and in future will only be nulled when the last element is pushed off the stack. struct frame *currentFrame; // The first free index within the buffer of the current frame. // The buffer is full when this is equal to BUFFER_SIZE-1. int bufferIndex = 0; // Number of frames in the stack. Only used for reporting purposes. int frameCount = 0; /** Allocate a new frame on the stack. This is intended to only be called when the * current stack frame is full, and the results are undefined if called otherwise. */ int newFrame() { struct frame *oldFrame = currentFrame; struct frame *nextFrame; nextFrame = malloc(sizeof(struct frame)); if (nextFrame == NULL) return -1; else currentFrame = nextFrame; currentFrame->previous = oldFrame; bufferIndex = 0; frameCount++; return 0; } /** Free the memory used by the current frame and reset the head of the stack to the * end of the previous frame. */ void clearFrame() { if (currentFrame != NULL) { struct frame *oldFrame = currentFrame->previous; free(currentFrame); currentFrame = oldFrame; bufferIndex = BUFFER_SIZE - 1; frameCount--; } } /** * The number of characters currently on the stack. */ int stackSize() { return (currentFrame == NULL) ? 0 : (frameCount - 1) * BUFFER_SIZE + bufferIndex; } /** * Push a character onto the stack. This returns -1 if it fails to push, or 0 otherwise. */ int push(char i) { int error = 0; if ((bufferIndex >= BUFFER_SIZE) || (currentFrame == NULL)) { error = newFrame(); } if (error == -1) return -1; currentFrame->buffer[bufferIndex++] = i; } /** * Pops the character at the head of the stack and returns it, or returns -1 if the stack is * empty. */ int pop() { // This will reset bufferIndex to BUFFER_SIZE - 1 if (bufferIndex < 0) clearFrame(); if (currentFrame == NULL) return -1; return currentFrame->buffer[--bufferIndex]; } /** * Returns the current head of the stack without popping it. */ int head() { if (currentFrame == NULL) return -1; else if ((bufferIndex == 0) && (currentFrame->previous == NULL)) return -1; else if (bufferIndex > 0) return currentFrame->buffer[bufferIndex - 1]; else return currentFrame->previous->buffer[BUFFER_SIZE - 1]; } /** * Duplicates the current head of the stack. */ void dup() { push(head()); } int main() { int val; while ( (val = getchar()) != EOF ) { if (push(val) == -1) { printf("Failed to push "); putchar(val); printf(". Exiting."); return -1; } } printf("Stack size %d \n", stackSize()); while ( (val = pop()) != -1 ) putchar(val); return 0; }