Search code examples
cstringpointersuppercase

What is wrong with this example in Dietel's "C: How to Program" book?


I'm studying C: How to program by Dietel. in Pointers chapter, there is this example code:

#include <stdio.h>
#include <ctype.h>

void convertToUppercase(char *sPtr);

int main( void )
{
    char string[] = "cHaRaCters and $32.98";
    printf( "The string before conversion is: %s", string );
    convertToUppercase( string );
    printf( "\nThe string after conversion is: %s\n", string );
}

void convertToUppercase(char *sPtr)
{
    while(*sPtr != '\0') {
        *sPtr = toupper(*sPtr);
        ++*sPtr;
    }
}

when I compile it, there is no problem. but when I run it, nothing happens. I can't find out what is the problem!


Solution

  • There is a typo in the function

    void convertToUppercase(char *sPtr)
    {
        while(*sPtr != '\0') {
            *sPtr = toupper(*sPtr);
            ++*sPtr;
            ^^^^^^^^
        }
    }
    

    Instead there must be

            ++sPtr;
            ^^^^^^^
    

    This expression ++*sPtr increments the character pointed to by the pointer sPtr while this expression ++sPtr increments the pointer itself.

    Nevertheless the code has several drawbacks.

    There is a convention for string functions in the C Standard that they should return pointers to target strings. So it is musch better to declare the function like

    char * convertToUppercase(char *sPtr);
    

    Also the function toupper relies on that its argument can be represented as unsigned character.

    From the C Standard (7.4 Character handling )

    1 The header declares several functions useful for classifying and mapping characters.198) In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.

    So it will be more correctly to write

            *sPtr = toupper( ( unsigned char )*sPtr);
    

    And a for loop will be more appropriate than while loop in this case.

    Taking all this into account the function can be implemented the following way

    char * convertToUppercase(char *sPtr)
    {
        for ( char *p = sPtr; *p != '\0'; ++p ) {
            *p = toupper( ( unsigned char )*p );
        }
    
        return sPtr;
    }
    

    and called like

    printf( "\nThe string after conversion is: %s\n", convertToUppercase( string ) );