I want to output a whole formatted console line (80 characters) in C++.
It should look like this:
Some things on the left side some other on the right side
The data contains two iterator functions that return std::string and fixed texts. Something like this:
std::cout << (*some_iterator)->getID() << " some text:" << LOTSOFSPACES << (*some_other_iterator)->getName() << " some more text.";
Outcome should always be 80 characters.
I tried messing around with std::setw and std::setfill, std::left and std::right, using a stringstream and calculating the spaces I have to create. But nothing really works and most ideas just destroyed the output completely.
Any ideas? Unfortunately I am not allowed to use external libraries.
If you can tell for sure both parts are always less than 40 characters (or they can be split in two columns in any other way), you could do it like this:
std::string firstPart = (*some_iterator)->getID() + " some text:";
std::string secondPart = (*some_other_iterator)->getName() + " some more text.";
std::cout << std::setw(40) << std::left << firstPart
<< std::setw(40) << std::right << secondPart;
See it online
More versatile solution would be to simply calculate the spacing between strings and insert it manually. This doesn't require having columns of known length:
std::string firstPart = (*some_iterator)->getID() + " some text:";
std::string secondPart = (*some_other_iterator)->getName() + " some more text.";
std::size_t spacingSize = 80 - firstPart.length() - secondPart.length();
//Add some code to check if spacingSize is not negative!
std::cout << firstPart << std::string(spacingSize, ' ') << secondPart;
See it online
You can try to set the coursor at the position.
First you have to add library:
#include <windows.h>
Now you can use function:
COORD c;
c.X = x_coordinate;
c.Y = y_coordinate;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
What's the best way (if any) to format std::*stream output in localized manner, so that formatting changes in one location won't affect the use of that stream in other locations?
That is, I'd like to set format of the stream for a single statement, not for the remaining lifetime of the stream.
The following is just a rationale for asking the above question.
Suppose you print intensity in default floating point format:
ostringstream oss;
oss << "Intensity = " << intensity << "; ";
Then print coordinates with fixed 2 digits precision:
oss << "Point = (" << fixed << setprecision(2) << pt.x << ", " << pt.y << "); ";
then, 20 lines later, print ray direction in the same fixed 2 digits format:
oss << "Direction = (" << dir.x << ", " << dir.y << "); ";
A few months later add printing of luminosity in default floating point format somewhere between printing pt and printing dir:
oss << "Luminosity = " << lum << "; ";
Oops, lum will be printed in fixed 2 digits precision because you changed oss format 20 lines before, when printing pt. Now you have to recall what you've changed in oss and rewind it for printing lum.
Moreover, after fixing format for lum you'd get another problem: dir won't be printed in fixed 2 digits anymore...
Therefore I'd like to be able to format streams locally to avoid unnecessary dependencies.
You can simply save and restore stream format flags (see std::iosbase::flags()):
fmtflags oldflags = oss.flags();
// change current format flags
oss.flags(oldflags); // <<< restore to former state
If you don't like it straight forward as mentioned above, you could also use a proxy:
class local_ostream {
public:
friend template<typename T>
local_ostream& operator<<(local_ostream& los, const& T value) {
los.os_ << value;
return los;
}
local_ostream(std::ostream& os) : os_(os), oldflags_(os.flags()) {
}
~local_ostream() {
os_.flags(oldflags_);
}
private:
std::ostream& os_;
std::iosbase::fmtflags oldflags_;
};
And use as follows:
{ local_ostream los(oss);
los << "Point = (" << fixed << setprecision(2) << pt.x << ", " << pt.y << "); ";
} // previous formatting state is restored here
I generate a set of data files. As the files are supposed to be readable, they text files (opposed to binary files).
To output information to my files, I used very comfortable std::ofstream object.
In the beginning, when the data to be exported was smaller, the time needed to write to the files was not noticeable. However, as the information to be exported has accumulated, it takes now around 5 minutes to generate them.
As I started being bothered by waiting, my question is obvious: Is there any faster alternative to std::ofstream, please? In case there is faster alternative, will it be worth of rewritting my application? In other words, could the time saved be +50%? Thank you.
Update:
I was asked to show you my code that generates the above files, so here you are - the most time consuming loop:
ofstream fout;
fout.open(strngCollectiveSourceFileName,ios::out);
fout << "#include \"StdAfx.h\"" << endl;
fout << "#include \"Debug.h\"" << endl;
fout << "#include \"glm.hpp\"" << endl;
fout << "#include \"" << strngCollectiveHeaderFileName.substr( strngCollectiveHeaderFileName.rfind(TEXT("\\")) + 1) << "\"" << endl << endl;
fout << "using namespace glm;" << endl << endl << endl;
for (unsigned int nSprite = 0; nSprite < vpTilesetSprites.size(); nSprite++ )
{
for(unsigned int nFrameSet = 0; nFrameSet < vpTilesetSprites[nSprite]->vpFrameSets.size(); nFrameSet++)
{
// display index definition
fout << "// Index Definition: " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetLongDescription() << "\n";
string strngIndexSignature = strngIndexDefinitionSignature;
strngIndexSignature.replace(strngIndexSignature.find(TEXT("#aIndexArrayName#")), strlen(TEXT("#aIndexArrayName#")), TEXT("a") + vpTilesetSprites[nSprite]->GetObjectName() + vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetFrameSetName() + TEXT("IndexData") );
strngIndexSignature.replace(strngIndexSignature.find(TEXT("#ClassName#")), strlen(TEXT("#ClassName#")), strngCollectiveArrayClassName );
fout << strngIndexSignature << "[4] = {0, 1, 2, 3};\t\t" << "// " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetShortDescription() << ": Index Definition\n\n";
// display vertex definition
fout << "// Vertex Definition: " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetLongDescription() << "\n";
string strngVertexSignature = strngVertexDefinitionSignature;
strngVertexSignature.replace(strngVertexSignature.find(TEXT("#aVertexArrayName#")), strlen(TEXT("#aVertexArrayName#")), TEXT("a") + vpTilesetSprites[nSprite]->GetObjectName() + vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetFrameSetName() + TEXT("VertexData") );
strngVertexSignature.replace(strngVertexSignature.find(TEXT("#ClassName#")), strlen(TEXT("#ClassName#")), strngCollectiveArrayClassName );
fout << strngVertexSignature << "[" << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetFramesCount() << "] =\n";
fout << "{\n";
for (int nFrameNo = 0; nFrameNo < vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetFramesCount(); nFrameNo++)
{
fout << "\t" << "{{ vec4(" << fixed << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[0].vPosition.fx << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[0].vPosition.fy << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[0].vPosition.fz << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[0].vPosition.fw << "f), vec2(" << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[0].vTextureUV.fu << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[0].vTextureUV.fv << "f) }, // " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetShortDescription() << " vertex 1: vec4(x, y, z, w), vec2(u, v) \n";
fout << "\t" << " { vec4(" << fixed << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[1].vPosition.fx << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[1].vPosition.fy << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[1].vPosition.fz << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[1].vPosition.fw << "f), vec2(" << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[1].vTextureUV.fu << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[1].vTextureUV.fv << "f) }, // " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetShortDescription() << " vertex 2: vec4(x, y, z, w), vec2(u, v) \n";
fout << "\t" << " { vec4(" << fixed << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[2].vPosition.fx << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[2].vPosition.fy << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[2].vPosition.fz << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[2].vPosition.fw << "f), vec2(" << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[2].vTextureUV.fu << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[2].vTextureUV.fv << "f) }, // " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetShortDescription() << " vertex 3: vec4(x, y, z, w), vec2(u, v) \n";
fout << "\t" << " { vec4(" << fixed << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[3].vPosition.fx << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[3].vPosition.fy << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[3].vPosition.fz << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[3].vPosition.fw << "f), vec2(" << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[3].vTextureUV.fu << "f, " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->vpFrames[nFrameNo]->aVertices[3].vTextureUV.fv << "f) }}, // " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetShortDescription() << " vertex 4: vec4(x, y, z, w), vec2(u, v) \n\n";
}
fout << "};\n\n\n\n";
}
}
fout.close();
If you don't want to use C file I/O then you can give a try to; FastFormat. Look at the comparison for more info.
How are vpTilesetSprites and vpTilesetSprites[nSprite] stored? Are they implemented with lists or arrays? There is a lot of indexed access to them, and if they are list-like structures, you'll spend a lot of extra time following needless pointers. Ed S.'s comment is right: giving the long indexed temporary variables and linebreaks could make it easier to read, and maybe faster, too:
fout << "// Index Definition: " << vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetLongDescription() << "\n";
string strngIndexSignature = strngIndexDefinitionSignature;
strngIndexSignature.replace(strngIndexSignature.find(TEXT("#aIndexArrayName#")), strlen(TEXT("#aIndexArrayName#")), TEXT("a") + vpTilesetSprites[nSprite]->GetObjectName() + vpTilesetSprites[nSprite]->vpFrameSets[nFrameSet]->GetFrameSetName() + TEXT("IndexData") );
strngIndexSignature.replace(strngIndexSignature.find(TEXT("#ClassName#")), strlen(TEXT("#ClassName#")), strngCollectiveArrayClassName );
vs
string idxsig = strngIndexDefinitionSignature;
sprite sp = vpTilesetSprites[nSprite];
frameset fs = sp->vpFrameSets[nFrameSet];
fout << "// Index Definition: " << fs->GetLongDescription() << "\n";
idxsig.replace(idxsig.find(TEXT("#aIndexArrayName#")), strlen(TEXT("#aIndexArrayName#")),
TEXT("a") + sp->GetObjectName() + fs->getFrameSetName() + TEXT("IndexData"));
idxsig.replace(idxsig.find(TEXT("#ClassName#")), strlen(TEXT("#ClassName#")),
strngCollectiveArrayClassName);
But, the much bigger problem is how you're using strings as templates; you're looking for a given text string (and computing the length of your needle string every single time you need it!) over and over again.
Consider this: You're performing the find and replace operations nSprite * nFrameSet times. Each time through, this loop:
makes a copy of strngIndexDefinitionSignature
creates four temporary string objects when concatenating static and dynamic strings
compute strlen(TEXT("#ClassName#"))
compute strlen(TEXT("#aIndexArrayName#"))
find start point of both
replace both texts with new texts
And that's just the first four lines of your loop.
Can you replace your strngIndexDefinitionSignature with a format string? I assume it currently looks like this:
"flubber #aIndexArrayName# { blubber } #ClassName# blorp"
If you re-write it like this:
"flubber a %s%sIndexData { blubber } %s blorp"
Then your two find and replace lines can be replaced with:
sprintf(out, index_def_sig, sp->GetObjectName(), fs->getFrameSetName(),
strngCollectiveArrayClassName);
This would remove two find() operations, two replace() operations, creating and destroying four temporary string objects, a string duplicate that was promptly over-written with two replace() calls, and two strlen() operations that return the same result every time (but aren't actually needed anyway).
You can then output your string with << as usual. Or, you can change sprintf(3) to fprintf(3), and avoid even the temporary C string.
Assuming you do it in large enough chunks, calling write() directly might be faster; that said, it's more likely that your biggest bottleneck doesn't have anything directly to do with std::ofstream. The most obvious thing is to make sure you aren't using std::endl (because flushing the stream frequently will kill performance). Beyond that, I would suggest profiling your app to see where it's actually spending the time.
The performance of ostream is probably not your actual issue; I suggest using a profiler to determine where your real bottlenecks are. If ostream turns out to be your actual problem, you can drop down to <cstdio> and use fprintf(FILE*, const char*, ...) for formatted output to a file handle.
The best answer will depend on what sort of text you are generating, and how you are generating it. C++ streams can be slow, but that mostly is because they can also do a lot more for you, such as locale-dependent formatting, and so on.
You may find speed ups with streams by bypassing some of the formatting (eg. ostream::write), or by writing characters directly to a streambuf instead (streambuf::sputn). Sometimes increasing the buffer size on the relevant streambuf helps (via streambuf::pubsetbuf).
If this isn't good enough, you might want to try C-style stdio files, eg fopen, fprintf, etc. It takes a little while to get used to the way the text is formatted if you're not used to that method but the performance is usually pretty good.
For the absolute top performance you usually have to go to OS-specific routines. Sometimes the direct low-level file routines are significantly better than the C stdio, but sometimes not - for example, I've seen some people say WriteFile on Win32 is the fastest method on Windows, whereas some Google hits report it as being slower than stdio. Another approach might be a memory-mapped file, eg. mmap + msync - this essentially uses your system memory as the disk and writes the actual data to disk in large blocks, which is likely to be near optimal. However you run the risk of losing all the data if you incur a crash half way for some reason, which may or may not be a problem for you.
I am trying to print the value of a const but it is not working. I am making a return to C++ after years so I know casting is a possible solution but I can't get that working either.
The code is as follows:
//the number of blanks surrounding the greeting
const int pad = 0;
//the number of rows and columns to write
const int rows = pad * 2 + 3;
const string::size_type cols = greeting.size() + pad * 2 + 2;
cout << endl << "Rows : " + rows;
I am trying to print the value of 'rows' without success.
You want:
cout << endl << "Rows : " << rows;
Note this has nothing to do with const - C++ does not allow you to concatenate strings and numbers with the + operator. What you were actually doing was that mysterious thing called pointer arithmetic.
You're almost there:
cout << endl << "Rows : " << rows;
The error is because "Rows : " is a string literal, thus is a constant, and generally speaking is not modified as you may think.
Going slightly further, you likely used + (colloquially used as a concatenation operation) assuming you needed to build a string to give to the output stream. Instead operator << returns the output stream when it is done, allowing chaining.
// It is almost as if you did:
(((cout << endl) << "Rows : ") << rows)
I think you want:
std::cout << std::endl << "Rows : " << rows << std::endl;
I make this mistake all the time as I also work with java a lot.
As others have pointed out, you need
std::cout << std::endl << "Rows : " << rows << std::endl;
The reason (or one of the reasons) is that "Rows : " is a char* and the + operator for char*s doesn't concatenate strings, like the one for std::string and strings in languages like Java and Python.
Ok, I must preface this by stating that I know so so little about c++ and am hoping someone can just help me out...
I have the below code:
string GoogleMapControl::CreatePolyLine(RideItem *ride)
{
std::vector<RideFilePoint> intervalPoints;
ostringstream oss;
int cp;
int intervalTime = 30; // 30 seconds
int zone =ride->zoneRange();
if(zone >= 0)
{
cp = 300; // default cp to 300 watts
}
else
{
cp = ride->zones->getCP(zone);
}
foreach(RideFilePoint* rfp, ride->ride()->dataPoints())
{
intervalPoints.push_back(*rfp);
if((intervalPoints.back().secs - intervalPoints.front().secs) > intervalTime)
{
// find the avg power and color code it and create a polyline...
AvgPower avgPower = for_each(intervalPoints.begin(),
intervalPoints.end(),
AvgPower());
// find the color
QColor color = GetColor(cp,avgPower);
// create the polyline
CreateSubPolyLine(intervalPoints,oss,color);
intervalPoints.clear();
intervalPoints.push_back(*rfp);
}
}
return oss.str();
}
void GoogleMapControl::CreateSubPolyLine(const std::vector<RideFilePoint> &points,
std::ostringstream &oss,
QColor color)
{
oss.precision(6);
QString colorstr = color.name();
oss.setf(ios::fixed,ios::floatfield);
oss << "var polyline = new GPolyline([";
BOOST_FOREACH(RideFilePoint rfp, points)
{
if (ceil(rfp.lat) != 180 && ceil(rfp.lon) != 180)
{
oss << "new GLatLng(" << rfp.lat << "," << rfp.lon << ")," << endl;
}
}
oss << "],\"" << colorstr.toStdString() << "\",4);";
oss << "GEvent.addListener(polyline, 'mouseover', function() {" << endl
<< "var tooltip_text = 'Avg watts:" << avgPower <<" <br> Avg Speed: <br> Color: "<< colorstr.toStdString() <<"';" << endl
<< "var ss={'weight':8};" << endl
<< "this.setStrokeStyle(ss);" << endl
<< "this.overlay = new MapTooltip(this,tooltip_text);" << endl
<< "map.addOverlay(this.overlay);" << endl
<< "});" << endl
<< "GEvent.addListener(polyline, 'mouseout', function() {" << endl
<< "map.removeOverlay(this.overlay);" << endl
<< "var ss={'weight':5};" << endl
<< "this.setStrokeStyle(ss);" << endl
<< "});" << endl;
oss << "map.addOverlay (polyline);" << endl;
}
And I'm trying to get the avgPower from this part:
AvgPower avgPower = for_each(intervalPoints.begin(),
intervalPoints.end(),
AvgPower());
the first part to cary over to the second part:
<< "var tooltip_text = 'Avg watts:" << avgPower <<" <br> Avg Speed: <br> Color: "<< colorstr.toStdString() <<"';" << endl
But of course I haven't the slightest clue how to do it... anyone feeling generous today?
Thanks in advance
Well you didn't state the problem with the code other than it doesn't work. I'm suspicious of your use of AvgPower() in the for_each. Also, you have AvgPower as a class. why not a double or something? For this code I would have expected to see something like this:
PowerType addIntervals(const RideFilePoint &p1, const RideFilePoint &p2) {
//Add and return.
}
...
...
PowerType total = accumulate(i.begin(), i.end(), PowerType(0.0), &addIntervals);
avg = total/i.length();
read these docs carefully:
http://www.sgi.com/tech/stl/accumulate.html
It seems like you are asking how to access the local variable avgPower within a different function (sorry if I am misunderstanding). This is less about c++ specifically and more about functional or object oriented design. There are many different ways to do this, but here are the sane ones I can think of, in the order of my preference.
Create avgPower (and color), within CreateSubPolyLine. There doesn't really seem to be any reason they are in CreatePolyLine anyway. Implement a separate call if there are other consumers. The function signature would change to
void GoogleMapControl::CreateSubPolyLine(const std::vector &points,
std::ostringstream &oss)
Include it in the function's paramemters, e.g., change the signature to:
void GoogleMapControl::CreateSubPolyLine(const std::vector &points,
std::ostringstream &oss,
const QColor& color,
const AvgPower& avgPower)
Put it in a member variable of GoogleMapControl. It doesn't seem like this would be a bad design choice in my opinion.