What will happen if I won't clear stringstream? - c++

I was doing a graph problem in TopCoder and somehow my program kept outputting wrong answer even though I thought everything should be ok with it. I spent hours and hours looking for error in my logic and, as it turned out, the problem was lying somewhere else. Here is a snippet of code I've got a question about:
int x, y;
stringstream ssx;
stringstream ssy;
for (int i = 0; i < connects.size(); i++){
neighbours.push_back(vector<int> ());
edges_cost.push_back(vector<int> ());
ssx.str(connects[i]);
ssy.str(costs[i]);
while (ssx >> x && ssy >> y){
neighbours[i].push_back(x);
edges_cost[i].push_back(y);
}
// The problem lied here. Apparently without these 2 lines
// the program outputs wrong answer. Why?
ssx.clear();
ssy.clear();
}
As you can see in the comments I managed to solve the problem. But I can't see why do I need to clear those stringstreams. What exactly is happening if I'm not doing that?

Once you've extracted all data from the stream and attempted to read "just one more character!" (which the in-built extraction to int will try to do, to find out whether there are more digits to read), its eof bit is set.
You are re-using the stream by changing its buffer's "contents", which is fine, but you need to reset that eof bit too. That's what .clear() does.
To re-use a stringstream in general:
ss.str(""); // clears data
ss.clear(); // clears all error flag bits
(In your case you're directly replacing the buffer with your new data, later on, using .str("newText!"), instead of writing .str(""), and that's fine.)
It's confusing because a function like clear sounds like it's going to clear the data, but it doesn't.

Related

C++: ctrl+d terminates program (ubuntu)

(New to C++)
I have this simple code (simplified for the question):
int main()
{
string currInput;
while (getline(cin, currInput))
{
}
cout << "wont be printed" << std::flush;
return 0;
}
I have been debugging for a while and I probably miss something:
When running it and pressing ctrl+d (after some strings or right away), it does not print the string that is after the while loop. It just stop running. I thought it might be something with flushing so I added that too.
What am I missing?
PS: When running in debug, it mentions something about sighup signal.
So, with a lot of help from #manni and #rici, we found the problem.
It turns out to be a known problem in cLion.
see sending EOF to stdin in Clion IDE
https://intellij-support.jetbrains.com/hc/en-us/community/posts/206849765-How-to-enter-EOF-Ctrl-z-in-Run-console-
https://youtrack.jetbrains.com/issue/IDEA-12514
Your error is the while loop. You should not be using a loop here. What happens is it hits this line and attempts to get input. Regardless of whether you type in anything or not, if you hit CTRL+D it will end the getline. But you have it in a while loop....so it'll hop back to the top of the loop and get another line...then another line....then another line. Welcome to your first infinite loop.
while (getline(cin, currInput))
{
}
The simplest thing would be to do just
getline(cin, currInput);
If you're starting out programming this is probably what you want to do anyway.
If you feel gutsy, read this page: http://www.cplusplus.com/reference/string/string/getline/
You'll notice that getline returns the stream you pass in. Which will evaluate to true as far the loop is concerned.

outputting binary data is missing some bytes

I have the following code
fin.close();
open = inName + ".xxx";
fin.open(open.c_str(),ios::binary);
fin>>noskipws;
while (fin>>_4byte[0])
{
fout<<_4byte[0];
}
I also have fout open in binary mode too.
However, this code was working perfectly, but suddenly after adding a loop before it it stopped outputting all the data, it is missing somewhere around 33~55 bytes.
I tried removing every other fin.open and fin.close to keep this one, but I keep on getting the same issue which is the output file is missing some data.
_4byte is an unsigned char array.
So I solved it, the issue was that I only had to add fin.close() after the while loop. I'm not sure why it happened. Can someone explain the reason?
Edit:
Okay that was not the issue.
After this code I had a cin, it actually stops writing when it reaches the cin if it hadn't done writing yet.

C++ unexpected hangtime

I am trying to write a function in my program that loads a huge text-file of 216,555 words and put them as strings into a set. This works properly, but as expected, it will hang for a few micro seconds while looping through the file. But there is something funky going on with my loop, and it's not behaving properly. Please take the time to read, I am sure there's a valid reason for this, but I have no idea what to search for.
The code, which is working by the way, is this:
ifstream dictionary;
dictionary.open("Dictionary.txt");
if(dictionary.fail())
{
cout<<"Could not find Dictionary.txt. Exiting."<<endl;
exit(0);
}
int i = 0;
int progress = 216555/50;
cout<<"Loading dictionary..."<<endl;
cout<<"< >"<<endl;
cout<<"<";
for(string line; getline(dictionary, line);)
{
usleep(1); //Explanation below (not the hangtime)
i++;
if(i%progress == 0)
cout<<"=";
words.insert(line);
}
The for-loop gets every string from the file, and inserts them in the map.
This is a console-application, and I want the user to see the progress. It's not much of a delay, but I wanted to do it anyway. If you don't understand the code, I'll try to explain.
When the program starts, it first prints out "Loading Dictionary...", and then a "<" and a ">" separated by 50 spaces. Then on the next line: "<" followed by a "=" for every 433 word it loops through (216555/50). The purpose of this is so the user can see the progress. The wanted output half way through the loop would be like this:
Loading dictionary...
< >
<=========================
My problem is:
The correct output is shown, but not at the expected time. It prints out the full progress bar, but that only after it has hanged and are done with the loop. How is that possible? The correct number of '=' are shown, but they all pop out at the same time, AFTER it hangs for some microseconds. I added the usleep(1) to make the hangtime a bit longer, but the same thing happened. The if-statement clearly works, or the '=' would've never showed at all, but it feels like my program is stacking the cout-calls for after the entire loop.
The weirdest thing of all, is that the last cout<<"<"; before the for-loop starts, is also shown at the same time as the rest of its line; after the loop is finished. Why and how?
You never flush the stream, so the output just goes into a buffer.
Change cout<<"="; to cout<<"="<<std::flush;
You need to flush the output stream.
cout << "=" << std::flush;
The program is "stacking the cout-calls". It's called output buffering, and every major operating system does it.
When in interactive mode (as your program is intended to be used), output is buffered by line; that is, it will be forced to the terminal when a newline is seen. You can also have block-buffered (fixed number of bytes between forced outputs; used when piping output) and unbuffered.
C++ provides the std::flush stream modifier to force an output at any point. It can be used like this:
cout << "=" << std::flush;
This will slow down your program a bit; the point of buffering is for efficiency. As you'll only be doing it about 51 times, though, the slowdown should be negligible.

