Using scanf() to Build a String – Part I

The scanf() function is useful for teaching, but it’s a booger. I avoid it outside of demonstration purposes. But it does provide good fodder for training beginning programmers to think about stream I/O.

The chief limitation of scanf() is that it’s easy to overflow a string buffer. Better input statements, such as fgets(), should be used instead when reading standard input. Even then, the default for scanf() is to terminate reading input upon the first whitespace character encountered: space, tab, or newline. This limitation annoys and inspires me.

I became curious to see whether the scanf() function could be put to work building a string out of separate text chunks. For example, you input two or three words in a row to build a sentence. How would this approach work when using scanf()?

As with any project, I start small and build. The first step is to write code that uses the scanf() function to fetch a single word and sends it to standard output.

2023_07_08-Lesson-a.c

#include <stdio.h>

int main()
{
    char buffer[16];

    scanf("%s",buffer);
    puts(buffer);

    return(0);
}

This simple program uses scanf() to read text into a 15 character buffer, plus one for the null character — hopefully. Remember that string input can overflow, which is one of the weakness of not only the scanf() function but the C language.

The puts() statement outputs whatever word is input, adding a newline.

Here’s a sample run:

hello
hello

The next step is to store the words to build a longer string. I could convert buffer[] into a two dimensional array for storing each word scanf() gobbles. More efficient, however, is to allocate storage as the words flow in. After all, you can always allocate (or reallocate) memory on-the-fly. You can’t do that with a fixed-size array.

The following modification to the code uses the malloc() function to allocate storage for the string input. The allocation is based on size of the string in array buffer[]. The string in buffer[] is then copied to the newly allocated memory chunk. Finally, puts() generates the output.

2023_07_08-Lesson-b.c

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

int main()
{
    char buffer[16];
    char *s;

    scanf("%s",buffer);
    /* allocate buffer for word */
    s = malloc( strlen(buffer)+1 * sizeof(char) );
    if( s==NULL )
    {
        fprintf(stderr,"Memory allocation error\n");
        exit(1);
    }
    /* copy the word */
    strcpy(s,buffer);

    /* output results */
    puts(s);

    return(0);
}

Though this update to the program generates the same output as the original, it requires more overhead to allocate storage, confirm that storage is present, and to copy over the text input. Yet, this core provides a base upon which I can build to expand the code.

The next stage in the program’s development is to contain the core code in a loop to build the string. I tackle this phase of the project in next week’s Lesson.

Leave a Reply