{"id":7053,"date":"2025-07-08T00:01:24","date_gmt":"2025-07-08T07:01:24","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=7053"},"modified":"2025-07-05T11:26:00","modified_gmt":"2025-07-05T18:26:00","slug":"the-reversing-filter-solution","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=7053","title":{"rendered":"The Reversing Filter &#8211; Solution"},"content":{"rendered":"<p>This <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7042\">month&#8217;s Exercise<\/a> 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!<br \/>\n<!--more--><br \/>\nBecause 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.<\/p>\n<p>I&#8217;ve used a similar approach in my <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=689\">word wrap filter post<\/a>, but in that code the buffer size is fixed and the buffer re-used. With this month&#8217;s challenge, the buffer must be allocated and repeatedly reallocated as necessary.<\/p>\n<p>For the buffer size, I chose one character, which reduces the complicated math required for reallocating larger buffer sizes.<\/p>\n<p>Here is my solution:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2025_07-Exercise.c\" rel=\"noopener\" target=\"_blank\">2025_07-Exercise.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n\r\nint main()\r\n{\r\n    char *buffer = NULL;\r\n    int ch,offset;\r\n\r\n    <span class=\"comments\">\/* read and store standard input *\/<\/span>\r\n    offset = 0;\r\n    while( (ch=getchar()) != EOF )\r\n    {\r\n        <span class=\"comments\">\/* allocate buffer first time through *\/<\/span>\r\n        if( buffer==NULL )\r\n        {\r\n            <span class=\"comments\">\/* allocate one byte *\/<\/span>\r\n            buffer = malloc( sizeof(char) );\r\n            if( buffer==NULL )\r\n            {\r\n                fprintf(stderr,\"Unable to allocate buffer\\n\");\r\n                exit(1);\r\n            }\r\n        }\r\n        else\r\n        {\r\n            <span class=\"comments\">\/* expand the buffer by one byte *\/<\/span>\r\n            offset++;\r\n            buffer = realloc(buffer,sizeof(char) * (offset+1) );\r\n            if( buffer==NULL )\r\n            {\r\n                fprintf(stderr,\"Unable to expand storage\\n\");\r\n                exit(1);\r\n            }\r\n        }\r\n        *(buffer+offset) = ch;\r\n    }\r\n\r\n    <span class=\"comments\">\/* input saved in the buffer, dump the buffer backwards *\/<\/span>\r\n    while(offset&gt;=0)\r\n    {\r\n        putchar( *(buffer+offset) );\r\n        offset--;\r\n    }\r\n\r\n    <span class=\"comments\">\/* clean-up *\/<\/span>\r\n    free(buffer);\r\n    return 0;\r\n}<\/pre>\n<p>Pointer <code>buffer<\/code> is initialized to NULL, which helps the <em>while<\/em> loop determine whether <code>buffer<\/code> is allocated.<\/p>\n<p>Variable <code>offset<\/code> holds the address within the buffer where new characters are added from input; you don&#8217;t want to alter the address stored in pointer <code>buffer<\/code> as the program runs.<\/p>\n<p>The <em>while<\/em> loop repeats until the EOF is encountered.<\/p>\n<p><code>while( (ch=getchar()) != EOF )<\/code><\/p>\n<p>The looping condition captures input into <em>int<\/em> variable <code>ch<\/code>. Remember that <em>getchar()<\/em> returns an integer value, otherwise the EOF can&#8217;t be detected. The parentheses around <code>ch=getchar()<\/code> return the value of <code>ch<\/code>, which is compared with the EOF value.<\/p>\n<p>The <em>if<\/em> decision within the <em>while<\/em> loop tests to see whether <code>buffer<\/code> is allocated. If not, it&#8217;s initialized with storage for one character. Otherwise, in the <em>else<\/em> condition, <code>buffer<\/code> is reallocated, expanded by the value of variable <code>offset<\/code>, plus one. (Variable <code>offset<\/code> is initialized to zero.)<br \/>\nEither way, the statement <code>*(buffer+offset) = ch;<\/code> sets the received character into the buffer.<\/p>\n<p>After the EOF is encountered, a second <em>while<\/em> loop uses the value of variable <code>offset<\/code> to dump the buffer&#8217;s contents backwards:<\/p>\n<p><code>while(offset&gt;=0)<\/code><\/p>\n<p>Because <code>offset<\/code> 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.<\/p>\n<p>Note that <code>buffer<\/code> isn&#8217;t a string. It&#8217;s not terminated with a null character, nor does it need to be.<\/p>\n<p>When the dumping is done, <em>buffer<\/em> is freed and program control returns to the operating system.<\/p>\n<p>Here&#8217;s a sample run:<\/p>\n<p><code>This is a test<\/p>\n<p>tset a si sihT<\/code><\/p>\n<p>At the command prompt, press Enter and Ctrl+D (and Enter again) to send the EOF.<\/p>\n<p>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.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This month&#8217;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. &hellip; <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7053\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-7053","post","type-post","status-publish","format-standard","hentry","category-solution"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7053","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7053"}],"version-history":[{"count":3,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7053\/revisions"}],"predecessor-version":[{"id":7065,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7053\/revisions\/7065"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7053"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7053"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7053"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}