在运算符中设置float字段<<输出功能,然后将其更改回来

时间:2014-05-29 00:33:47

标签: c++ operator-overloading ostream

假设我有一些商品,商品,名为价格的字段。当有人试图输出我的Merchandise对象时,最常见的是cout,我想显示该商品所售的美元金额,正好是两位小数。但我不想做的是永久改变流。例如,如果有人这样做:

double someNumber;  //someNumber should be displayed to 3 decimal places
Merchandise product;
/* something happens to product here */

cout << product << "And the number generated is " << someNumber << endl;

在这种情况下,产品应显示两个小数位,但someNumber仍应显示为3,就像客户期望的那样。所以当我实现我的函数时,我不想永久地更改ostream,我只想为这一个字段显示2个小数位,然后将其恢复正常。我该怎么做?

我尝试过更改一次ostream标志,然后将其更改为:

ostream& operator<< (ostream& os, const Merchandise& rhs) {
  int precision = os.precision();  //Get the current precision so we can change it back later
  /* I don't know how to get the current floatfield */
  os.setf(std::ios::fixed, std::ios::floatfield);  //Forces the same precision all the time
  os.precision(2);  //Forces a precision of 2

  os << rhs.price;

  os.precision(precision);
  /* I can't change the floatfield back, since I don't know how to get it or what kind of object to store it in */ 

  return os;
}

我一直在想着这个问题。我不知道这是否是做到这一点的最佳或标准方法。如果有更好的方法,有人可以让我知道吗?如果没有,那么如何将当前浮点数存储在一个变量中,以及我用它来存储哪种对象?感谢。

2 个答案:

答案 0 :(得分:1)

您可以使用iomanip库:

 os << std::fixed << std::setprecision(2) << std::showpoint << rhs.price;

这是一个简单的例子:

#include <iostream>
#include <iomanip>
using namespace std;

class a
{
   public:
   double b;
   friend ostream& operator<< (ostream& os, const a& rhs);
};

ostream& operator<< (ostream& os, const a& rhs)
{
    os << fixed << setprecision(2) << showpoint << rhs.b;
}

int main() {
     a n1;
     n1.b = 2.34567;
     cout << "Your num: " << n1 << std::endl;
     n1.b = 123.399999;
     cout << "Your num: " << n1 << std::endl;
     return 0;
 }

<强>输出

Your num: 2.35
Your num: 123.40

如果您使用的是c ++,那么这肯定会有用。

答案 1 :(得分:1)

设置新精度时,

precision()也会返回旧精度,因此您可以利用它并将精度与赋值一起设置为内嵌:

std::streamsize precision = os.precision(2);
对于窄字符流(使用std::streamsize的流),

intchar相同,但对于最佳做法,您应该使用此类型。

此外,要保存标志,您应该将流标记存储在std::ios_base::fmtflags类型的对象中:

std::ios_base::fmtflags flags = os.flags(os.flags() | std::ios_base::fixed);

然后在完成后再将其更改。


您可以通过使用RAII技术在完成后更改设置来实现此目的:

template <typename Stream>
class format_saver
{
public:
    format_saver(Stream& os)
        : os_(os)
        , flags(os.flags())
        , precision(os.precision())
    { }

    ~format_saver() { os_.flags(flags); os_.precision(precision); }
private:
    Stream& os_;
    std::ios_base::fmtflags flags;
    std::streamsize         precision;
};

现在你可以做到:

std::ostream& operator<<(std::ostream& os, const Merchandise& rhs)
{
    format_saver<std::ostream> _(os);
    return os << std::setprecision(2) << std::fixed << rhs.price;
}