how print in same column?

how can i print 3 or more values, in same column using cout?
heres my actual code:
1
2
3
4
5
cout <<"\n" << "show tokens\n";
        for(unsigned int i=0;i<Tokens.size(); i++)
        {
            cout << "Token: " << Tokens[i].Token <<right<<setw(20-Tokens[i].Token.size())<< "Type: " << Tokens[i].Type <<setw(40) << fixed << "Position Line: " << i<<"\n";
        }

heres the print:
https://imgur.com/46vvCA0

the "Type" is in same column, because i know the string size. but the "Position Line: " isn't in same column, because, in these case, i don't know the type size(Tokens[i].Type).
so how can show the "Position Line: " in same line?
If you do cout << std::setfill('*'); before printing, you can get a more accurate picture of how it's trying to format the lines.

You'll see that it's trying to do something like:
show tokens
Token: var***********Type: KeyWord*************************Position Line: 0
Token: const*********Type: KeyWord*************************Position Line: 1
Token: varname*******Type: ID*************************Position Line: 2


One possible fix is to change your setw(40) to setw(40-Tokens[i].Type.size()), however this feels ugly and I'm not sure if it's the best solution.
Last edited on
No, use setw() to control the width of the current column, not the previous.

Use std::left and std::right to control how things align in the column. You will almost always want to justify left.

When I get home tonight I'll post an example for you.
I think i made my solution better:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// Example program
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>

using std::cout;
using std::right;
using std::left;
using std::setw;
using std::fixed;

struct Token {
    std::string Token;
    std::string Type;
};

int main()
{
    std::vector<Token> Tokens = {
        { "var", "KeyWord" },
        { "const", "KeyWord" },
        { "varname", "ID" },
        // ...
    };
    cout <<"\n" << "show tokens\n";
    
    //cout << std::setfill('*');

    for(unsigned int i=0;i<Tokens.size(); i++)
    {
        std::string token_column = "Token: " + Tokens[i].Token;
        std::string token_type_column = "Type: " + Tokens[i].Type;

        cout << setw(20) << left << token_column << setw(20) << token_type_column << "Position Line: " << i <<"\n";
    }
}

show tokens
Token: var          Type: KeyWord       Position Line: 0
Token: const        Type: KeyWord       Position Line: 1
Token: varname      Type: ID            Position Line: 2


But would of course like to see your solution, especially if it doesn't require the contents of a single column to be manually concatenated beforehand.
Last edited on
You have it exactly right.

There is no way to avoid building the content of a column, though, as setw() works on a single item. Where it is important a simple function/lambda or local ostringstream or string concatenation will do.
setw() works on a single item. Where it is important a simple function/lambda or local ostringstream or string concatenation will do.
Thanks for confirming that :)
Notice, however, that you are combining two columns into a single item...
Because, now that I am not staring at a tiny cell phone screen...

1
2
3
4
5
6
7
8
9
10
11
    for (auto n = 0UL; n < Tokens.size(); n++)
    {
        std::cout << left
            << "Token: "                                  // column 1
            << std::setw( 12 ) << Tokens[n].Token << " "  // column 2
            << "Type: "                                   // column 3
            << std::setw( 13 ) << Tokens[n].Type << " "   // column 4
            << "Position Line: "                          // column 5
            << n                                          // column 6
            << "\n";
    }

[edit]
Also, sometimes it is worth converting an item to string beforehand so that you can crop it to fit the column...

Hope this helps.

[small]
[edited for clarity]
Last edited on
Not what you were asking about......

Boost has a Format library that allows for formatting parameters. As printf can do.

https://www.boost.org/doc/libs/1_71_0/libs/format/

I've used it before, makes outputting columnar data easy.

std::cout is IMO too generalized to easily do formatted output without a lot of effort.

Last edited on
I disagree. You get the same limitations with printf() as you do with std::cout in terms of space formatting. (What printf() functions have going for them is making life much more succinct. And with modern C++ template magic, you can still get type genericity, which is nice.)
I also prefer printf & sprintf at times. Nothing I can't do without but its one of those places c++ makes things harder than it should be.
1
2
cout << left
            << "Token: " << setw( 12 ) << Tokens[i].Token

so the 'setw( 12 )' it's the empty space and what we wrote is inside of that space, right?
I edited my post above to increase clarity.

std::setw() applies to the next thing actually written to stream.

It tells how many character columns minimum to use, padding with the fill character if necessary.

std::left and std::right tell which side to pad (indirectly: std::left means pad on the right, because the output text sticks to the left.)

When designing any kind of organized output, such as columnar output, it is always useful to get a text editor and start counting things. Even better: use some graph paper so you can draw extra stuff around the columns to help keep track.
Duthomhas: C\C++ don't have GotoXY(), ANSI, for that... and is very useful.
(unless we use the API Console functions)
but, in these case, is what i really need.
thank you so much for all to all
It does not matter whether you have a TUI library — you still have to design your output: pull out the graph paper and colored pencils.
true... at least the Turbo C++ had the conio.h with textcolor(), gotoxy() and others ;)
Turbo C++ was designed to work on an entirely different system. It was natural for programming languages to come bundled with a TUI library, since GUI as we know it today didn’t exist.

I suppose I ought to put up my Simple Cross-Platform Console I/O library at some point...
It is shockingly easy to do all that stuff and more.

(Though, making clipboard access work on X takes a some 150 LOC + threads.)
Registered users can post here. Sign in or register to post.