开发者

Aligning output to the terminal using C++

开发者 https://www.devze.com 2023-04-05 20:13 出处:网络
I am having a lot of troubl开发者_高级运维e aligning my output to the terminal. I want to print a vector of vectors viz vector< vector<double>>myvec; to the output where myvec[i] occupies

I am having a lot of troubl开发者_高级运维e aligning my output to the terminal. I want to print a vector of vectors viz vector< vector<double> > myvec; to the output where myvec[i] occupies the ith row on the terminal. The vectors composing myvec have size 3

This is the way I am trying to print it.

for(unsigned int i=0; i<myvec.size() ; ++i   )
{


cout<<myvec[i][0]<<"     "
    <<myvec[i][1]<<"     "
    <<myvec[i][2]<<'\n';
}

When I print this to output only the myvec[i][0] column of numbers is aligned properly. The rest of the numbers look messy. Is there a good way to align this output? (Ignore the 0.7 printed to the right on line 5 of image)

Aligning output to the terminal using C++


You can use setw() to set the minimum number of characters you want to be written and left to output the data to the left. Like this:

cout << setw(8) << left << myvec[i][0];

This should fill the empty space with spaces but if not, then you can do:

cout << setw(8) << left << setfill(' ') << myvec[i][0];

You will need to #include <iomanip> for this.


Just a couple notes about your code:

Alignment types

quasiverse's answer gives you left justification, i.e. every number starts in the first character position. Drop the left to make it right-justify, i.e. every number starts in the last character position.

Aligning the decimal points is a bit harder. If you want to set a fixed number of digits past the decimal point, then replace the left with fixed and add setprecision(), giving it the number of digits you want past the decimal. For example, to show two digits past the decimal:

cout << setw(8) << fixed << setprecision(2) << myvec[i][0];

2-D Vectors

You're declaring vector< vector<double> > myvec;, but the minor (second) dimension appears hardcoded to 3. This means that you are creating a vector of vectors, where each row is an entire vector object with storage for three doubles.

vectors don't store their data internally; the actual vector object just stores the number of elements, a pointer to the actual data storage, and maybe a couple other things. The actual data is stored in a separate block. This will create a lot of overhead and memory fragmentation (every row allocates a block to store the data).

For example, for a 1000x3 vector, there is the top-level vector object on the stack, an array of 1000 vector objects (one per row) on the heap, and each of those points to a block of three doubles, so you have 1001 objects on the heap and every access has to go through two pointers. Slow and inefficient.

vector is overkill if the length is fixed. So I'd recommend having a vector of structures, with each structure having three doubles:

struct point {
    double x, y, z;
};
vector<point> myvec;

This stores all the data in one block, since point is completely self-contained. Then your code is:

for(unsigned int i = 0; i < myvec.size() ; ++i)
{
    cout << setw(8) << left << myvec[i].x << ' ' << setw(8) << left << myvec[i].y 
        << ' ' << setw(8) << left << myvec[i].z << endl;
}

Or, the C++ iterator way to do it:

for(vector<point>::const_iterator elem = myvec.begin(); elem != myvec.end() ; ++elem)
{
    cout << setw(8) << left << elem.x << ' ' << setw(8) << left << elem.y 
        << ' ' << setw(8) << left << elem.z << endl;
}

This saves a bunch of calls to operator[]. If your compiler supports the new C++11 standard, you can change the for() line to:

for(auto elem = myvec.begin(); elem != myvec.end() ; ++elem)

where auto tells the compiler to make elem the same type as what myvec.begin() returns. Another C++11 way, less likely to be supported, is the range-based for loop:

for(auto elem: myvec)
0

精彩评论

暂无评论...
验证码 换一张
取 消