Home > Software engineering >  Make first letter of every word capital after removing vowels
Make first letter of every word capital after removing vowels

Time:10-26

My code works to delete any vowels and prints the first letter of the word as a capital letter. How can I get my expected output to work? If the value is " I am Iron Man" (with a leading space), it works and prints "M Rn Mn". However, without the space at the beginning of the string, my output is "m Rn Mn" but the expected output is "M Rn Mn".

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

int main() {
    
    char str[] = "I am Iron Man";
    int i, j, len = 0;


    len = strlen(str);
    // Accepting input.

    for (i = 0; i < len; i  ) {
        // Check vowels.
        if (str[i] == 'a' || str[i] == 'e' || str[i] == 'i' || str[i] == 'o' || str[i] == 'u' ||
            str[i] == 'A' || str[i] == 'E' || str[i] == 'I' || str[i] == 'O' || str[i] == 'U') {

            // delete vowel syntax
            for (j = i; j < len; j  ) {

                // Store after removing vowels
                str[j] = str[j   1];
            }
            i--;
            len--;
        }
        str[len   1] = '\0';
    }

    for(i=0; str[i]!='\0'; i  )
    {
        //check first character is lowercase alphabet
        if(i==0)
        {
            if((str[i]>='a' && str[i]<='z'))
                str[i]=str[i]-32; //subtract 32 to make it capital
            continue; //continue to the loop
        }
        if(str[i]==' ')//check space
        {
            //if space is found, check next character
              i;
            //check letter if lowercase
            if(str[i]>='a' && str[i]<='z')
            {
                str[i]=str[i]-32; //subtract 32 to make it capital
                continue; //continue to the loop
            }
        }
    }
       printf("%s", str);
       return 0;
}

CodePudding user response:

Your problem lies with excessive use of the continue statement in the second for loop. The second continue is just plain pointless, as control reaches the end of the loop, anyway, after the point where you have that.

But the first continue is actually causing the fault: after removal of the vowels, the first character in the modified string will be a space – so, the first if block inside the second loop will be entered, and that will skip the check for a lowercase letter following the space.

Removing those continue statement will fix your code.

Also, note that you can use the islower and toupper functiosn to check for lowercase letters and convert to uppercase:

#include <stdio.h>
#include <string.h>
#include <ctype.h> // For islower and toupper

int main()
{
    char str[] = "I am Iron Man";
    size_t i, j, len = 0;

    len = strlen(str);
    // Accepting input.

    for (i = 0; i < len; i  )
    {
        // Check vowels.
        if (str[i] == 'a' || str[i] == 'e' || str[i] == 'i' || str[i] == 'o' || str[i] == 'u' ||
            str[i] == 'A' || str[i] == 'E' || str[i] == 'I' || str[i] == 'O' || str[i] == 'U') {
            // delete vowel syntax
            for (j = i; j < len; j  )
            {
                // Store after removing vowels
                str[j] = str[j   1];
            }
            i--;
            len--;
        }
        str[len   1] = '\0';
    }

    for (i = 0; str[i] != '\0'; i  )
    {
        //check first character is lowercase alphabet
        if (i == 0)
        {
            if (islower(str[i])) {
                str[i] = toupper(str[i]);
            }
            // A "continue" here is wrong ... it will skip the following check for a lowercase letter
        }
        if (str[i] == ' ') //check space
        {
            //if space is found, check next character
              i;
            //check letter if lowercase
            if (islower(str[i]))
            {
                str[i] = toupper(str[i]);
                // No need for a "continue" here ... we're already at the end of the loop
            }
        }
    }
    printf("%s\n", str);
    return 0;
}

CodePudding user response:

I have another solution for you, that may be a bit easier to comprehend:

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

int main(void) {
    char str[] = "I am Iron Man";
    char *in;
    char *out;
    int up = 1; // very simple state, if "up" then next character should be made upper

    for (in = str, out = str; *in; in  ) {
        if (strchr("aeiouAEIOU", *in) != NULL) {
            // do nothing
        } else if (*in == ' ') {
            *out   = *in;
            up = 1; // we see a space, so next letter should be upper
        } else if (up) {
            *out   = toupper(*in);
            up = 0; // we see a letter (or other character), ignore case
        } else {
            *out   = *in;
        }
    }
    *out = '\0';

    printf("%s\n", str);
}