C++ File outputting strange number, and part of code not running

Yeah. So, I'm trying to make a code for a guessing game. In this game, there's a hard mode. In hard mode, you have 15 guesses, and have to guess between 1 and 500. But my problem is this:
I'm trying to have hard mode save & display your wins/losses, but when it outputs the contents of wins.txt it outputs something like this:
Wins: 0x7fffee26df78
Losses: 0x7fffee26e178
It's really confusing me. Here's the part of the code I have for that:
ifstream losses_var("losses.txt");
ifstream wins_var("wins.txt");
losses_var>> loss;
wins_var>> win;
wins_var.close();
losses_var.close();
Then it gets called with:
cout<<"Wins: "<< wins <<"\nLosses: "<< losses <<"\n"
If you would like to see the full source code, it's here: http://pastebin.com/gPT37uBJ
My second problem:
Hard mode won't display when you win. That's pretty much the whole problem. In my code, the loop for asking users for input uses
while (guess != randNum)
So at the end bracket I have what I want the code to display when a user wins, but it just doesn't run. It just stops. I would like it if someone could help me with this. The line that has the bug is line 97 through 105. Again, source code is here: http://pastebin.com/gPT37uBJ
You've got your variable names confused
cout<<"Wins: "<< wins <<"\nLosses: "<< losses <<"\n";
should be
cout<<"Wins: "<< win <<"\nLosses: "<< loss <<"\n";
It's important to pick good variable names. One reason is so that you don't confuse yourself about what your variables mean (if you confuse yourself think how it's going to be for someone else looking at your code).
Others have already answered the output problem (win vs. wins). The other problem is probably in your logic of while loop nesting. The outer loop (while (guess != randNum)) starts, but its body contains the entire inner loop (while (guesses_left != 0)). This means that the outer condition is not checked again until the inner loop terminates, which means you've run out of guesses. Also note that if you guess correctly, inner loop will never terminate. You probably want something like this:
while (guesses_left > 0) {
// input user's guess
if (guess < randNum) {
// process it
} else if (guess > randNum) {
// process it
} else {
// it's equal, user won
// do what's necessary for a win
return 0;
}
}
// ran out of guesses
// do what's necessary for a loss
return 0;
You are not writing your variables win and loss to cout. From your pasted code, I can see that wins and losses are ofstream objects, which means you are probably seeing addresses there. I would advise you to choose more informative variable names to avoid hard to spot mistakes like this.

cin.ignore() and cin.clear() in C++

So I understand that a piece of code:
cin.ignore(80, '\n');
will clear the buffer of up to 80 characters until it hits a return (Enter key) and stop... right?
Here are the questions...
1) What is different about simply doing cin.ignore(); with no parameters? Which is better used in what situation?
2) cin.clear(); says it clears error flags... what does this mean? What are error flags and why do you want them cleared?
Thanks!
Error flags are set on a stream object whenever some operation on it fails. Once the stream is in error, no further operations can succeed on it until you reset the error state.
Here's a simple example:
std::istringstream iss("ABC123");
int n;
iss >> n;
assert(!iss);
Now the stream is in error. However, there's still data in it, and it might be worthwhile resetting and trying again:
iss.clear(); // note: this must come first!
std::string token;
iss >> token;
assert(iss);
Instead of another extraction, you could also call iss.ignore() after the clear(), in case you know what you have to ignore before it makes sense to try again.
Usually, this sort of trial-and-error isn't a very good approach, I find. I would always use getline on the stream first to get complete lines. This can only fail when the stream has been exhausted (end of file, or end of string). Then you can proceed to process each line by a dedicated parsing logic, and errors can be handled in the most appropriate way. The error flags on the original stream are too crude to allow for elegant control flow design.
I can answer your second question .
The cin.clear() function is useful when you trying to enter two different paragraphs.
For example :
std::vector<std::string> veca,vecb;
std::string x;
while(getline(std::cin,x))
veca.push_back(x);
cin.clear();
while(getline(std::cin,x))
vecb.push_back(x);
if you didn't use the cin.clear() function , the vecb got nothing, because the cin met an end-of-file before.
Hope this could help.