{"id":5957,"date":"2023-07-22T00:01:19","date_gmt":"2023-07-22T07:01:19","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=5957"},"modified":"2023-07-29T09:27:43","modified_gmt":"2023-07-29T16:27:43","slug":"using-scanf-to-build-a-string-part-iii","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=5957","title":{"rendered":"Using <em>scanf()<\/em> to Build a String &#8211; Part III"},"content":{"rendered":"<p>Unless the code must run endlessly, such as a program that operates a gas pump, an endless loop isn&#8217;t something you want. From <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5949\">last week&#8217;s Lesson<\/a>, I crafted an endless loop to accept single-word input from the <em>scanf()<\/em> function to build a string. But no string is output because the loop never ends! It&#8217;s time to address this situation.<br \/>\n<!--more--><br \/>\nI often craft endless loops when the terminating condition is just too ugly to put into a <em>while<\/em> or <em>for<\/em> statement. For building a string, I could set an input size limit. After the limit is reached, the loop exits and the string is output. However, such a size limit lacks flexibility. So instead, I added two statements to the existing code to terminate the loop:<\/p>\n<p><code>if( strcmp(b,\"END\")==0 )<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;break;<\/code><\/p>\n<p>These lines are set immediately after the <em>scanf()<\/em> statement. The string input is compared with the text <code>END<\/code>. When a match is found, the loop breaks and the string is output. The word &#8220;END&#8221; isn&#8217;t appended to the string (which is why input is checked immediately). Here is the full code:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2023_07_22-Lesson-a.c\" rel=\"noopener\" target=\"_blank\">2023_07_22-Lesson.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;string.h&gt;\r\n\r\n#define SIZE 16\r\n\r\nint main()\r\n{\r\n    char *b,*s;\r\n\r\n    <span class=\"comments\">\/* allocate\/initialize buffers *\/<\/span>\r\n    b = malloc( SIZE * sizeof(char) );    <span class=\"comments\">\/* input *\/<\/span>\r\n    s = malloc( sizeof(char) );            <span class=\"comments\">\/* string *\/<\/span>\r\n    if( b==NULL || s==NULL )\r\n    {\r\n        fprintf(stderr,\"Memory allocation error\\n\");\r\n        exit(1);\r\n    }\r\n    <span class=\"comments\">\/* initialize string storage *\/<\/span>\r\n    *b = *s = '\\0';\r\n\r\n    while(1)\r\n    {\r\n        <span class=\"comments\">\/* fetch input *\/<\/span>\r\n        printf(\"Word: \");\r\n        scanf(\"%s\",b);\r\n        if( strcmp(b,\"END\")==0 )\r\n            break;\r\n        <span class=\"comments\">\/* copy the word *\/<\/span>\r\n            <span class=\"comments\">\/* add two: space and null char *\/<\/span>\r\n        s = realloc(s,strlen(s) + strlen(b) + 2);\r\n        if( s==NULL )\r\n        {\r\n            fprintf(stderr,\"Reallocation error\\n\");\r\n            exit(1);\r\n        }\r\n        strcat(s,b);\r\n        strcat(s,\" \");\r\n    }\r\n\r\n    <span class=\"comments\">\/* output results *\/<\/span>\r\n    puts(s);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>Now the program runs &mdash; and terminates! &mdash; providing you type the word <strong>END<\/strong> (all caps) after the string of text:<\/p>\n<p><code>Word: Hello<br \/>\nWord: there,<br \/>\nWord: blue<br \/>\nWord: ball!<br \/>\nWord: END<br \/>\nHello there, blue ball!<\/code><\/p>\n<p>Because the <em>scanf()<\/em> function devours stream input, you can type everything on a single line:<\/p>\n<p><code>Word: Hello there, blue ball! END<br \/>\nWord: Word: Word: Word: Hello there, blue ball!<\/code><\/p>\n<p>Alas, the program outputs the input prompt <code>Word:<\/code> for each whitespace character input. Still, the string is properly built.<\/p>\n<p>To fix the multiple prompts, I moved the prompting <em>printf()<\/em> statement before the endless <em>while<\/em> loop, and changed it to read <code>\"Type some text:\"<\/code>. This update is found <a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2023_07_22-Lesson-b.c\" rel=\"noopener\" target=\"_blank\">on GitHub<\/a>. Here is the output from the updated program:<\/p>\n<p><code>Type some text: This is some text END<br \/>\nThis is some text<\/code><\/p>\n<p>Another flaw I pointed out last week is that each word in the string is suffixed with a space character. This assumption means that the string is always terminated with a space and that spaces sandwich each word. A possible solution is to create a series of &#8220;secret&#8221; words to type that help format the text.<\/p>\n<p>For example, in addition to <code>END<\/code>, the user could type <code>SP<\/code> to add a space or <code>NL<\/code> for a newline. These words can be scanned for similar to <code>END<\/code> in the current program. A better solution is to write a tokenizing function that translates special words into tokens or characters. I cover this update in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5963\">next week&#8217;s Lesson<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Somehow, my <em>scanf()<\/em> string building program needs a way to terminate input. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5957\">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-5957","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\/5957","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=5957"}],"version-history":[{"count":5,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5957\/revisions"}],"predecessor-version":[{"id":5984,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5957\/revisions\/5984"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5957"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5957"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5957"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}