Search code examples
cfunctionrecursionc-stringscapitalize

How can i make first letter of all words in a string uppercase recursively?


I wonder how can i make this. I don't want any iteration or isalpha() and toupper() functions. We want to use our own code to read input. We assume that user enters all characters lowercase. This is what i've tried so far:

define MAX_LENGTH 100

int read_line(char str[],int);
void capitalize(char[]);

int main (void){
    char A[MAX_LENGTH];
printf("Enter a text \n");
read_line(A, MAX_LENGTH);

capitalize(A);
puts(A);


}

int read_line(char str[],int n){
    int ch,i=0;

    while ((ch = getchar()) != '\n'){
        if(i<MAX_LENGTH)
            str[i++] = ch;
    }
    str[i] = '\0';
    return i;
}

void capitalize(char str[]){
 int x = strlen(str);
 static int i = 0;
    if(str[i]=='\0')
    return;
    if(str[i-1]==' '|| i == 0)
      str[i] -= 32;
      i++;
      return capitalize(&str[i]);
 }

Output is like this:

Enter a text:

asdf sdf df

Asdf sdf df

What is wrong with my code?


Solution

  • You code is invalid. For example even the function read_line

    int read_line(char str[],int n){
        int ch,i=0;
    
        while ((ch = getchar()) != '\n'){
            if(i<MAX_LENGTH)
                str[i++] = ch;
        }
        str[i] = '\0';
        return i;
    }
    

    is incorrect at least because when i is equal to MAX_LENGTH -1 there is an access memory beyond the character array

    str[i] = '\0';
    

    That is the condition of the loop is initially written incorrectly.

    As for the recursive function then it can look for example the following way.

    #include <stdio.h>
    
    int is_blank( char c )
    {
        return c == ' ' || c == '\t';
    }
    
    char * capitalize( char *s )
    {
        if ( *s )
        {
            int blank = is_blank( *s );
    
            if ( !blank )
            {
                *s &= ~' ';
            }
    
            capitalize( s + 1 );
    
            if ( !blank && !is_blank( *( s + 1 ) ) && *( s + 1 ) )
            {
                *( s + 1 ) |= ' ';
            }
        }
    
        return s;
    }
    
    int main(void) 
    {
        char s[] = "hello everybody. how do you do?";
    
        puts( s );
        puts( capitalize( s ) );
    
        return 0;
    }
    

    The program output is

    hello everybody. how do you do?
    Hello Everybody. How Do You Do?
    

    Here is a similar demonstrative program but with your fixed function read_line.

    #include <stdio.h>
    
    #define MAX_LENGTH  100
    
    int is_blank( char c )
    {
        return c == ' ' || c == '\t';
    }
    
    char * capitalize( char *s )
    {
        if ( *s )
        {
            int blank = is_blank( *s );
    
            if ( !blank )
            {
                *s &= ~' ';
            }
    
            capitalize( s + 1 );
    
            if ( !blank && !is_blank( *( s + 1 ) ) && *( s + 1 ) )
            {
                *( s + 1 ) |= ' ';
            }
        }
    
        return s;
    }
    
    size_t read_line( char *s, size_t n )
    {
        int ch;
        size_t i = 0;
    
        while ( i + 1 < n && ( ch = getchar() ) != EOF && ch != '\n' )
        {
            s[i++] = ch;
        }
    
        s[i] = '\0';
    
        return i;
    }
    
    int main(void) 
    {
        char s[MAX_LENGTH];
    
        read_line( s, MAX_LENGTH );
    
        puts( s );
    
        puts( capitalize( s ) );
    
        return 0;
    }
    

    If to enter the string

    hello everybody. how do you do?
    

    then the program output will be the same as shown above.

    hello everybody. how do you do?
    Hello Everybody. How Do You Do?
    

    If the bit-wise operations is unclear for you then you can substitute this statement

    for this statement

    *s &= ~' ';
    

    for this statement

    *s -= 'a' - 'A';
    

    and this statement

    *( s + 1 ) |= ' ';
    

    for this statement

    *( s + 1 ) += 'a' - 'A';
    

    If to use your approach to the implementation of a recursive function with a static variable then it will be interesting to you why your function does not work will not be?

    Let's consider it ignoring the first statement with the call of strlen.

    void capitalize(char str[]){
     int x = strlen(str);
     static int i = 0;
        if(str[i]=='\0')
        return;
        if(str[i-1]==' '|| i == 0)
          str[i] -= 32;
          i++;
          return capitalize(&str[i]);
     }
    

    First of all after the first call the function for one string you may not call it a second time for another string because the static variable i will not be already equal to 0.

    The condition of the if statement should be written at least like

        if ( i == 0 || str[i-1]==' ' )
    

    that is the order of sub-expressions shall be changed.

    The return statement shall not contain an expression

          return capitalize(&str[i]);
    

    you could just write

          capitalize(&str[i]);
    

    Nevertheless the initial value of the pointer str was changed. However within the function you are using the index i relative the initial value of str of the first call of the function.

    And I am sure it is interesting to you how correctly to rewrite the function, is not it?

    The function can look the following way as it is shown in the demonstrative program below.

    #include <stdio.h>
    
    #define MAX_LENGTH  100
    
    int is_blank( char c )
    {
        return c == ' ' || c == '\t';
    }
    
    char * capitalize( char *s )
    {
        static size_t i = 0;
    
        if ( *( s + i ) )
        {
            if ( !is_blank( s[i] ) && ( i == 0  || is_blank( s[i-1] ) ) )
            {
                s[i] -= 'a' - 'A';
            }
    
            ++i;
    
            capitalize( s );
    
            --i;
        }
    
        return s;
    }
    
    size_t read_line( char *s, size_t n )
    {
        int ch;
        size_t i = 0;
    
        while ( i + 1 < n && ( ch = getchar() ) != EOF && ch != '\n' )
        {
            s[i++] = ch;
        }
    
        s[i] = '\0';
    
        return i;
    }
    
    int main(void) 
    {
        char s[MAX_LENGTH];
    
        read_line( s, MAX_LENGTH );
    
        puts( s );
    
        puts( capitalize( s ) );
    
        return 0;
    }