-1

I'm learning the basics in c++ and I'm trying to write a simple function that capitalizes every letter of each word in a given input. What I've written:

#include <iostream>
#include <string>
#include <vector>
#include <cctype>

int main()
{
    std::cout << "Please enter a sentence: ";
    std::vector<std::string> words;
    std::string x;

    while (std::cin >> x) {
        words.push_back((std::string) x);
    }
    std::cout << std::endl;
    std::vector<std::string>::size_type size;
    size = words.size();

    for (int j = 0; j != size; j++) {
        std::string &r = words[j];
        for (int i = 0; i != r.length(); i++) {
            r = toupper(r[i]);
            std::cout << r << std::endl;
        }
    }
}

returns the first letter of each word capitalized. For example, if I write hello world, the program returns:

H
W

Can someone please tell me what I'm doing wrong and how to fix it.

b_rabbit
  • 61
  • 5
  • 1
    Remove the `(std::string)` cast - it does nothing. – John Zwinck Jun 24 '17 at 05:07
  • *I'm trying to write a simple function that capitalizes every letter of each word in a given input* -- If you consider learning the algorithm functions "basics of C++", you could have simply used `std::transform(words[j].begin(), words[j].end(), words[j].begin(), toupper);` instead of that `i` loop. – PaulMcKenzie Jun 24 '17 at 05:21

3 Answers3

0

Your handling of each word is wrong:

    for (int i = 0; i != r.length(); i++) {
        r = toupper(r[i]);
        std::cout << r << std::endl;
    }

What you actually need is to modify only the first letter:

    r[0] = toupper(r[0]);
    std::cout << r << '\n';

As a simplfication, your loop:

std::vector<std::string>::size_type size;
size = words.size();
for (int j = 0; j != size; j++) {
    std::string &r = words[j];

Can be more succinct:

for (std::string &r : words) {
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
0
for (int j = 0; j != size; j++) {
    std::string &r = words[j];
    for (int i = 0; i != r.length(); i++) {
        r = toupper(r[i]);
        std::cout << r << std::endl;
    }
}

At r = toupper(r[i]);, you are overwriting r to be a string of length 1. So your inner for loop condition becomes false and you get out of the inner loop. So only the first letters of each word are printed out.

To fix this, save the return value of toupper to some other variable.

for (int j = 0; j != size; j++) {
    std::string &r = words[j];
    for (int i = 0; i != r.length(); i++) {
        char c = toupper(r[i]);
        std::cout << c << std::endl;
    }
}
nglee
  • 1,913
  • 9
  • 32
0

I have a Utility class that contains nothing but static functions or methods for doing string manipulation(s). Here is what my class looks like with a toUpper and toLower static method:

Utility

#ifndef UTILITY_H
#define UTILITY_H

#include <string>

class Utility {
public:
    static std::string toUpper( const std::string& str );
    static std::string toLower( const std::string& str );
private:
    Utility();
};

#endif // UTILITY_H

#include "Utility.h"
#include <algorithm>

std::string Utility::toUpper( const std::string& str ) {
    std::string result = str;
    std::transform( str.begin(), str.end(), result.begin(), ::toupper );
    return result;
}

std::string Utility::toLower( const std::string& str ) {
    std::string result = str;
    std::transform( str.begin(), str.end(), result::begin(), ::tolower );
    return result;
}

Usage:

#include <string>
#include <iostream>

#include "Utility.h"

int main() {
    std::string strMixedCase = std::string( "hEllO WOrlD" );
    std::string lower = Utility::toLower( strMixedCase );
    std::string upper = Utility::toUpper( strMixedCase );

    std::cout << lower << std::endl;
    std::cout << upper << std::endl;

    return 0;
}

Note: - This does full string manipulation of the string passed in. If you are trying to do specific characters within a string; you may need to do something different but this is a start on how to use <algorithm>'s std::transform() with ::toupper and ::tolower

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59