Search code examples
ccharc-stringscase-sensitivefunction-definition

I wrote a function that takes one string and, capitalize the last character of each word in uppercase and the rest in lowercase.What's wrong with it?


I have a function that takes one string and, capitalize the last character of each word in uppercase and the rest in lowercase. If a word has a single letter, it must be capitalized.

My code:

#include <string.h>
char* rcapitalize(char* p)
{
    char space = 32,tab = 9;
    int len = strlen(p);
    for (int i = 0;i<len;i++)
    {
        if (p[i]>='a' && p[i]<='z' && (p[i+1])==space ||p[i]>='a' && p[i]<='z' && (p[i+1])=='\0' ||p[i]>='a' && p[i]<='z' && (p[i+1])==tab)
        {
            p[i]=p[i]-32;
        }
        else if (p[i]>='A' && p[i]<='Z' && (p[i+1])!=tab ||p[i]>='A' && p[i]<='Z' && (p[i+1])!=space || p[i]>='A' && p[i]<='Z' && (p[i+1])!='\0')
        {
            p[i] = p[i]+32;
        }
        
        
    }
    return p;
}
Input: "a FiRSt LiTTlE TESt"
Return Value: "A firsT littlE tesT"
My return value: "A firsT little tesT"

Why it's lowercasing the 'E' in a word "littlE"?


Solution

  • The word "LiTTlE" is the only word in the string that contains the last letter in the upper case.

    The first sub-expression of the else if statement

    p[i]>='A' && p[i]<='Z' && (p[i+1])!=tab
    

    will always evaluate to true because the character p[i+1] is indeed unequal to tab. So the full expression will also always evaluate to true.

    Instead of the logical OR operator you have to use the logical AND operator in the full expression of this else if statement.

    For example it could look like

    else if ( p[i] >= 'A' && p[i] <= 'Z' && p[i+1] != tab && p[i+1] != space && p[i+1] != '\0' )
    

    Nevertheless the program looks bad. It will not work correctly for example if instead of the ASDII character table there will be used the EBCDIC character table.

    For starters do not use magic numbers like 32. The used logical expressions are too compound. The call of strlen is redundant.

    Here is a demonstrative program that shows how the function can be written.

    #include <stdio.h>
    #include <ctype.h>
    
    char * rcapitalize( char *s )
    {
        for ( char *p = s; *p; ++p )
        {
            unsigned char c1 = p[0], c2 = p[1];
            
            if ( isalpha( c1 ) )
            {
                if ( isspace( c2 ) || c2 == '\0' )
                {
                    *p = toupper( c1 );
                }
                else if ( isupper( c1 ) )
                {
                    *p = tolower( c1 );
                }
            }
        }
        
        return s;
    }
    
    int main(void) 
    {
        char s[] = "a FiRSt LiTTlE TESt";
        
        puts( rcapitalize( s ) );
        
        return 0;
    }
    

    The program output is

    A firsT littlE tesT