{"id":689,"date":"2014-05-17T00:01:21","date_gmt":"2014-05-17T07:01:21","guid":{"rendered":"http:\/\/c-for-dummies.com\/blog\/?p=689"},"modified":"2014-05-24T07:59:12","modified_gmt":"2014-05-24T14:59:12","slug":"a-word-wrap-filter","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=689","title":{"rendered":"A Word Wrap Filter"},"content":{"rendered":"<p>Unlike static text, streaming text feeds into a program one character at a time. To wrap that text, you need to know all the basics about wrapping text (covered in <a href=\"http:\/\/c-for-dummies.com\/blog\/?p=669\">this Lesson<\/a>), but also how to concoct a filter that buffers its output.<br \/>\n<!--more--><br \/>\nA filter is a basic I\/O machine. I write about them in my <em>For Dummies<\/em> C language titles. The program gobbles up input one character at a time, does something to the character(s), then spews output.<\/p>\n<p>Here is a most basic filter:<\/p>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n\r\nint main()\r\n{\r\n    int a;\r\n\r\n    while( (a = getchar()) != EOF)\r\n        putchar(a);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>The code simply takes input from <em>getchar()<\/em> and sends that to output via <em>putchar()<\/em>. The <em>while<\/em> loop keeps working until the input stream generates an <em>EOF<\/em> (end of file) character.<\/p>\n<blockquote><p>When using this code to read standard input, the <em>EOF<\/em> character is Ctrl+D in Unix, Ctrl+Z in Windows. Or just type Ctrl+C to terminate the program.<\/p><\/blockquote>\n<p>The problem with the code above is that it doesn&#8217;t do anything to modify input, so it&#8217;s not a very useful filter.<\/p>\n<p>An example of a more useful filter would be one that wraps text. The code needs to know a wrapping point, what I call the <em>right margin<\/em>. Then it also needs to determine the proper breaking point at which to wrap. The following code shows one way to handle this task.<\/p>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;ctype.h&gt;\r\n\r\nint main()\r\n{\r\n    char *buffer,*space;\r\n    int c,x,right_margin,position;\r\n\r\n    right_margin = 40;      <span class=\"comments\">\/* make the margin variable *\/<\/span>\r\n\r\n    <span class=\"comments\">\/* allocate space for the buffer *\/<\/span>\r\n    buffer = malloc(sizeof(char) * right_margin);\r\n    if(buffer==NULL)\r\n    {\r\n        perror(\"Unable to allocate buffer\");\r\n        exit(1);\r\n    }\r\n\r\n    *buffer = '\\0';         <span class=\"comments\">\/* initialize buffer *\/<\/span>\r\n    space = buffer;         <span class=\"comments\">\/* Initialize space *\/<\/span>\r\n    position = 0;           <span class=\"comments\">\/*  and position *\/<\/span>\r\n    c = 65;                 <span class=\"comments\">\/* Ensure that it loops *\/<\/span>\r\n    while(c)\r\n    {\r\n        c = getchar();          <span class=\"comments\">\/* fetch character *\/<\/span>\r\n        *(buffer+position) = c; <span class=\"comments\">\/* store character *\/<\/span>\r\n        <span class=\"comments\">\/* if c is white space, save its location *\/<\/span>\r\n        if(isspace(c))\r\n            space = buffer+position;\r\n        position++;             <span class=\"comments\">\/* buffer index *\/<\/span>\r\n        <span class=\"comments\">\/* check to see if the margin has been reached *\/<\/span>\r\n        if(position &gt; right_margin)\r\n        {\r\n            <span class=\"comments\">\/* Display the buffer up to the space *\/<\/span>\r\n            for(x=0;x&lt;right_margin;x++)\r\n            {\r\n                if( *(buffer+x)==EOF)   <span class=\"comments\">\/* exit on EOF *\/<\/span>\r\n                    exit(0);\r\n                if(buffer+x == space)   <span class=\"comments\">\/* stop at w\/s char *\/<\/span>\r\n                    break;\r\n                putchar(*(buffer+x));\r\n            }\r\n            putchar('\\n');\r\n            <span class=\"comments\">\/* copy the rest of the buffer to the start *\/<\/span>\r\n            position = 0;\r\n            space++;\r\n            while(space &lt;= buffer+right_margin)\r\n            {\r\n                *(buffer+position) = *(space);\r\n                position++;\r\n                space++;\r\n            }\r\n            <span class=\"comments\">\/* Re-initialize the space pointer *\/<\/span>\r\n            space = buffer;\r\n        }\r\n    }\r\n\r\n    return(0);\r\n}<\/pre>\n<p>Yes! That&#8217;s a long chunk of code, but it&#8217;s doing a lot. The primary difference between this code and last week&#8217;s Lesson (on wrapping existing text) is that this example deals with stream input. That ratchets up the difficulty a notch.<\/p>\n<p>To demonstrate how the code works you can run the program and type text at the command prompt, or you can redirect input from a file. As an example, assume that the file <code>preamble.txt<\/code> contains the Preamble to the Declaration of Independence. Figure 1 illustrates how this code processes that input.<\/p>\n<div id=\"attachment_700\" style=\"width: 460px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-700\" src=\"http:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2014\/05\/0517-figure1-300x177.png\" alt=\"Figure 1. Processing a file redirected as input.\" width=\"450\" height=\"266\" class=\"size-medium wp-image-700\" srcset=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2014\/05\/0517-figure1-300x177.png 300w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2014\/05\/0517-figure1.png 306w\" sizes=\"auto, (max-width: 450px) 100vw, 450px\" \/><p id=\"caption-attachment-700\" class=\"wp-caption-text\">Figure 1. Processing a file redirected as input.<\/p><\/div>\n<p>Click <a href=\"http:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2014\/05\/preamble.txt\">here<\/a> to download a copy of the <code>preamble.txt<\/code> file.<\/p>\n<p><a href=\"http:\/\/c-for-dummies.com\/blog\/?p=702\">Next week<\/a>, I&#8217;ll present the blow-by-blow of how this code works, along with a video that visually explains what&#8217;s going on. I&#8217;ll also offer an explanation of the two conditions that cause this code to malfunction.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wrapping streaming text requires that you &#8220;look ahead&#8221; to see what&#8217;s coming up. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=689\">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":[2],"tags":[],"class_list":["post-689","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/689","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=689"}],"version-history":[{"count":11,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/689\/revisions"}],"predecessor-version":[{"id":741,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/689\/revisions\/741"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=689"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=689"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=689"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}