{"id":3829,"date":"2019-11-08T00:01:21","date_gmt":"2019-11-08T08:01:21","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=3829"},"modified":"2019-11-08T08:48:13","modified_gmt":"2019-11-08T16:48:13","slug":"the-yorn-function-solution","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=3829","title":{"rendered":"The Yorn Function &#8211; Solution"},"content":{"rendered":"<p>The most difficult thing about this month&#8217;s Exercise is to deal with stream input: When the user overstuffs the input buffer, those extra characters continue to flow into the program, interpreted as additional input and they make the output look ugly.<br \/>\n<!--more--><br \/>\nIf you truly want a clean-looking program that&#8217;s interactive, you must use input other than standard I\/O. For example, use Ncurses to interactively read the keyboard. But <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3820\">this month&#8217;s Exercise<\/a> required that you handle stream input, which is dicey.<\/p>\n<p>I decided that if the buffer overflows, it overflows. As long as the program continues to prompt for Yes\/No input, I&#8217;m good. Otherwise, I tackled my solution for the <em>yorn()<\/em> function in these steps:<\/p>\n<ol>\n<li>Display the input prompt<\/li>\n<li>Read input<\/li>\n<li>Check for null\/invalid input<\/li>\n<li>Convert input to uppercase<\/li>\n<li>Evaluate input<\/li>\n<\/ol>\n<p>For Step 2, I use the worthy <em>fgets()<\/em> function. Immediately after retrieving input, I move to Step 3, which is to check for null or invalid input &mdash; to see whether I\/O is being redirected as empty input or the user is just being silly:<\/p>\n<pre class=\"screen\">\r\n    <span class=\"comments\">\/* read stream input *\/<\/span>\r\n    fgets(buffer,SIZE,stdin);\r\n\r\n    <span class=\"comments\">\/* check for null input *\/<\/span>\r\n    ch = (int)buffer[0];\r\n    if( ch=='\\0' || ch==EOF )\r\n        return(0);<\/pre>\n<p>If the input buffer is empty, <code>buffer[0]=='\\0'<\/code> or a null file was redirected as input, <code>buffer[0]==EOF<\/code>, the program returns zero, meaning invalid input.<\/p>\n<p>For Step 4, I combine two tasks: remove the newline from input and convert characters to uppercase.<\/p>\n<pre class=\"screen\">\r\n    <span class=\"comments\">\/* replace the newline with null char\r\n       and convert input to uppercase *\/<\/span>\r\n    for( x=0; x&lt;SIZE; x++ )\r\n    {\r\n        if( buffer[x]=='\\0' )\r\n            break;\r\n        if( buffer[x]=='\\n' )\r\n        {\r\n            buffer[x]='\\0';\r\n            break;\r\n        }\r\n        buffer[x] = toupper(buffer[x]);\r\n    }<\/pre>\n<p>When the null character is encountered, <code>buffer[x]=='\\0'<\/code>, the loop breaks. Otherwise, when the newline is encountered, <code>buffer[x]=='\\n'<\/code>, it&#8217;s replaced with the null character and the <em>for<\/em> loop breaks. Beyond those two conditions, the <em>toupper()<\/em> function converts the character to uppercase.<\/p>\n<p>Finally, Step 5 evaluates the results. To meet this end, I use the <em>strcmp()<\/em> function to compare the four desired results: <code>YES<\/code>, <code>Y<\/code>, <code>NO<\/code>, and <code>N<\/code>. Anything else is considered invalid:<\/p>\n<pre class=\"screen\">\r\n    <span class=\"comments\">\/* evaluate results *\/<\/span>\r\n        <span class=\"comments\">\/* return 1 for Yes *\/<\/span>\r\n    if( strcmp(buffer,\"YES\")==0 )\r\n        return(1);\r\n    if( strcmp(buffer,\"Y\")==0 )\r\n        return(1);\r\n        <span class=\"comments\">\/* return 2 for No *\/<\/span>\r\n    if( strcmp(buffer,\"NO\")==0 )\r\n        return(2);\r\n    if( strcmp(buffer,\"N\")==0 )\r\n        return(2);\r\n    <span class=\"comments\">\/* neither *\/<\/span>\r\n    return(0);<\/pre>\n<p>Longer strings, such as <code>yessiree<\/code> and <code>nope<\/code> are rejected. After all, the prompt does indicate &#8220;Yes or No.&#8221;<\/p>\n<p>Here&#8217;s a sample run:<\/p>\n<p><code>Would you like to destroy the Earth? (Yes or No)? No<br \/>\nThe Earth will be saved.<\/code><\/p>\n<p>Buffer overflow is handled in the code, though the output looks sloppy:<\/p>\n<p><code>Would you like to destroy the Earth? (Yes or No)? Most definitely not.<br \/>\nInvalid response<br \/>\nWould you like to destroy the Earth? (Yes or No)? Invalid response<br \/>\nWould you like to destroy the Earth? (Yes or No)?<\/code><\/p>\n<p>Because the input string is longer than <code>SIZE<\/code> (12) characters, two responses are interpreted. Both are invalid. Still, the code saves itself, continuing to prompt for valid input.<\/p>\n<p><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2019_11-Exercise.c\" rel=\"noopener noreferrer\" target=\"_blank\">Click here<\/a> to view the entire code on Github. I hope your solution dealt with the many puzzles and issues presented with stream input. The process can be challenging.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The most difficult thing about this month&#8217;s Exercise is to deal with stream input: When the user overstuffs the input buffer, those extra characters continue to flow into the program, interpreted as additional input and they make the output look &hellip; <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3829\">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-3829","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\/3829","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=3829"}],"version-history":[{"count":5,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3829\/revisions"}],"predecessor-version":[{"id":3856,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3829\/revisions\/3856"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3829"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3829"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3829"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}