有效使用C++ iomanip库

Esc*_*alo 7 c++ iostream stream iomanip

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

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;
} 
Run Code Online (Sandbox Code Playgroud)

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

 1.123456123456e+01
-1.123456123456e+01
Run Code Online (Sandbox Code Playgroud)

代替

1.123456123456e+01
-1.123456123456e+01
Run Code Online (Sandbox Code Playgroud)

代码似乎非常重复.你怎么能"存储"的格式(所有的setiosflags,setwsetprecision语句),这样你就会这样说:"这个给定的格式打印以标准方式中的字符,但数字".

谢谢!

编辑

根据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;
}
Run Code Online (Sandbox Code Playgroud)

Rob*_*obᵩ 10

只是std::setw()暂时的.另外两个电话,setiosflags并且setprecision具有永久效果.

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

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;
} 
Run Code Online (Sandbox Code Playgroud)

但是现在你已经为下一个人提供了标志和精确度.试试这个:

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;
} 
Run Code Online (Sandbox Code Playgroud)

最后,如果你必须摆脱常量的重复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;
} 
Run Code Online (Sandbox Code Playgroud)

另见这个问题,他们决定你不能使宽度永久.