I am going through C++ Primer (Lippman) and am in chapter 3. Exercise 3.17 reads as follows:
Read a sequence of words from cin and store the values in a vector. After you've read all the words, process the vector and change each word to uppercase. Print the transformed elements, eight words to a line.
Two things:
1. I don't think the while loop is storing the words in the vector bc whenever I've tried to access the elements in text nothing prints out.
2. Since I've added toupper(), the compiler says there
At this point I’ve spent over three hours on this one question and I can’t help but feel like I’m missing something simple.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
usingnamespace std;
using std::string;
using std::vector;
int main() {
string word;
vector<string> text;
while (cin >> word) {
text.push_back(word);
for (auto &i : text)
i = toupper(i);
}
}
'text' is your vector<string>, not an individual string.
Therefore each 'i' in text in your for-each loop is a string, but toupper needs to be passed an individual character -- it does not know what a string is.
To access the string you just push_back'd, you can do text.back().
So you could do,
1 2
for (auto &ch : text.back())
ch = toupper(ch);
Alternatively, you could write a helper function, something like:
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
usingnamespace std;
using std::string;
using std::vector;
int main()
{
string word;
vector<string> text;
while(cin >> word)
{
text.push_back(word);
for(auto &i : text)
i = toupper(i);
}
}
Next: Your instructions say:
Read a sequence of words from cin and store the values in a vector. After you've read all the words, process the vector and change each word to uppercase.
You are presently trying to do both of these steps in the same loop, they should be separated into different loops.
Also your for() loop is processing the vector not a string. Which means that you're trying to call toupper() on a string not a single character (which is why your program should not compile). The toupper() function works on single characters, not strings.
#include <vector>
#include <string>
#include <iostream>
#include <cctype>
int main()
{
std::vector<std::string> vs;
for (std::string line; std::cout << "Enter word <CR> to terminate: " && std::getline(std::cin, line) && !line.empty(); vs.push_back(line));
for (auto& s : vs)
for (auto& c : s)
c = std::toupper(c);
for (int c = 1; constauto & s : vs)
std::cout << s << (c++ % 8 ? ' ' : '\n');
}
NB requires C++20 for initialisation within a range-for. If your compiler doesn't yet support this, move the int c = 1; outside of the for loop.
Enter word <CR> to terminate: qwe
Enter word <CR> to terminate: asd
Enter word <CR> to terminate: zxc
Enter word <CR> to terminate: tyyu
Enter word <CR> to terminate: gh
Enter word <CR> to terminate: uuii
Enter word <CR> to terminate: hggff
Enter word <CR> to terminate: wee
Enter word <CR> to terminate: ggh
Enter word <CR> to terminate: kjhh
Enter word <CR> to terminate:
QWE ASD ZXC TYYU GH UUII HGGFF WEE
GGH KJHH
Read a sequence of words from cin and store the values in a vector. After you've read all the words, process the vector and change each word to uppercase. Print the transformed elements, eight words to a line.
You need to look at them in a different way.
1. Read a sequence of words from cin and store the values in a vector.
2. After you've read all the words, process the vector and change each word to uppercase.
3. Print the transformed elements, eight words to a line.
Complete each step 1 at a time.
First input words and create the vector.
Step 2. Now that you have a vector of strings where eace element of the vector is an individual string you can process each string and shange it to uppercase.
Step 3 is to print the vector.
It is much easier to do 1 part at a time than to try and work on the whole at 1 time.
As you work on each compile often and test as needed.
usingnamespace std;
using std::string;
using std::vector;
Pick 1 or the other, but not both. The usingnamespace std; should be avoided. The 2 using statements that follow are slightly better, but still should be avoided. Either is not helping you.
As I started to work with your program I first noticed that the while loop is an endless loop with no way out.
Using formatted input, std::cin >> word there is no way to cause "cin" to fail and it will not accept just the enter key. So what you have is an endless loop with no way out.
With the input from Furry Guy I ended up with this:
1 2 3 4 5 6 7
while (std::cout<<" Enter a word (Enter to quit): " && std::getline(std::cin, word) && !(word.empty()))
{
//if (!(word.size())) // <--- An Alternative to the big while condition.
// break;
text.push_back(word);
}
The commented code in the loop is if you do not want to use the last "&&", but i would suggest keeping it.
The "cout" at the beginning of the while condition is needed otherwise you end up staring at a blank screen wondering what to do. Or even wondering if the program
is running.
Using formatted input, std::cin >> word there is no way to cause "cin" to fail and it will not accept just the enter key. So what you have is an endless loop with no way out.
ctrl-z keyboard input will cause 'cin' to fail for Windows. But I prefer getline() as per my previous post.