how print in same column?

Oct 9, 2019 at 8:44pm
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?
Oct 9, 2019 at 10:46pm
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 Oct 9, 2019 at 10:47pm
Oct 9, 2019 at 11:43pm
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.
Oct 9, 2019 at 11:53pm
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 Oct 9, 2019 at 11:57pm
Oct 10, 2019 at 2:34am
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.
Oct 10, 2019 at 2:44am
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 :)
Oct 10, 2019 at 4:32am
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 Oct 10, 2019 at 9:29pm
Oct 10, 2019 at 4:50am
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 Oct 10, 2019 at 4:51am
Oct 10, 2019 at 5:11am
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.)
Oct 10, 2019 at 2:38pm
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.
Oct 10, 2019 at 8:05pm
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?
Oct 10, 2019 at 9:34pm
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.
Oct 11, 2019 at 9:09pm
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
Oct 12, 2019 at 1:07am
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.
Oct 12, 2019 at 3:25pm
true... at least the Turbo C++ had the conio.h with textcolor(), gotoxy() and others ;)
Oct 12, 2019 at 4:51pm
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.)
Topic archived. No new replies allowed.