the default contents in the buffer of a stream - c++

I have a little confused about the result of two slightly different piece of code like this:
FILE* file=fopen("test.txt","w");
char buffer[6]="hello";
char arr[6]="haloo";
//setbuf(file,buffer);
fputs(arr,file);
//fflush(file);
As you can see I firstly commented out two line of code. So the buffer would not be flushed until I close the program, at which time the file stream will be closed too. And then, as what I expect, the program would write the haloo to the test.txt as soon as I close the program. And the same things happened When I don't commented out those two lines. Like this:
setbuf(file,buffer);
fputs(arr,file);
fflush(file);
But, when I only commented out only the flush(file) line of code, like this:
setbuf(file,buffer);
fputs(arr,file);
//fflushed(file);
strange thing happen. I got things like 2800 c579 7a in my test.txt when I close my program.
And then I try to change the buffer a little bit, to something like this:
char buffer[5]="hell"; //change the contents a little bit
char arr[5]="halo"; // also change a little bit
setbuf(file,buffer);
fputs(arr,file);
//fflush(file);
Then I got 00c5 797a in my text.txt.
So I wonder if this is any undefined behavior or default pattern that I don't know.

I think you want to terminate your buffer with a '\0'. Check that out.
If you are not calling fclose, there might be an undefined behaviour problem because of setbuf, see http://man7.org/linux/man-pages/man3/setbuf.3.html.
Check adding a fclose at the end of the program, this will make sure the fflush is enforced and the stream is cleanly closed, while at the same time avoiding the above mentioned bug.

Related

gdb debugger unfamiliar with code displayed

I am fairly new to using gdb debugger and so coming across the code being displayed when I ran gdb left me having no use for the debugger. I am unfamiliar with the code being displayed but a did a little research and I assume I accidentally opened up a "thread"? It's hard to explain something I do not understand but I will link a picture explaining what I am talking about. Basically I want to revert back to the "basic" display of my actual code and not this: displayed by the debugger
Your program called one of scanf family of functions, with a NULL stream.
Usually this happens when you don't check for errors. For example:
FILE *fp = fopen("/file/which/does/not/exist", "r");
char ch;
fscanf(fp, "%c", &ch); /* BUG: should check fp!=NULL first. */
You should always check return value from any function that may fail.
You can see which code called into the fscanf with GDB where command.

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.

While loop construct in combination with getline function that continues until EOF

I am in a bind right now and the most frustrating thing about this is that I know what the problem is but, I cannot fix it :(...
My goal is to ultimately use getline to read lines of strings from redirected input (from a text file) and keep going until EOF is reached.
Example text file (contents):
Hello World!
Good Bye.
My source code(only includes the section where it will not work):
while (!(getline(std::cin, s_array)).eof()){ // it won't read second line
//do some awesome stuff to the first line read!
}
As far as I know, getline reads everything upto the newline and stops so how do we get it to keep reading because it always stops at Hello World!.
Use while (getline(std::cin, s_array)) { } instead.
std::getline() returns istream&, and istream::operator void*() makes it evaluated as false whenever any error flag is set.
You should definitely read Joseph Mansfield's blog post titled "Don't condition input on eof()" which describes this pitfall in details and provides a well justified guideline.

What will happen if I won't clear stringstream?

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.

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.