在 C++ 中使用流操纵器在固定宽度字段中居中文本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14861018/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Center text in fixed-width field with stream manipulators in C++
提问by Keith Pinson
I am refactoring some legacy code which is using printf
with longs strings (without any actual formatting) to print out plain text table headers which looks notionally like this:
我正在重构一些printf
与 longs 字符串(没有任何实际格式)一起使用的遗留代码,以打印出纯文本表头,理论上看起来像这样:
| Table | Column | Header |
which are currently being produced like this:
目前正在这样生产:
printf("| Table | Column | Header |");
I would like to produce the above with code to the effect of1:
我想用代码产生上面的效果1:
outputStream << "|" << std::setw(10) << std::center << "Table"
<< "|" << std::setw(10) << std::center << "Column"
<< "|" << std::setw(9) << std::center << "Header"
<< "|" << std::endl;
which does not compile because <iomanip>
has the stream manipulators std::left
, std::right
and std::internal
, but does not seem to have any std::center
. Is there a clean way to do this already in standard C++ libraries, or will I have to manually compute the necessary spacing?
它无法编译,因为<iomanip>
有流操纵器std::left
,std::right
并且std::internal
,但似乎没有任何std::center
. 在标准 C++ 库中是否有一种干净的方法可以做到这一点,还是我必须手动计算必要的间距?
1Even though this is more verbose than the C code, it will be less verbose in the long run because of the number of printf
statements and the amount of infixed duplication in their strings. It will also be more extensible and maintainable.
1尽管这比 C 代码更冗长,但从长远来看,由于printf
语句的数量和字符串中中缀重复的数量,它会不那么冗长。它也将更具可扩展性和可维护性。
采纳答案by Lily Ballard
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:
只需调用 即可使用它centered("String")
,如下所示:
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;
}
回答by Masked Man
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.
没有std::center
操纵器。恐怕你必须自己做。您可以编写一个辅助函数来计算给定宽度和字符串的空间,以减少工作量。
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, ' ');
}
回答by James Kanze
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.
应该做的伎俩。
回答by jEXEy
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/
你可以使用 NCURSES 库......它有点吓人,你必须在你的编译命令(g++ -L NCURSES yourProgram.cpp)中添加“-L NCURSES”,它会起作用,而且你可以做颜色和其他“酷”东西 [无论如何对 CLI 来说很酷]。只需阅读手册,居中的东西很容易。 http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/