Lance Ocampo
Lance Ocampo

Reputation: 1

C++ First letter of every word must be uppercased

I'm a student and new to programming

I'm trying to make every first letter of every word uppercased and the rest lowercased.

The output currently is that only the first word is being printed even though I'm typing in 2 or more words.

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    int i;
    char str[100];
    char rev;
    int len = 0;

    cout << "Enter a string: ";
    cin >> str;
    
    len = strlen(str);
    
    for (i = 0; i < len; i++)
    {
        if (i == 0)
        {
            str[i] = toupper(str[i]);
        }
        else
        {
            str[i] = tolower(str[i]);
        }
        cout << str[i];
    }
}

Upvotes: 0

Views: 473

Answers (4)

WBuck
WBuck

Reputation: 5503

As others have pointed out, once std::cin encounters a space it will stop reading.

The code below is still reading 1 word at a time. I like how it essentially does a string split for you without much effort on your part.

I then use iterator's to traverse the characters in the std::string.

The skip function was needed to remove any space in the stream so that I could then check for a newline (\n) character. If a newline character is detected, break out of the loop.

static std::istream& skip( std::istream& stream ) 
{
    static const std::set<char> needles{ ' ', '\t', '\r', '\v' };
    while ( needles.find( static_cast<char>( stream.peek( ) ) ) != needles.end( ) ) 
    {
        stream.ignore( );
    }
    return stream;
}

int main( ) 
{
    const auto to_upper{ [ ]( auto begin, auto end ) { 
        std::transform( begin, end, begin, [ ]( unsigned char c ) { 
            return std::toupper( c );
        } );
    } };

    const auto to_lower{ [ ]( auto begin, auto end ) { 
        std::transform( begin, end, begin, [ ]( unsigned char c ) { 
            return std::tolower( c );
        } );
    } };

    std::cout << "Enter a strings\n";

    for( std::string input{ }; std::cin >> input; ) 
    {
        to_upper( input.begin( ), input.begin( ) + 1 );
        to_lower( input.begin( ) + 1, input.end( ) );
    
        std::cout << input << ' ';
        if ( std::cin >> skip && std::cin.peek( ) == '\n' ) 
        {
            std::cout << '\n';
            break;
        }
    }
}

Upvotes: 0

Pepijn Kramer
Pepijn Kramer

Reputation: 13076

Note your code still has more of a "c" flavor to it then a "c++" flavor. Managing the sizes of your own arrays and using indices can still be used, but its better left to classes of the standard library. So if you want a string then use std::string and not char str[100]; Also note that string has a length method and that converting a string to an array of characters is not needed. Have a look at this example:

#include <string>
#include <set>
#include <iostream>

// do not teach yourself to type : using namespace std.
// just type std:: in front of every std type
// it will avoid problems in bigger projects later

// for anything you do make a function with a readable name.
// pass by value so we get a copy of the string to work on.
std::string capitalize(std::string string)
{
    // create a static set of unique characters that will
    // be used to recognize where new words begin.
    // I added a few, maybe more are needed. 
    static std::set<char> delimiters{ ' ', ',', '.', '\n' };

    // first character of a sentence should always be uppercase
    bool make_next_char_uppercase = true;

    // loop over all the characters in the input string.
    // this is called a range based for loop and is 
    // an improvement over the indexed for loop
    // used since "C", this style of loop can't go outside
    // the bounds of the array.
    // use a reference so we can modify the characters in place
    for (char& c : string)
    {
        if (make_next_char_uppercase) c = toupper(c);
        
        // the next line of code is C++20 syntax.
        // but it means that if you encounter a word delimiter
        // then the next character read must be changed to uppercase.
        make_next_char_uppercase = delimiters.contains(c);

        // for earlier versions of C++ use
        //make_next_char_uppercase = (std::find(delimiters.begin(), delimiters.end(), c) != delimiters.end());
    }

    return string;
}

int main()
{
    auto output = capitalize("the quick brown fox jumps over the lazy dog!\nalso text after a newline and a,should be uppercase!");
    std::cout << output;
}

Upvotes: 1

std::cin stop reading when it sees a space. If you want to read until a newline, use getline(). Also, as in C++ use std::string instead of C-style string. And you shouldn't use using namespace std; as it's consider bad practise as show in here.

My "recommend" code:

#include <iostream>
#include <string>
#include <cctype>
int main()
{
    std::string str;
    char rev{};

    std::cout << "Enter a string: ";
    getline(std::cin, str);

    int len {str.size()};

    for (int i = 0; i < len; i++)
    {
        if (i == 0)
        {
            str[i] = toupper(str[i]);
        }
        if (str[i] == ' ')
        {
            str[i + 1] = toupper(str[i + 1]);
        }
        std::cout << str[i];
    }
}

Upvotes: 0

Deepank
Deepank

Reputation: 1

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int i;
char str[100];
char rev;
int len = 0;

cout << "Enter a string: ";
cin.getline(str, 100);

len = strlen(str);

for (i = 0; i < len; i++)
{
    if (i == 0)
    {
        str[i] = toupper(str[i]);
    }
    if (str[i] == ' ')
    {
        str[i + 1] = toupper(str[i + 1]);
    }
    cout << str[i];
}
}

Upvotes: 0

Related Questions