Or, if you don't like/understand the pointer syntax:

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

int main(void) {
    char str[] = "I am Iron Man";
    int i;
    int o;
    int up = 1; // very simple state, if "up" then next character should be made upper

    for (i = 0, o = 0; str[i]; i  ) {
        if (strchr("aeiouAEIOU", str[i]) != NULL) {
            // do nothing
        } else if (str[i] == ' ') {
            str[o  ] = str[i];
            up = 1; // we see a space, so next letter should be upper
        } else if (up) {
            str[o  ] = toupper(str[i]);
            up = 0; // we see a letter (or other character), ignore case
        } else {
            str[o  ] = str[i];
        }
    }
    str[o] = '\0';

    printf("%s\n", str);
}

In both cases, a very simple state is used. For more complex conditions, you should learn about state machines. In this case, the up state indicates that the next letter should be capitalised.

Note that if you want to remove leading spaces, after "removing" the vowels, you need to modify the logic a bit:

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

int main(void) {
    char str[] = "I am Iron Man";
    char *in = str; // we initialize in and out here already
    char *out = str;
    int up = 1; // very simple state, if "up" then next chacter should be made upper

    // we skip leading vowels AND spaces, this is a special case
    while (*in && (strchr("aeiouAEIOU ", *in) != NULL)) {
        in  ;
    }

    // now we are at the first character that is not a vowel or space
    for ( ; *in; in  ) {
        if (strchr("aeiouAEIOU", *in) != NULL) {
            // do nothing
        } else if (*in == ' ') {
            *out   = *in;
            up = 1; // we see a space, so next letter should be upper
        } else if (up) {
            *out   = toupper(*in);
            up = 0; // we see a letter (or other character), ignore case
        } else {
            *out   = *in;
        }
    }
    *out = '\0';

    printf("%s\n", str);
}

Well now you have a few examples to study that take a bit of a different approach. See if you understand the logic, and try to make it so that other characters like e.g. ( and ) also delimit words.

CodePudding user response:

One of the problems is that you've got too much code. It iterates through the entire array once to strip out vowels, then again to adjust the case of the first letter of each word. Imagine this is processing data that is measured in Gb. A second pass is unnecessary.

(And, there are standard library functions like isalpha() and toupper() that you should use. Don't write code with "magic numbers".)

It's worth studying a program's 'flow control', without resorting to arbitrary 'continue' statements to affect that flow.

It's also worth starting from scratch with a minimal block of code in main(), then developing your algorithm in a function (or several). Avoid the tendency to have one long, linear program all inside main(). If you can put functionality into 'compartments', each can be developed and tested and forgotten about as the program grows more complex.

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

// A single pass "compacts" the data (no vowels) while also using some single operations
//tracking changing from one word to the next (first letter to uppercase.)
char *func( char *str ) {
    for ( int d = 0, s = 0, up = 0; (str[d] = str[s]) != '\0'; s  )
        if( !strchr( " aeiouAEIOU"   !!up, str[d] ) ) {
            if( str[d] == ' ' )
                up = 1;
            else if( up   < 2 )
                up  , str[d] = (char)toupper( (unsigned char)str[d] );
            d  ; // 'd'estination idx only increments here!
        }

    return str;
}

int main(void) {
    // sample test strings
    char *strs[] = {
        "I am Iron Man",
        "  I am   Iron Man   ",
        "Iron Man am I",
        "   Iron   Man   am  I",
        "The man of steel",
        "  The  man  of  steel",
    };

    for( size_t i = 0; i < sizeof strs/sizeof strs[0]; i   )
        puts( func( strs[i] ) );

    return 0;
}
M Rn Mn
M   Rn Mn
Rn Mn M
Rn   Mn   M
Th Mn F Stl
Th  Mn  F  Stl
  • Related