cout center alignment

I was wondering if there is an easy way to center your cout? Like dumb it down for me please lol.
Print the appropriate number of spaces first.
Do you always assume that the 'console' is always 80 characters wide?

Because measuring the actual width of a real console is an implementation specific detail that is not part of the standard.

How would you measure the 'width' when output is redirected to say a pipe or a file?
It depends on what you mean by "easy".

Nothing "automatic".

As @salem c points out, you have to figure out the width of the output.

For a console window it could depend on what the user does, and what operating system you're using. That is quite a winding road, too much to post here.

If you're writing output to a file then you're probably in charge of deciding what the width is.

That said, let's say you can determine the width of the output, whatever that is.

This is a description of the "how", though the details are up to you:

1
2
3
4
5
6
7
8
int width = 80; // a typical assumption from history, not always correct for modern systems.

std::string = "Some String";

int half_string_length = string.length() / 2;
int half_output_width = width / 2;

int leading_spaces = half_output_width - half_string_length;


At that point your task is to cout a string of spaces "leading_spaces" long, then your string, which could be one of the cout formatting methods, or just a string made of spaces.

This assumes, without checking, that "leading_spaces" is not negative.

There are simpler "formulae" related to the "midpoint" formula from algebra. This is a pedantic way to think of it.

Last edited on
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
#include <iostream>
#include <string>
using namespace std;

enum Position{ LEFT, CENTRE, RIGHT };            // "CENTRE" because I'm British!

void print( Position pos, string s, int linelength )
{
   int spaces = 0;
   switch( pos )
   {
      case CENTRE: spaces = ( linelength - s.size() ) / 2; break;
      case RIGHT : spaces =   linelength - s.size()      ; break;
   }
   if ( spaces > 0 ) cout << string( spaces, ' ' );
   cout << s << '\n';
}


int main()
{
   const int LINELENGTH = 40;
   string header( LINELENGTH, '=' );

   cout << header << '\n';
   print( LEFT  , "Left"  , LINELENGTH );
   print( RIGHT , "Right" , LINELENGTH );
   print( CENTRE, "Centre", LINELENGTH );
   cout << header << '\n';
}


========================================
Left
                                   Right
                 Centre
========================================
Ah, see those are all good. I was just doing the \t until I thought it was centered enough. Kinda silly lol. Seems more legit to use a code instead of \t. Thanks every I need to keep that in the memory bank. @lastchance, I enjoy British people. Their accents and fun to be around. Your military guys love to drink lol.
An output stream manipulator to center an item in a field:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>

namespace utility
{
    // output stream manipulator to centre an item in a field.
    // uses the field width and fill character specified by the stream.
    // for the most part, obeys the format flags specified by the stream
    template < typename T > struct centre
    {
        explicit centre( const T& v ) : what(v) {}
        const T& what ;

        template < typename C, typename CT >
        friend std::basic_ostream<C,CT>& operator << ( std::basic_ostream<C,CT>& stm, centre c )
        {
            const auto width = stm.width() ;
            if( width < 2 ) return stm << c.what ;

            std::basic_ostringstream<C,CT> str_stm ;
            str_stm.flags( stm.flags() ) ;
            // TO DO: handle internal justification
            str_stm << std::left << c.what ;
            const auto string_rep = str_stm.str() ;

            if( string_rep.size() >= width ) return stm << string_rep ;

            const auto left = ( width - string_rep.size() ) / 2 ;
            const auto right = width - string_rep.size() - left ;
            const auto fill = stm.fill() ;

            str_stm.str({}) ;
            for( int i = 0 ; i < left ; ++i ) str_stm << fill ;
            str_stm << string_rep ;
            for( int i = 0 ; i < right ; ++i ) str_stm << fill ;

            stm.width(0) ;
            return stm << str_stm.str() ;
        }

        // TO DO: allow chaining std::put_money etc.
    };
}

int main()
{
    std::cout << '|' << std::setw(10) << std::setfill('*') << utility::centre(1234) << '|' ;

    std::wcout << std::setw(10) << std::setfill(L'=') << utility::centre(" XYZ ") << L"|\n" ;

    std::cout << '|' << std::showpos << std::fixed << std::setprecision(7)
              << std::setw(20) << std::setfill('!') << utility::centre(1234.56) << '|'

              << std::showbase << std::hex << std::uppercase
              << std::setw(9) << std::setfill('^') << utility::centre(255) << "|\n" ;
}

http://coliru.stacked-crooked.com/a/3063cdc2a1498343
On Windows and any sane *nix system, you can use the code from my Gosper Glider Gun (http://www.cplusplus.com/forum/lounge/75168/) to get the console window size.

(The code is buried in the Initialize() functions.)

On *nix, if you only want the console size, you do not need to link with ncurses. If you use any of the other ncurses output functions, however, then you do need to link with ncurses.

Hope this helps.
Topic archived. No new replies allowed.