I have this exercise from Programming principles and practice using C by B. Stroustrup:
- Design and implement a
Name_pairs
class holding (name,age) pairs where name is astring
and age is adouble
. Represent that as avector<string>
(calledname
) and avector<double>
(calledage
) member. Provide an input operationread_names()
that reads a series of names. Provide aread_ ages()
operation that prompts the user for an age for each name. Provide aprint()
operation that prints out the (name[i]
,age[i]
) pairs (one per line) in the order determined by thename
vector. Provide asort()
operation that sorts thename
vector in alphabetical order and reorganizes theage
vector to match. Implement all "operations" as member functions. Test the class (of course: test early and often).
Here I show the part that causes the problem only for the brevity sake:
std::istream& Name_pairs::read_names(std::istream& in){
for(std::string str; in >> str; )
name.push_back(str);
in.clear();
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// the following lines are added just for testing the stream state
int x;
std::cout << "x: ";
std::cin >> x;
std::cout << x << '\n';
return in;
}
Now if I call the member function:
Name_pairs{}.read_names(std::cin);
I get prompted to enter names until I hit EOF
(Ctrl D
). At that moment I follow it by clear
and ignore
to reset the input buffer. But I am not prompted to input x
!!?
I've seen some suggestions that I should trigger a constant string as an exit mark like
std::string quit = "quit; if(str == quit) break;
but I don't want this; I want to useCtrl d
then get input again. In other words can I use the input stream after pressingCtrl D
?I've tried the very program on windows 10 and Code::blocks for windows and it worked fine! I press
Ctrl D
; the loop breaks then I am prompted to inputx
.So how could I fix the problem? thanks
CodePudding user response:
There is no standard way to reuse a closed/terminated stream, including cin
.
Once cin
is closed/terminated, it can't be reused by standard means. However, there may be non-standard, platform-specific ways to reopen it. Check your compiler/platform documentation.
That being said, nothing in the requirements you have shown will prevent you from prompting the user for the number of names to enter and then using an ordinary for
loop, or simply asking the user to enter a termination string to stop reading. Rather than relying on Ctrl-D/Ctrl-Z to stop the reading, which is very platform-specific behavior.
CodePudding user response:
It works on Windows because Ctrl D
isn't the EOF key combo on Windows, it's the end-of-text character. Ctrl Z
(plus Enter
) is the EOF marker on Windows.
If cin
actually hits EOF, it's done. Your code only works on Windows because you didn't actually hit EOF on Windows.
CodePudding user response:
The most common (and obnoxious, IMHO) way is to first ask how many.
std::vector <std::string> names;
int n;
std::cout << "How many names? ";
std::cin >> n;
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
while (n--)
{
std::string name;
getline( std::cin, name );
names.push_back( name );
}
The way I prefer is to simply terminate on the first empty line:
std::vector <std::string> names;
std::cout << "Enter names, one per line. Press ENTER twice to finish.\n";
while (true)
{
std::cout << "name? ";
std::string name;
getline( std::cin, name );
if (name.empty()) break;
names.push_back( name );
}
Now that you have a vector of names, you can ask for an age to go with each one:
std::vector <int> ages;
for (auto name : names)
{
std::cout << name << "’s age? ";
int n;
std::cin >> n;
ages.push_back( n );
}
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
Another common way, which is a variation of the “empty line” method I just showed you, is to use a sentinel value to terminate the input. It can be anything, like having the user enter “done” as the final name, or “-1” or something. You can guess my opinion on that nonsense.
As always, make sure you are reading your assignment correctly. If unsure, email your professor and ask clarification. Remember to ask an intelligent question, which shows your professor you aren’t just begging for an answer.