{"id":5949,"date":"2023-07-15T00:01:41","date_gmt":"2023-07-15T07:01:41","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=5949"},"modified":"2023-07-22T09:11:16","modified_gmt":"2023-07-22T16:11:16","slug":"using-scanf-to-build-a-string-part-ii","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=5949","title":{"rendered":"Using <em>scanf()<\/em> to Build a String &#8211; Part II"},"content":{"rendered":"<p>Trying to salve my frustration with the <em>scanf()<\/em> function, I decided in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5932\">last week&#8217;s Lesson<\/a> to try to use <em>scanf()<\/em> to build a string. Because the function terminates standard input at the first whitespace character (space, tab, newline), the strings input must be stored and the string built in memory.<br \/>\n<!--more--><br \/>\nThe first change I made is to get rid of the <code>buffer[]<\/code> array and replace it with a pointer. This move may seem redundant, as pointer <code>s<\/code> is already used in the code to store the string. But I want to build a string. Therefore having one buffer for input and another for creating the string makes sense.<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2023_07_15-Lesson-a.c\" rel=\"noopener\" target=\"_blank\">2023_07_15-Lesson-a.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\/initalize buffers *\/<\/span>\r\n    b = malloc( SIZE * sizeof(char) );    <span class=\"comments\">\/* input *\/<\/span>\r\n    s = malloc( SIZE * 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    <span class=\"comments\">\/* fetch input *\/<\/span>\r\n    printf(\"Word: \");\r\n    scanf(\"%s\",b);\r\n    <span class=\"comments\">\/* copy the word *\/<\/span>\r\n    strcpy(s,b);\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>The code allocates storage for both pointers <code>b<\/code> and <code>s<\/code>, setting the size to <code>SIZE<\/code> or 16 characters (15 characters plus one for the null character). Remember: the <em>scanf()<\/em> function does not do bounds checking! Don&#8217;t input a long string just to see what happens and don&#8217;t ever use <em>scanf()<\/em> in this manner in code you plan on releasing or even using non-experimentally.<\/p>\n<p>Both strings are tested for success: <code>if( b==NULL || s==NULL )<\/code>. If either string is <code>NULL<\/code>, the program mercifully stops.<\/p>\n<p>The strings are initialized, setting each to a <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=2641\">null string<\/a>: <code>*b = *s = '\\0';<\/code> This step may not be necessary, though I want to ensure that <code>*b<\/code> and <code>*s<\/code> are &#8220;real&#8221; strings.<\/p>\n<p>The rest of the code works like the original shown in last week&#8217;s Lesson. I added a <em>printf()<\/em> statement to output a prompt. Here&#8217;s a sample run:<\/p>\n<p><code>Word: hello<br \/>\nhello<\/code><\/p>\n<p>The next step is to add a loop to collect words and build the string. This improvement requires a major change: Pointer <code>s<\/code> must be reallocated each iteration of the loop to append the new word input:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2023_07_15-Lesson-b.c\" rel=\"noopener\" target=\"_blank\">2023_07_15-Lesson-b.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        <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>Pointer <code>s<\/code> is allocated only a single character of storage for the null character: <code>s = malloc( sizeof(char) );<\/code>  This improvement builds a short string, but it comes in handy when storage is reallocated later.<\/p>\n<p>And endless <em>while<\/em> loop builds the string: <code>while(1)<\/code><\/p>\n<p>Within the loop, the <em>scanf()<\/em> function fetches input. The next statement reallocates storage for pointer <code>s<\/code>:<\/p>\n<p><code>s = realloc(s,strlen(s) + strlen(b) + 2);<\/code><\/p>\n<p>The pointer&#8217;s new size <code>s<\/code> is is based on its current size (<code>strlen(s)<\/code>) plus the length of the string input (<code>strlen(b)<\/code>) plus two. The two extra characters are for a space to separate the words and the null character.<\/p>\n<p>The <em>ralloc()<\/em> function retains the original memory buffer contents. The result is a buffer that contains the original string plus storage for the new string input.<\/p>\n<p>Two <em>strcat()<\/em> functions build the string. The first adds the input word. The second appends a space character.<\/p>\n<p>Output doesn&#8217;t happen, however, as the loop is endless. Further, why always append a space? Strings are more than words and spaces. I address these issues in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5957\">next week&#8217;s Lesson<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Building a string with the <em>scanf()<\/em> function requires allocating memory on the fly. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5949\">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-5949","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\/5949","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=5949"}],"version-history":[{"count":7,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5949\/revisions"}],"predecessor-version":[{"id":5971,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5949\/revisions\/5971"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5949"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5949"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5949"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}