c++ - C++ iomanip 库的有效使用

标签 c++ stream iostream iomanip

我用 C++ 创建了一个 Vector 类,它非常适合我的问题。我现在正在清理它,我遇到了以下代码:

std::ostream& operator<<(std::ostream &output, const Vector &v){
  output<<"["
    <<std::setiosflags(std::ios::right | std::ios::scientific)
    <<std::setw(23)
    <<std::setprecision(16)
    <<v._x<<", "
    <<std::setiosflags(std::ios::right | std::ios::scientific)
    <<std::setw(23)
    <<std::setprecision(16)
    <<v._y<<", "
    <<std::setiosflags(std::ios::right | std::ios::scientific)
    <<std::setw(23)
    <<std::setprecision(16)
    <<v._z<<"]";
  return output;
} 

该代码允许将 vector 打印为 std::cout<<v<<std::endl; 。每个数字有 23 个空格,其中 16 个是小数。文本右对齐,以便打印:

 1.123456123456e+01
-1.123456123456e+01

代替

1.123456123456e+01
-1.123456123456e+01

代码看起来非常重复。您如何“存储”格式(所有 setiosflagssetwsetprecision 语句),这样您就可以说“以标准方式打印字符,但使用此给定格式打印数字”。

谢谢!

编辑

根据 Rob Adams 的评论,我将丑陋的代码(正如其他人所指出的那样,会弄乱“下一个人”的精度)更改为更简洁(和正确):

std::ostream& operator<<(std::ostream &output, const Vector &v){
  std::ios_base::fmtflags f = output.flags(std::ios::right | std::ios::scientific);
  std::streamsize p = output.precision(16);
  output<<"["
    <<std::setw(23)<<v._x<<", "
    <<std::setw(23)<<v._y<<", "
    <<std::setw(23)<<v._z
    <<"]";
  output.flags(f);
  output.precision(p);
  return output;
}

最佳答案

只有 std::setw() 是临时的。另外两个调用 setiosflagssetprecision 具有永久效果。

因此,您可以将代码更改为:

std::ostream& operator<<(std::ostream &output, const Vector &v){
  output<<"["
    <<std::setiosflags(std::ios::right | std::ios::scientific)
    <<std::setw(23)
    <<std::setprecision(16)
    <<v._x<<", "
    <<std::setw(23)
    <<v._y<<", "
    <<std::setw(23)
    <<v._z<<"]";
  return output;
} 

但是现在您已经为下一个人设置了标志和精度。试试这个:

std::ostream& operator<<(std::ostream &output, const Vector &v){
  std::ios_base::fmtflags f = output.flags(std::ios::right | std::ios::scientific);
  std::streamsize p = output.precision(16);
  output<<"["
    <<std::setw(23)
    <<v._x<<", "
    <<std::setw(23)
    <<v._y<<", "
    <<std::setw(23)
    <<v._z<<"]";
  output.flags(f);
  output.precision(p);
  return output;
} 

最后,如果您绝对必须摆脱常量 23 的重复,您可以这样做(但我不推荐这样做):

struct width {
  int w;
  width(int w) : w(w) {}
  friend std::ostream& operator<<(std::ostream&os, const width& w) {
    return os << std::setw(width.w);
  }
};


std::ostream& operator<<(std::ostream &output, const Vector &v){
  std::ios_base::fmtflags f = output.flags(std::ios::right | std::ios::scientific);
  std::streamsize p = output.precision(16);
  width w(23);
  output<<"["
    <<w
    <<v._x<<", "
    <<w
    <<v._y<<", "
    <<w
    <<v._z<<"]";
  output.flags(f);
  output.precision(p);
  return output;
} 

另见 this other question ,他们决定您不能使宽度永久化。

关于c++ - C++ iomanip 库的有效使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5328411/

相关文章:

c++ - 当 constexpr 函数出错时会发生什么?

stream - 如何检查 std::io::Cursor 是否有未使用的数据?

sql-server - Node +SQL Server : Get row data as stream

node.js - 流式传输 zip 文件,通过管道解压,通过管道输出?

sockets - Boost Asio tcp::iostream构造每秒钟使用都会引发访问冲突异常

c++ - 我如何将字符串中的每个字符更改为不同的颜色而不是整个字符串

c++ - decltype 返回的模板推导/替换错误

c# - 链表的应用 C++ vs C#

c++ - 程序返回值 -1073741571 而不是永远

c++ - 将提供 operator<< 的对象转换为 std::string 的标准库函数