This month’s Exercise presents more than a traditional filter. Instead of input being processed and immediately output, the input must be stored. Further, the storage quantity is unknown. Therefore, to provide proper storage the code must employ an expanding buffer. This condition means that the solution relies upon the scariest aspect of C programming: pointers!
Because the amount of input is unknown, storage must be allocated as characters come in. This process involves an initial allocation then reallocation to expand a buffer as the storage fills. After the EOF (end-of-file) is encountered, the buffer is dumped in reverse order to standard output.
I’ve used a similar approach in my word wrap filter post, but in that code the buffer size is fixed and the buffer re-used. With this month’s challenge, the buffer must be allocated and repeatedly reallocated as necessary.
For the buffer size, I chose one character, which reduces the complicated math required for reallocating larger buffer sizes.
Here is my solution:
2025_07-Exercise.c
#include <stdio.h> #include <stdlib.h> int main() { char *buffer = NULL; int ch,offset; /* read and store standard input */ offset = 0; while( (ch=getchar()) != EOF ) { /* allocate buffer first time through */ if( buffer==NULL ) { /* allocate one byte */ buffer = malloc( sizeof(char) ); if( buffer==NULL ) { fprintf(stderr,"Unable to allocate buffer\n"); exit(1); } } else { /* expand the buffer by one byte */ offset++; buffer = realloc(buffer,sizeof(char) * (offset+1) ); if( buffer==NULL ) { fprintf(stderr,"Unable to expand storage\n"); exit(1); } } *(buffer+offset) = ch; } /* input saved in the buffer, dump the buffer backwards */ while(offset>=0) { putchar( *(buffer+offset) ); offset--; } /* clean-up */ free(buffer); return 0; }
Pointer buffer
is initialized to NULL, which helps the while loop determine whether buffer
is allocated.
Variable offset
holds the address within the buffer where new characters are added from input; you don’t want to alter the address stored in pointer buffer
as the program runs.
The while loop repeats until the EOF is encountered.
while( (ch=getchar()) != EOF )
The looping condition captures input into int variable ch
. Remember that getchar() returns an integer value, otherwise the EOF can’t be detected. The parentheses around ch=getchar()
return the value of ch
, which is compared with the EOF value.
The if decision within the while loop tests to see whether buffer
is allocated. If not, it’s initialized with storage for one character. Otherwise, in the else condition, buffer
is reallocated, expanded by the value of variable offset
, plus one. (Variable offset
is initialized to zero.)
Either way, the statement *(buffer+offset) = ch;
sets the received character into the buffer.
After the EOF is encountered, a second while loop uses the value of variable offset
to dump the buffer’s contents backwards:
while(offset>=0)
Because offset
references the end of the buffer, characters are output in reverse order. The variable is decremented each time the loop repeats. Looping must stop at zero, which is the location (offset) of the first character input.
Note that buffer
isn’t a string. It’s not terminated with a null character, nor does it need to be.
When the dumping is done, buffer is freed and program control returns to the operating system.
Here’s a sample run:
This is a test
tset a si sihT
At the command prompt, press Enter and Ctrl+D (and Enter again) to send the EOF.
I hope that your solution met with success. The key is to reallocate the buffer to ensure that all text, no matter what its quantity, is captured.
An interesting thing about realloc is that if it fails (ie returns NULL) it doesn’t free the original memory so you can still use it.
I have some vague idea you could move the characters up one with memmove each time a new character is entered and then add new ones at [0]. Probably a stupid idea!
Interesting about realloc().
Re mememove(): Seems like a lot of overhead, but worth a try!