Using scanf() to Build a String – Part II

Trying to salve my frustration with the scanf() function, I decided in last week’s Lesson to try to use scanf() 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.

The first change I made is to get rid of the buffer[] array and replace it with a pointer. This move may seem redundant, as pointer s 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.

2023_07_15-Lesson-a.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SIZE 16

int main()
{
    char *b,*s;

    /* allocate/initalize buffers */
    b = malloc( SIZE * sizeof(char) );    /* input */
    s = malloc( SIZE * sizeof(char) );    /* string */
    if( b==NULL || s==NULL )
    {
        fprintf(stderr,"Memory allocation error\n");
        exit(1);
    }
    /* initialize string storage */
    *b = *s = '\0';

    /* fetch input */
    printf("Word: ");
    scanf("%s",b);
    /* copy the word */
    strcpy(s,b);

    /* output results */
    puts(s);

    return(0);
}

The code allocates storage for both pointers b and s, setting the size to SIZE or 16 characters (15 characters plus one for the null character). Remember: the scanf() function does not do bounds checking! Don’t input a long string just to see what happens and don’t ever use scanf() in this manner in code you plan on releasing or even using non-experimentally.

Both strings are tested for success: if( b==NULL || s==NULL ). If either string is NULL, the program mercifully stops.

The strings are initialized, setting each to a null string: *b = *s = '\0'; This step may not be necessary, though I want to ensure that *b and *s are “real” strings.

The rest of the code works like the original shown in last week’s Lesson. I added a printf() statement to output a prompt. Here’s a sample run:

Word: hello
hello

The next step is to add a loop to collect words and build the string. This improvement requires a major change: Pointer s must be reallocated each iteration of the loop to append the new word input:

2023_07_15-Lesson-b.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SIZE 16

int main()
{
    char *b,*s;

    /* allocate/initialize buffers */
    b = malloc( SIZE * sizeof(char) );    /* input */
    s = malloc( sizeof(char) );            /* string */
    if( b==NULL || s==NULL )
    {
        fprintf(stderr,"Memory allocation error\n");
        exit(1);
    }
    /* initialize string storage */
    *b = *s = '\0';

    while(1)
    {
        /* fetch input */
        printf("Word: ");
        scanf("%s",b);
        /* copy the word */
            /* add two: space and null char */
        s = realloc(s,strlen(s) + strlen(b) + 2);
        if( s==NULL )
        {
            fprintf(stderr,"Reallocation error\n");
            exit(1);
        }
        strcat(s,b);
        strcat(s," ");
    }

    /* output results */
    puts(s);

    return(0);
}

Pointer s is allocated only a single character of storage for the null character: s = malloc( sizeof(char) ); This improvement builds a short string, but it comes in handy when storage is reallocated later.

And endless while loop builds the string: while(1)

Within the loop, the scanf() function fetches input. The next statement reallocates storage for pointer s:

s = realloc(s,strlen(s) + strlen(b) + 2);

The pointer’s new size s is is based on its current size (strlen(s)) plus the length of the string input (strlen(b)) plus two. The two extra characters are for a space to separate the words and the null character.

The ralloc() function retains the original memory buffer contents. The result is a buffer that contains the original string plus storage for the new string input.

Two strcat() functions build the string. The first adds the input word. The second appends a space character.

Output doesn’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 next week’s Lesson.

Leave a Reply