Center text in fixed-width field with stream manipulators in C++

若如初见. 提交于 2019-11-30 06:52:34

Here's a helper class that accomplish what you want:

#include <string>
#include <iostream>
#include <iomanip>

template<typename charT, typename traits = std::char_traits<charT> >
class center_helper {
    std::basic_string<charT, traits> str_;
public:
    center_helper(std::basic_string<charT, traits> str) : str_(str) {}
    template<typename a, typename b>
    friend std::basic_ostream<a, b>& operator<<(std::basic_ostream<a, b>& s, const center_helper<a, b>& c);
};

template<typename charT, typename traits = std::char_traits<charT> >
center_helper<charT, traits> centered(std::basic_string<charT, traits> str) {
    return center_helper<charT, traits>(str);
}

// redeclare for std::string directly so we can support anything that implicitly converts to std::string
center_helper<std::string::value_type, std::string::traits_type> centered(const std::string& str) {
    return center_helper<std::string::value_type, std::string::traits_type>(str);
}

template<typename charT, typename traits>
std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& s, const center_helper<charT, traits>& c) {
    std::streamsize w = s.width();
    if (w > c.str_.length()) {
        std::streamsize left = (w + c.str_.length()) / 2;
        s.width(left);
        s << c.str_;
        s.width(w - left);
        s << "";
    } else {
        s << c.str_;
    }
    return s;
}

It's used simply by calling centered("String"), like so:

int main(int argc, char *argv[]) {
    std::cout << "|" << std::setw(10) << centered("Table")
              << "|" << std::setw(10) << centered("Column")
              << "|" << std::setw(9)  << centered("Header") << "|"
              << std::endl;
}

There is no std::center manipulator. I am afraid you have to do it yourself. You could write a helper function to calculate the spaces given the width and the string, to reduce the efforts.

Here's a sample of what a helper function might look like. It needs some work to make it more efficient, etc.

string helper(int width, const string& str) {
    int len = str.length();
    if(width < len) { return str; }

    int diff = width - len;
    int pad1 = diff/2;
    int pad2 = diff - pad1;
    return string(pad1, ' ') + str + string(pad2, ' ');
}

I'm afraid you'll have to do it manually. But it's not that hard if you work with strings. Something like:

std::string
centered( std::string const& original, int targetSize )
{
    assert( targetSize >= 0 );
    int padding = targetSize - checked_cast<int>( original.size() );
    return padding > 0
        ? std::string( padding / 2, ' ' ) 
            + original
            + std::string( targetSize - (padding / 2), ' ' )
        : original;
}

should do the trick.

you could use the NCURSES library... it's kinda funk and you have to add "-L NCURSES" to your compile command (g++ -L NCURSES yourProgram.cpp) and it'll work plus you can do colors and other 'cool' stuff [cool for CLI anyway]. just read the manual, centering stuff is pretty easy. http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!