Postpone standard output in the end - c++

Many warning messages (via std::cout) might be printed out during the process. Is there a way to postpone the printing of the warning messaged in the end of the program? There are huge amount of the processing information will be printed. I'm planing to have all the warnings together in the end rather than scattered around.
More background:
code is already there.
there are about 50 warning messages within the code (in case if there is some sort of delay( ) function, I don't want to add 50 times, would be nice if there is an globally delaye/postpone function for stand output)
Thanks

One way to do it is to send everything to a stringstream, and then print at the end.
For example:
#include <iostream>
#include <sstream>
int main(){
int i = 5, j = 4;
std::stringstream ss;
std::cout << i * j << std::endl;
ss << "success" << std::endl;
std::cout << j + i * i + j << std::endl;
ss << "failure" << std::endl;
std::cout << ss.str() << std::endl;
return 0;
}
Output:
20
33
success
failure

If you're just trying to delay all printing of std::cout what you can do is redirect standard out to a string stream that acts as a buffer. It's pretty simple and avoids all of the dup, dup2, and piping stuff that one might be inclined to try.
#include <sstream>
// Make a buffer for all of your output
std::stringstream buffer;
// Copy std::cout since we're going to replace it temporarily
std::streambuf normal_cout = std::cout.rdbuf();
// Replace std::cout with your bufffer
std::cout.rdbuf(buffer.rdbuf());
// Now your program runs and does its thing writing to std::cout
std::cout << "Additional errors or details" << std::endl;
// Now restore std::cout
std::cout.rdbuf(normal_cout);
// Print the stuff you buffered
std::cout << buffer.str() << std::endl;
Also in the future, you should really use a buffer for errors from the start OR at a minimum write errors and logging to std::cerr so that your normal runtime print outs aren't cluttered with errors.

Related

How to automatically set stream mode back to default [duplicate]

This question already has answers here:
Restore the state of std::cout after manipulating it
(9 answers)
Closed 4 years ago.
C++ steam objects have state. If one write a piece of code like
using namespace std;
cout << hex << setw(8) << setfill('0') << x << endl;
forgetting setting the stream state back. This will cause problems in some other unrelated codes. It's tedious to do "set" and "set back" pair matching. Besides from that, it seems to me it's also against convention behind RAII.
My question is: is it possible, with only a thin layer of wrapping, to make those state manipulations RAII-like. That is, right after the end of an expression by semicolon, stream state is automatically set back to default.
Update: Following the link provided by #0x499602D2, one workaround might be something like
#include <boost/io/ios_state.hpp>
#include <ios>
#include <iostream>
#include <ostream>
#define AUTO_COUT(x) {\
boost::io::ios_all_saver ias( cout );\
x;\
}while(0)
Then one can use the macro like
AUTO_COUT(cout << hex << setw(8) << setfill('0') << x << endl);
BTW, it might be a good idea to add a lock field to those saver class of boost::io::ios_state, in case funny things occur in a multi-threading program. Or they have already done so?
I'm going to suggest an alternative approach. The manipulators apply to the std::[i|o]stream instance, but they do nothing with regards to the std::[i|o]streambuf which is managed by that std::[i|o]stream.
Therefore, you can create your own std::[i|o]stream, which will have its own formatting state, but writing to the same buffer std::cout uses:
#include <iostream>
#include <iomanip>
int main()
{
std::cout << std::hex << 32 << "\n";
std::ostream os(std::cout.rdbuf());
os << 32 << "\n" << std::hex;
std::cout << std::dec;
os << 32 << "\n";
std::cout << 32 << "\n";
}
Output:
20
32
20
32
Live on Coliru
This uses only features from standard library, and since the original stream is not touched, applying manipulators is trivially thread safe (because each thread operates on a different stream). Now, the actual writes and reads' thread safety depends on the thread safety of the managed stream buffer.
I once wrote a utility class for my personal use. (I don't know whether it is as perfect as the boost code probably is but it worked for me – so, I dare to share.)
#include <iostream>
#include <iomanip>
/** provides a helper class to work with streams.
*
* It stores current format states of a stream in constructor and
* recovers these settings in destructor.
*
* Example:
* <pre>
* { // backup states of std::cout
* IOSFmtBackup stateCOut(std::cout);
* // do some formatted output
* std::cout
* << "dec: " << std::dec << 123 << std::endl
* << "hex: " << std::hex << std::setw(8) << std::setfill('0')
* << 0xdeadbeef << std::endl;
* } // destruction of stateCOut recovers former states of std::cout
* </pre>
*/
class IOSFmtBackup {
// variables:
private:
/// the concerning stream
std::ios &_stream;
/// the backup of formatter states
std::ios _fmt;
// methods:
public:
/// #name Construction & Destruction
//#{
/** constructor.
*
* #param stream the stream for backup
*/
explicit IOSFmtBackup(std::ios &stream):
_stream(stream), _fmt(0)
{
_fmt.copyfmt(_stream);
}
/// destructor.
~IOSFmtBackup() { _stream.copyfmt(_fmt); }
// disabled:
IOSFmtBackup(const IOSFmtBackup&) = delete;
IOSFmtBackup& operator=(const IOSFmtBackup&) = delete;
//#}
};
int main()
{
{ // backup states of std::cout
IOSFmtBackup stateCOut(std::cout);
// do some formatted output
std::cout
<< "dec: " << std::dec << 123 << std::endl
<< "hex: " << std::hex << std::setw(8) << std::setfill('0')
<< 0xdeadbeef << std::endl
<< "123 in current: " << 123 << std::endl;
} // destruction of stateCOut recovers former states of std::cout
// check whether formatting is recovered
std::cout << "123 after recovered: " << 123 << std::endl;
return 0;
}
Compiled and tested on ideone (life demo).
Output:
dec: 123
hex: deadbeef
123 in current: 7b
123 after recovered: 123

Why does ifstream read() behave differently in two different programs?

I'm trying to write a program that reads in an OpenGL shader from a .txt file. I've actually already done this a few days ago, this was the code I used:
char vShaderData[2000];
char fShaderData[2000];
void readShaders() {
std::ifstream vShaderF;
std::ifstream fShaderF;
vShaderF.open("shaders//vertexShader.txt");
fShaderF.open("shaders//fragShader.txt");
if (vShaderF.is_open() && fShaderF.is_open()) std::cout << m << "Shader read success" << std::endl;
else std::cout << "Shader read fail" << std::endl;
std::cout << m << "vertex shader: " << std::endl;
vShaderF.read(vShaderData, 2000);
for (int i = 0; i < 2000; i++) {
std::cout << vShaderData[i];
}
std::cout << std::endl << std::endl;
std::cout << m << "frag shader: " << std::endl;
fShaderF.read(fShaderData, 2000);
for (int i = 0; i < 2000; i++) {
std::cout << fShaderData[i];
}
std::cout << std::endl;
vShaderF.close();
fShaderF.close();
}
This worked great. my shader file was not actually not 2000 in length, but the read() call seemed to store the extra characters as whitespace into the char array which is what I wanted.
Now having restructured my code a little bit in a newer program, my reader now looks like this:
std::ifstream shaderFile;
shaderFile.open(path);
if (shaderFile.is_open()) cout << "Shader at: " << path << ", initalized" << endl;
char data[2000];
shaderFile.read(data, 2000);
for (int i = 0; i < 2000; i++) std::cout << data[i];
The actual text portion still reads correct. However, now the extra space in the char array is stored with this instead of whitespace:
In case the image won't show, it is basically just a reapeating pattern of these two characters [|[|[|....
Why is this happening and how can I fix it?
NOTE: I'm using the same shader file, same computer, same IDE, same everything. The old one still works.
When using std::istream:read() it will not set the parts of the buffer to spaces which were not read. The memory will be left untouched. If you want to get spaces into an unread area of the buffer, you'll need to put the spaces there yourself. If the program indeed had spaces in the buffer it was because the buffer somehow already contained spaces by chance.
You can use std::istream::gcount() to determine how many characters were read.
If you want the arrays to contain predefined data, you'll have to initialize it with such predefined data. If the stream reads fewer data than the array size, you will have the padding you want.

c++ string concatenation second time

I am a newbie, writing a c++ code to open and read from multiple files and then dump part of the data into other files.
I want to generate file names in a for loop.
But I can't concatenate string(numbering of file) and string literal(a file extension). The same line of code works at the very beginning of the program, but not at the later part.
int main(int argc, char *argv[])
{
std::cout << std::string("9") + ".dat" << std::endl;
// many more lines
dump = 1;
if (dump == 1){
for (int ilevel=std::max(levelmin,lmin); ilevel < lmax + 1; ilevel++){
std::cout << std::string("9") + ".dat" << std::endl; // crashes here!
std::ofstream fout (std::string("9") + ".dat", std::ios::out | std::ios::binary);
std::cout << grid[ilevel].cube[0] << std::endl;
fout.write ((char*)&grid[ilevel].cube[0], grid[ilevel].cube.size() * sizeof(grid[ilevel].cube[0]));
fout.close();
}
}
...
}
If I put std::cout << std::string("9") + ".dat" << std::endl; at the beginning, it works and prints "9.dat".
but in the later loop, segmentation fault.
In between I call a function that uses stringstream to pad leading zeros to an integer. The function looks:
std::string int2str(const int n, const int m){
std::stringstream ss;
ss << std::setfill('0') << std::setw(m) << n;
std::string s2(ss.str());
ss.clear();
return s2;
}
I don't have a clear understanding about string and stringstream in c++.
But out of many things in my program, this function is the only thing I can think of being relevant. Other parts of codes does not deal with strings. It's mostly array manipulation code.
I've also tried std::string("9") + std::string(".dat")
but had no luck.
What is wrong?
Is there a specific reason why you're using std::string("9") rather than just "9"?
Where does the 9 come from? If its generated as part of a loop or a returned value from a function you can either place the variable itself to be concatenated, or the function that returns it, so:
std::cout << iFileNumber + ".dat" << std::endl;
or
std::cout << fileNumberGenerator() + ".dat" << std::endl;
For the hardcoded examples you've provided, I personally can't see the need for anything other than
std::cout << 9 + ".dat" << endl;
but that could easily just be lack of experience on my part.
For the sake of printing to the command line, its also worth nothing that this is equally acceptable syntax (assuming you're not already aware):
std::cout << 9 << ".dat" << endl;

how to keep track of the current position in std::stringstream

I am writing a custom logger where I buffer my log messages in a std::stringstream and flush it to a file (std::ofstream) whenever the std::stringstream is big enough(to save some IO latency) . sincestd::stringstream doesn't have a .size() method, I use seekg and tellg :
template <typename T>
MyClass & operator<< (const T& val)
{
boost::unique_lock<boost::mutex> lock(mutexOutput);
output << val; //std::stringstream output;
output.seekg(0, std::ios::end);
if(output.tellg() > 1048576/*1MB*/){
flushLog();
}
return *this;
}
Problem:
It seems to me that, whenever I invoke this method, it uses seekg to start counting the bytes from the beginning all the way to the end and get the size using tellg. I came up with this design to save some IO time in the first place, but: isn't this continuous counting impose a larger cost(if the number of calls to this method is high and log messages are small as in most of the cases)?
is there a better way to do this?
And a side question: is 1MB a good number for buffer size in a normal nowadays computers?
Thank you
You can just use ostringstream::tellp() to get the length of the string. Here's an example lifted from http://en.cppreference.com/w/cpp/io/basic_ostream/tellp.
#include <iostream>
#include <sstream>
int main()
{
std::ostringstream s;
std::cout << s.tellp() << '\n';
s << 'h';
std::cout << s.tellp() << '\n';
s << "ello, world ";
std::cout << s.tellp() << '\n';
s << 3.14 << '\n';
std::cout << s.tellp() << '\n' << s.str();
}
Output:
0
1
13
18
hello, world 3.14

cout no output but printf does

I'm very new to programming in C++ but I'm trying to write some code which filters a specific word from a string and then takes a specific action. For some reason the code does not see the text inside the string.
printf("%s \n", data.c_str());
cout << data;
This shows absolutely nothing - meaning I cannot use .find or write it to a file.
printf("%s \n", data);
This shows exactly what I need.
I am writing the code into data with assembly:
mov data, EDX
Why is that I can only use the the last method?
Edit:
Data is initiated as:
std::string data;
If a pointer to a string is null all subsequent calls to cout
stop working
const char* s=0;
cout << "shown on cout\n";
cout << "not shown" << s << "not shown either\n";
cout << "by bye cout, not shown\n";
The two function calls are not equivalent, as \n at printf flushes the stream. Try with:
cout << data << endl;
Be sure you used
#include <string>
in your file header. With this in place you should be able to use
std::cout << data << endl;
with no issues. If you're using a global namespace for std you may not need the std::, but I'd put it anyway to help you debug a it faster and eliminate that as a possible problem.
In Short
You will have a problem with cout, if you don't put a linebreak at it's end!
In Detail
Try adding an endl to your cout (e.g. std::cout << data << std::endl), or use following instruction to activate "immediate output" for cout (without it needing a linebreak first).
std::cout << std::unitbuf;
Complete example:
std::cout << std::unitbuf;
std::cout << data;
// ... a lot of code later ...
std::cout << "it still works";
Sidenote: this has to do with output buffering, as the name unitbuf suggests (if you want to look up what is really happening here).
This way it is also possible to rewrite the current line, which is a good example, where you would need this ;-)
Practical example
using namespace std;
cout << "I'm about to calculate some great stuff!" << endl;
cout << unitbuf;
for (int x=0; x<=100; x++)
{
cout << "\r" << x << " percent finished!";
// Calculate great stuff here
// ...
sleep(100); // or just pretend, and rest a little ;-)
}
cout << endl << "Finished calculating awesome stuff!" << endl;
Remarks:
\r (carriage return) puts the curser to the first position of the line (without linebreaking)
If you write shorter text in a previously written line, make sure you overwrite it with space chars at the end
Output somewhere in the process:
I'm about to calculate some great stuff!
45 percent finished!
.. and some time later:
I'm about to calculate some great stuff!
100 percent finished!
Finished calculating awesome stuff!