I know, this question has been treated tons of times.. but I can't make it work anyway.. here I paste some code:
#include <sstream>
#include "header.h"
using namespace std;
using namespace header;
int main(){
string parent, child, line, node;
int choose = 0;
tree_ptr tree_inst = new tree;
cout << "*** Start ***" << endl;
while (getline(cin, line, '\n')){
istringstream line_stream(line);
line_stream >> parent;
if (parent.compare("0") == 0) break;
while (line_stream >> child) {
if (!tree_inst->insert(parent, child)) {
cout << "*** ERROR! ***" << endl;
tree_inst->visit(tree_inst->root);
cout << "*** End ***" << endl;
return -1;
}
}
}
while (true) {
cin >> choose; //<== doesn't wait for the input, just loop forever
// on the default statement of the switch...
switch (choose) {
...
}
}
}
I've already tried to insert some cin.sync() cin.clear() cin.ignore() ..etc.. but nothing changed!
The first getline()
loop would loop forever, if you don't break it in one way or another. If done in a clean manner, this shouldn't be an issue at all. In fact I could not reproduce your error.
So the cause is either a bad sate of cin
or non numberic non space input that is still pending. To help you find out, I suggest you add some diagnostic code:
cout << "Enter free lines of text or stop to return to the menu:";
while (getline(cin, line, '\n')) { // This would loop foreved
if (line == "stop") // I added this one to exit
break; // but how do you do ?
}
while (true) { // I get no problem here
cout << "Cin status: failed=" // <===Add this simple diagnostic to
<< cin.fail() << " bad=" // check the state of the stream
<< cin.bad() << " eof=" << cin.eof() << endl;
cout << "Next char in decimal is:" // <=== Add this to show
<< cin.peek() << endl; // where in the stream you're hanging
cout << "Choose:";
cin >> choose;
cout << "selected: " << choose << endl;
}
If your stream state is not clean, despite a cin.clean()
, it's because either you closed the stream or typed in an end-of-file code at the console (Ctrl+D or Ctrl+Z depending on system) .
It the stream state is clean but the peeked char is not numeric (i.e. decimal code not between 48 and 57), it's the bad input that sets the stream in a fail state.
Looking at the diagnostic you've provided (fail=1, eof=1), it appears that after the first loop you've already eached the end of the input. So your input fails because there is no further data to read. Your input file on pastebin confirms that the last line is the "0" that you use to exit the first loop.
Following our exchanges, I understand that you've in fact redirected input from the command line (e.g. yourprogramme <yourinput.txt
) and expect your code to switch back to keyboard input once the redirected file input reaches its end. Unfortunately this is not the way it works. If you redirect input from a file, cin
will always refer to the redireted file.
To be able to mix file and keyboard input, you need to use <fstream>
and more precisely ifstream
for reading from the file and keep cin
for keyboard entry.
Here is a slightly modified code that takes the filename from the command line but without indirection (e.g. yourprogramme yourinput.txt
):
...
int main(int argc, char**argv)
{
if (argc != 2) { // if called from command line wrong arguments
cerr << "You must provide the name of the data file as command line argument\n";
return EXIT_FAILURE;
}
ifstream file(argv[1]); // open the file for reading
if (!file) { // if open failed, end the programme
cerr << "Could not open "<<argv[1]<<"\n";
return EXIT_FAILURE;
}
string line; // here your code from before
int choose = 0;
cout << "*** Loading "<<argv[1]<< " ***" << endl;
// but in the first loop replace cin with file
while (getline(file, line, '\n')){
cout << "Read: " << line<<endl;
if (line == "0") // Abridged version;-)
break;
}
file.close(); // File is no longer needed here.
while (true) { // Second loop, unchanged, using cin
cout << "Choose (9 to exit):";
if (!(cin >> choose)) // avoid looping forever if problem on cin
break;
cout << "selected: " << choose << endl;
if (choose == 9)
break;
}
return EXIT_SUCCESS;
}