How to change each word in a string vector to uppe

2019-09-18 02:16发布

问题:

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;
}

回答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.



回答2:

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)


回答3:

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.