Using scanf() to Build a String – Part V

In my code update for last week’s Lesson, I used return statements to send strings back to the main() function. This technique works — only once, even though the strings are declared static in the token() function.

If you don’t classify the strings as static, the program won’t build properly. This reason is why the strings are declared on lines by themselves:

static char space[] = " ";
static char newline[] = "\n";
static char tab[] = "\t";

But the sample output is ugly:

Type some Text: This SP is SP a SP test NL Hello, SP world! END
This isSPaSPtestHello,NLSPworld!

I didn’t debug the program to discover why the replacement strings aren’t copied into the final string. My guess, however, is that it has something to do with their addresses. Yes, it’s a pointer issue.

Obviously, a better solution must be found, one that allocates the strings as they’re needed. Though this may not be a simple solution, it works.

Here is the updated token() function:

char *token(char *s)
{
    char space[] = " ";
    char newline[] = "\n";
    char tab[] = "\t";
    char *r;

    /* test for special strings */
    if( strcmp(s,"END")==0 )
        return(NULL);
    if( strcmp(s,"SP")==0 )
    {
        r = malloc( strlen(space) +1 );
        strcpy(r,space);
        return(r);
    }
    if( strcmp(s,"NL")==0 )
    {
        r = malloc( strlen(newline) +1 );
        strcpy(r,newline);
        return(r);
    }
    if( strcmp(s,"TB")==0 )
    {
        r = malloc( strlen(tab) +1 );
        strcpy(r,tab);
        return(r);
    }

    return(s);
}

The first strcmp() comparison tests for the text END. If found, NULL is returned. No problems here.

The next comparison is for the SP token. If found, space is allocated for a new string based on the size of string space, plus one for the null character. No testing is done here to confirm whether memory is available; if I were to release this code I would check to ensure that memory is properly allocated.

After storage is created, the space string is copied into the new string at r. The new string’s address is returned: return(r);

This approach is used twice more with if decisions for the NL and TB tokens.

You can click here to view the full code on GitHub.

Here’s the output, using the same “aggressive” input from last week’s Lesson:

Type some Text: This SP is SP a SP test NL Hello, SP world! END
This is a test
Hello, world!

Because the strings are allocated as needed, the storage doesn’t vanish and is properly copied to the final string output.

Yes, I’m not freeing the memory when the main() function exits. This step isn’t necessary as the program is exiting and freeing all its memory anyway. But had these routines been part of a larger program, I would definitely free the allocated memory.

My goal with this series was to see how I could finagle the scanf() function to fetch a full string. While I’m able to use scanf() to do so, the tokens make input difficult to type and, well, ugly. Given that, and how scanf() can overflow a buffer, the best approach for string input remains using a function like fgets() instead.

Leave a Reply