0

I was inquiring about reading a sequence of words and storing the values in a vector. Then proceed to change each word in the vector to uppercase and print the out put with respect to eight word to a line. I think my code is either slow or running infinitely as i can't seem to achieve an output.

#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main() {
    string word;
    vector<string> text;
    while (getline(cin, word)) {
        text.push_back(word);
    }
    for (auto index = text.begin(); index != text.end(); ++index) {
        for ( auto it = word.begin(); it != word.end(); ++it)
            *it = toupper(*it);
        /*cout<< index << " " << endl;*/
    }

    for (decltype(text.size()) i = 0; i != 8; i++)
        cout << text[i] << endl;

    return 0;
}
dirty_sanchez
  • 69
  • 1
  • 1
  • 12
  • @Thomas: this is not about how to use toupper, it should be reopened. @dirty_sanchez: your outer `for` loop defines `index` to cycle through `text`, but you never use `index` inside it. The inner loop uses `word`, but `word` is still the last one the user entered. You should change the inner loop so that it uses `index` instead of `word`. – Fabio says Reinstate Monica Mar 01 '15 at 22:51
  • @FabioTurati OP is explicitly asking how to convert strings to upper case. The duplicate provides good answers to that. If OP has a different question, then they should be asking that question and not this one. – juanchopanza Mar 01 '15 at 22:56
  • @juanchopanza: The OP is explicitly asking about how to change each word in a vector of strings to upper case. It also includes breaking the output after every eighth word. This isn't a duplicate (at least of that question). – Jerry Coffin Mar 01 '15 at 23:09
  • @JerryCoffin Fine, I re-opened it. There are plenty of duplicates (except for the eighth word thing.) – juanchopanza Mar 01 '15 at 23:16
  • What do you mean by this: " respect to eight word to a line."? Can you provide example input and expected output? – Marcin Mar 01 '15 at 23:25
  • @Marcin the eight word line means that the output should break off after the eighth word. – dirty_sanchez Mar 02 '15 at 00:11
  • Rather than the first two `for` loops explicitly using iterators, why not learn about ranged-for loops? Rather than using decltype, why not use `auto`? – leewz Mar 02 '15 at 04:16

4 Answers4

1

At least as far as I can tell, the idea here is to ignore the existing line structure, and write out 8 words per line, regardless of line breaks in the input data. Assuming that's correct, I'd start by just reading words from the input, paying no attention to the existing line breaks.

From there, it's a matter of capitalizing the words, writing them out, and (if you're at a multiple of 8, a new-line.

I would also use standard algorithms for most of the work, instead of writing my own loops to do the pars such as reading and writing the data. Since the pattern is basically just reading a word, modifying it, then writing out the result, it fits nicely with the std::transform algorithm.

Code to do that could look something like this:

#include <string>
#include <iostream>
#include <algorithm>

std::string to_upper(std::string in) {
    for (auto &ch : in)
        ch = toupper((unsigned char) ch);
    return in;
}

int main() {
    int count = 0;

    std::transform(
        std::istream_iterator<std::string>(std::cin),
        std::istream_iterator<std::string>(),
        std::ostream_iterator<std::string>(std::cout),
        [&](std::string const &in) {
            char sep = (++count % 8 == 0) ? '\n' : ' ';
            return to_upper(in) + sep;
        });
}

We could implement capitalizing each string as a second lambda, nested inside the first, but IMO, that starts to become a bit unreadable. Likewise, we could use std::tranform to implement the upper-case transformation inside of to_upper.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
0

I'll rewrite my answer here:

Your outer for loop defines index to cycle through text, but you never use index inside it. The inner loop uses word, but word is still the last one the user entered. You should change the inner loop so that it uses index instead of word, like this:

for ( auto it = index->begin(); it != index->end(); ++it)
  • I regret to inform that it didn't work, as there were errors in the code at both index.begin() and index.end(). but i used the arrow operator instead and then proceed to run the script and as stated earlier the output is either slow or running infinitely – dirty_sanchez Mar 02 '15 at 00:17
  • @dirty_sanchez: my bad about the syntax, I've fixed it now, sorry. About the rest: have you tried debugging your code? What is the point where it slows down or hangs? And by the way, what causes the program to slow down, and what to hang? Does it depend on the input? And what is the output, are your strings at least converted to upper case? – Fabio says Reinstate Monica Mar 02 '15 at 02:00
  • the fact is after typing the words and pressing enter to obtain the uppercase conversion. I have no output at all. – dirty_sanchez Mar 02 '15 at 03:06
0

This is effectively an infinite loop:

while (getline(cin, word)) {
    text.push_back(word);
}

getline(cin, word) reads a line (ending in '\n') from stdin, and puts it into word. It then returns cin itself (which will evaluate to true if the read was successful). You seem to be using it to get a space-delimited word, rather than a whole line, but that's not what it does. Since you put it in the condition of the while, after you enter a line, it will wait for another line.

This loop only breaks when getline fails. For example, by hitting an End of File character. I expect you're using the console and pressing Enter. In that case, you are never causing getline to fail. (If you're feeding a file into stdin, it should work.)

The typical solution to this is to have some sort of way of indicating a stop (such as an "Enter an empty line to stop" or "Write \"STOP\" to stop", and then checking for that before inserting the line into the vector). For you, the solution is to read in a SINGLE line, and then break it up into words (for example, using the sstream library).

You can detect whether the program is doing actual work (rather than waiting for more input) by viewing your CPU use. In Windows, this is CTRL+SHIFT+ESC -> Performance, and -> Processes to see your program in particular. You will find that the program isn't actually using the CPU (because it's waiting for more input).

You should try inserting print statements into your program to figure out where it gets up to. You will find it never goes past the for-loop.

leewz
  • 3,201
  • 1
  • 18
  • 38
0

Short Answer

 for (string &str : vec)
    {
        transform(str.begin(), str.end(), str.begin(), [](char c) { return std::toupper(c); });
    }

Complete working code as example:

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

using namespace std;

int main()
{
    vector<string> vec;
    string str;

    while (cin >> str)
    {
        vec.push_back(str);
    }

    for (string &str : vec)
    {
        transform(str.begin(), str.end(), str.begin(), [](char c)
                  { return toupper(c); });
    }

    for (auto str : vec)
    {
        cout << str << endl;
    }
    return 0;
}