{"id":1701,"date":"2016-01-08T00:01:36","date_gmt":"2016-01-08T08:01:36","guid":{"rendered":"http:\/\/c-for-dummies.com\/blog\/?p=1701"},"modified":"2016-01-02T09:38:21","modified_gmt":"2016-01-02T17:38:21","slug":"defensive-input-solution","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=1701","title":{"rendered":"Defensive Input &#8211; Solution"},"content":{"rendered":"<p>Writing an input routine isn&#8217;t that difficult in C. I cobble together simple input routines all the time. The <em>scanf()<\/em> function is brilliant for such situations. When you have to test input, things get dicey, which I hope you discovered as you attempted this month&#8217;s exercise.<br \/>\n<!--more--><br \/>\nTake <em>scanf()<\/em> for example. Suppose you tried a solution with a simple <em>scanf()<\/em> for integer input:<\/p>\n<p><code>scanf(\"%d\",&amp;input);<\/code><\/p>\n<p>If your user is disobedient and types in a string, then the program may crash.<\/p>\n<p>As an alternative, you could modify <em>scanf()<\/em> to fetch a single character:<\/p>\n<p><code>scanf(%c\",&amp;input);<\/code><\/p>\n<p>The problem here is that text input (a string) generates a response for each character in the input stream.<\/p>\n<p>You could use <em>fgets()<\/em> to process input as a line of text. The issue you&#8217;ll discover with that function is that the newline at the end of the input is retained in the stream. The next input function reads the newline, which probably isn&#8217;t what you want.<\/p>\n<p>If you tried and tested all the C library input functions, then you will come to realize that the best solution is simply to write your own input routine. Have that function anticipate any and all forms of input, eliminate the excess, and then process whatever was typed to generate the desired result.<\/p>\n<p>Here is my solution:<\/p>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n\r\n#define LIMIT 24\r\n#define TRUE 1\r\n#define FALSE 0\r\n\r\nint one_digit(void);\r\n\r\nint main()\r\n{\r\n    int value;\r\n\r\n    while(1)\r\n    {\r\n        printf(\"Enter a number 1 to 9: \");\r\n        value = one_digit();\r\n        if( value != -1 )\r\n            break;\r\n        puts(\"Incorrect input. Try again:\");\r\n    }\r\n    printf(\"You input %d\\nThank you!\\n\",value);\r\n\r\n    return(0);\r\n}\r\n\r\nint one_digit(void)\r\n{\r\n    char text[LIMIT];\r\n    int count = 0;\r\n    int overflow = FALSE;\r\n    char t = '\\0';\r\n\r\n    <span class=\"comments\">\/* read in an entire string *\/<\/span>\r\n    while( t != '\\n')\r\n    {\r\n        t = getchar();\r\n        text[count] = t;\r\n        count++;\r\n        if (count &gt;= LIMIT)\r\n        {\r\n            overflow = TRUE;\r\n            count = 0;  <span class=\"comments\">\/* reset buffer *\/<\/span>\r\n        }\r\n    }\r\n\r\n    <span class=\"comments\">\/* check exit conditions *\/<\/span>\r\n    if(overflow)            <span class=\"comments\">\/* too much text typed *\/<\/span>\r\n        return(-1);\r\n    if( count != 2 )        <span class=\"comments\">\/* more than one digit *\/<\/span>\r\n       return(-1);\r\n                    <span class=\"comments\">\/* check single digit range *\/<\/span>\r\n    if( text[0] &gt;= '1' && text[0] &lt;= '9' )\r\n        return(text[0] - '0');  <span class=\"comments\">\/* return value *\/<\/span>\r\n    else\r\n        return(-1);\r\n}<\/pre>\n<p>The <em>one_digit()<\/em> function at Line 26 handles the single-digit input chore. It&#8217;s job is to return a valid digit in the range of 1 to 9. Any other input, no matter how whacky, generates a -1 return value. So the endless <em>while<\/em> loop at Line 13 keeps spinning until valid input is received (Lines 16 &#8211; 18). Valid input breaks the loop.<\/p>\n<p>To read input, the <em>one_digit()<\/em> function uses a throw-away buffer, defined as <code>text[]<\/code> at Line 28. The <em>while<\/em> loop at Line 34 reads standard input until a newline is intercepted.<\/p>\n<p>Each character input (at Line 36) is stored in the <code>text<\/code> buffer (Line 37). A <code>count<\/code> variable checks the buffer size (Line 39). If the buffer overflows, the <code>overflow<\/code> variable is set TRUE (line 41) and the buffer is reset (Line 42). Input continues until the newline is encountered.<\/p>\n<p>When the <em>while<\/em> loop stops, the buffer is examined by the exit conditions starting at Line 47. If the buffer was overflowed, condition -1 is returned (Lines 47 and 48). If the buffer contains more than a single character (Line 49), that&#8217;s also an error condition and -1 is returned. What&#8217;s left is a single character in the buffer. Line 52 checks to see if it&#8217;s in range and, if so, the character is converted to a value and returned at Line 53. All other conditions fail with the <em>return<\/em> statement at Line 55.<\/p>\n<p>Yeah, that&#8217;s a lot of defensive programming, but the result is fairly bullet-proof when it comes to grabbing the right type of input.<\/p>\n<p>As usual, other solutions are possible. As long as you can aggressively type anything at the prompt and have only valid input processed, then your solution is good.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Writing an input routine isn&#8217;t that difficult in C. I cobble together simple input routines all the time. The scanf() function is brilliant for such situations. When you have to test input, things get dicey, which I hope you discovered &hellip; <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=1701\">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-1701","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\/1701","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=1701"}],"version-history":[{"count":5,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1701\/revisions"}],"predecessor-version":[{"id":1723,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1701\/revisions\/1723"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1701"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1701"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1701"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}