我正在格式化一些日志输出。我希望最终结果看起来像这样:
Foo.................................12.1
Bar....................................4
Foo Bar............................42.01
总宽度是恒定的,但是两个参数(名称和值)都有不同的大小。一旦包含在std :: ostream中,有没有一种干净的方法来获取给定参数的宽度?
#include <iostream>
struct Entry {
std::string name_;
double value_;
};
constexpr int line_width = 30;
std::ostream& operator<<(std::ostream& log, const Entry& e)
{
log << e.name_
<< std::string(line_width - e.name_.size(), '.') \\ should subtract the width of e.value_
<< e.value_;
return log;
}
int main()
{
Entry foo = { "Foo", 12.1 };
Entry bar = { "Bar", 4};
Entry foobar = { "Foo Bar", 42.01};
std::cout << foo << '\n' << bar << '\n' << foobar << '\n';
}
上面的代码不起作用,因为我没有减去值的宽度。我正在考虑编写一个可以执行以下操作的函数:
template <typename T>
int get_width(std::ostream& log, T value)
{
// 1. use tellp to get initial stream size
// 2. insert the value in the stream
// 3. use tellp to get final stream size
// 4. remove the value from the stream (is that even possible?)
// 5. return the size = final - initial
}
有没有达到目标的干净方法?
您可以创建一个包含“名称”的字符串,以及一个包含“值”的字符串。
然后,很容易计算这两个字符串的总长度,并据此计算它们之间所需的空间。
如前所述,这个问题有点像X-Y问题,因为您不需要知道宽度即可获得所需的输出。为此,应该知道字段的总宽度并使用合适的填充字符就足够了。
这应该为您工作:
std::ostream& operator<<(std::ostream& log, const Entry& e)
{
auto beg = log.tellp();
log << e.name_;
auto len = log.tellp() - beg;
auto oldFill = log.fill();
auto oldWidth = log.width();
log.fill('.');
log.width(line_width - len);
log << e.value_;
log.fill(oldFill);
log.width(oldWidth);
return log;
}