{"id":2631,"date":"2017-08-05T00:01:35","date_gmt":"2017-08-05T07:01:35","guid":{"rendered":"http:\/\/c-for-dummies.com\/blog\/?p=2631"},"modified":"2017-08-13T08:36:07","modified_gmt":"2017-08-13T15:36:07","slug":"other-ways-to-fix-fgets-input","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=2631","title":{"rendered":"Other Ways to Fix <em>fgets()<\/em> Input"},"content":{"rendered":"<p>The C language string-input function was once <em>gets()<\/em>. That function has become Chernobyl in that it exists but you go there only when you don&#8217;t care about your health.<br \/>\n<!--more--><br \/>\nThe problem with <em>gets()<\/em> was that it lacked bounds-checking; you could input an infinite number of characters, overflowing the buffer. This process is how various trojans and worms were created long ago. So instead of <em>gets()<\/em>, I recommend using the <em>fgets()<\/em> function, which features bounds-checking.<\/p>\n<p>Alas, the <em>fgets()<\/em> function also retains the newline character at the end of input, which is often not what you want. So further processing is necessary when you must peel off the trailing newline.<\/p>\n<p>A solution I offered in a <a href=\"http:\/\/c-for-dummies.com\/blog\/?p=24\">blog post from 2013<\/a> uses <em>fgets()<\/em> in an <em>input()<\/em> function that strips away the newline. Here is that function:<\/p>\n<pre class=\"screen\">\r\nvoid input(char *string,int length)\r\n{\r\n    int x;\r\n\r\n    fgets(string,length,stdin);\r\n    for(x=0;x&lt;=length;x++)\r\n    {\r\n        if( string[x] == '\\n')\r\n        {\r\n            string[x] = '\\0';\r\n            break;\r\n        }\r\n    }\r\n}<\/pre>\n<p>The <em>input()<\/em> function gathers text from standard input, up to the value set by variable <code>length<\/code>, then it churns through the buffer, replacing the newline (<code>'\\n'<\/code>) with a null character (<code>'\\0'<\/code>). The code works, but I wrote it to be illustrative so it&#8217;s clunkier than what I&#8217;d normally code.<\/p>\n<p>Recently, I had to craft the <em>input()<\/em> function for another program. After I was done, I compared what I wrote today with the <em>input()<\/em> function from four years ago. Here&#8217;s my newer version:<\/p>\n<pre class=\"screen\">\r\nvoid input(char *string,int length)\r\n{\r\n    fgets(string,length,stdin);\r\n    while(*string != '\\n')\r\n        string++;\r\n    *string = '\\0';\r\n}<\/pre>\n<p>The difference is how I located the newline and replaced it with the null character. Instead of a <em>for<\/em> loop, I used <em>while<\/em>. Instead of array notation, I used pointers. Otherwise, the code has the same result: The newline is gone, replaced by a null character.<\/p>\n<p>I could make the loop tighter, but at this point it becomes obfuscated:<\/p>\n<pre class=\"screen\">\r\nvoid input(char *string,int length)\r\n{\r\n    fgets(string,length,stdin);\r\n    while(*string++ != '\\n')\r\n        ;\r\n    *--string = '\\0';\r\n}<\/pre>\n<p>Incrementing the <code>string<\/code> variable takes place in the <em>while<\/em> loop&#8217;s condition. The <code>++<\/code> operator is suffixed, which means that the pointer is incremented <em>after<\/em> its value is fetched.<\/p>\n<p>Because the pointer is post-incremented, it must be decremented after the loop to replace <code>'\\n'<\/code> with <code>'\\0'<\/code>. So, in the final statement, the <code>--<\/code> is prefixed to the string pointer variable; its location is decremented <em>before<\/em> the value is assigned.<\/p>\n<p>Yeah, the condensed code can be confusing. Not only does it use pointers, but unless you use these techinques all the time, prefixing and suffixing operators causes most programmers to stop and think about the order of operations.<\/p>\n<p>Is there a reason to go one way or the other?<\/p>\n<p>No. I prefer readable code, so when I compose a program I typically code a function as illustrated in the first example. The same process holds true with the ternary operator (<code>?:<\/code>): I write the code the long way, then reduce it down later. Still, as long as the program does what you want, you&#8217;re good.<\/p>\n<p>Here is the full program, the modified version of the one I presented originally back in June, 2013:<\/p>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n\r\n<span class=\"comments-red\">\/* This function has a flaw; see the comments to this post *\/<\/span>\r\nvoid input(char *string,int length)\r\n{\r\n    fgets(string,length,stdin);\r\n    while(*string++ != '\\n')\r\n        ;\r\n    *--string = '\\0';\r\n}\r\n\r\nint main()\r\n{\r\n    char firstname[32],lastname[32];\r\n\r\n    printf(\"What is your first name? \");\r\n    input(firstname,32);\r\n    printf(\"What is your last name? \");\r\n    input(lastname,32);\r\n    printf(\"Please to meet you %s %s.\\n\",\r\n            firstname,\r\n            lastname);\r\n\r\n    return(0);\r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>The <em>fgets()<\/em> function reads input, but it retains the newline. Here&#8217;s another way to get rid of that extra character. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=2631\">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-2631","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\/2631","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=2631"}],"version-history":[{"count":6,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2631\/revisions"}],"predecessor-version":[{"id":2664,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2631\/revisions\/2664"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2631"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2631"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2631"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}