Search code examples
c++text-alignment

How to align output?


How to align the output?

I tried this

  for(int x = 0; i<5; i++)
  cout<<a[x]<<setw(5)<<"|"<<setw(5)<<b[x]<<endl;

If all of a have same char length then the output like this

 frd     |     hehe
 asd   |     hoho
 .....
 .....

But if not have same length

 frd     |     hehe
 asdfg     |     hohoo

How to solve this?


Solution

  • In your suggested code:

        cout<<a[x]<<setw(5)<<"|"<<setw(5)<<b[x]<<endl;
    

    you have two problems that are leading to misalignment. (1) you have not provided any width for a[x] so it will be output without any adjustment; and (2) depending on the alignment you seek, the default justification when a width is specified for std::cout will be right justified.

    (additionally, as noted in my comment, in your first example, a[0] and a[1] cannot have the same length as the example suggests. There "frd " is stored with additional whitespace (or "asd\b" is stored with an embedded backspace) otherwise the output of "a[x]|" would be aligned.)

    To provide alignment for the output of both a and b, you must specify, at minimum, the width of a[x] with std::setw(n). Further, unless you want a[x] aligned to the right of the field created by std::setw(5), you must control the justification by setting std::ios_base::fmtflags with std::setiosflags(std::ios_base::left) (or simply std::left). See std::setiosflags.

    When you set a format flag for the stream, you are setting bits in a Bitmap type that will remain set after the current call to std::cout completes. So to tidy up after yourself and restore the flag state of the stream to default, you either (1) have to save the fmtflags for the stream with by capturing all flags with std::ios_base::fmtflags or (2) you must reset the individual flag you set with std::resetiosflags(...).

    So if I understand your question and your request for alignment (though it is unclear how you want b[x] aligned), you could align both a and b with left justification by:

        std::cout << "left justified output (both a & b)\n\n";
        for (size_t i = 0; i < a.size(); i++)
            std::cout << std::left  << std::setw(5) 
                    << a[i] << " | " << b[i] << '\n';
    

    or you could align a with left justification and then restore the default flag state letting b be output with default (right) justification, e.g.

        std::cout << "\nleft justified output for a, default for b\n\n";
        for (size_t i = 0; i < a.size(); i++)
            std::cout << std::left  << std::setw(5) 
                    << a[i] << " | " << std::resetiosflags(std::ios_base::left) 
                    << std::setw(5) << b[i] << '\n';
    

    Putting that altogether in an example, you could do:

    #include <iostream>
    #include <iomanip>
    #include <vector>
    #include <string>
    
    int main (void) {
    
        std::vector<std::string> a = { "frd", "asdfg", "asd", "quack" }, 
                                 b = { "hehe", "hohoo", "haloo", "hack" };
    
        std::cout << "left justified output (both a & b)\n\n";
        for (size_t i = 0; i < a.size(); i++)
            std::cout << std::left  << std::setw(5) 
                    << a[i] << " | " << b[i] << '\n';
    
        std::cout << "\nleft justified output for a, default for b\n\n";
        for (size_t i = 0; i < a.size(); i++)
            std::cout << std::left  << std::setw(5) 
                    << a[i] << " | " << std::resetiosflags(std::ios_base::left) 
                    << std::setw(5) << b[i] << '\n';
    }
    

    Example Use/Output

    $ ./bin/setwstring
    left justified output (both a & b)
    
    frd   | hehe
    asdfg | hohoo
    asd   | haloo
    quack | hack
    
    left justified output for a, default for b
    
    frd   |  hehe
    asdfg | hohoo
    asd   | haloo
    quack |  hack
    

    Note: if you want to make multiple changes to flags within the course of an output operation and then restore ALL format flags to their original state, you can use:

        std::ios_base::fmtflags f = std::cout.flags (); // save ios_base flags
        // do output, set flags as desired
        std::cout.flags (f);                            // restore saved flags
    

    Let me know if this addresses the alignment you were attempting to achieve.