How to achieve the following C++ output formatting

2019-07-26 08:10发布

问题:

I wish to print out double as the following rules :

1) No scietific notation
2) Maximum decimal point is 3
3) No trailing 0.

For example :

0.01        formated to  "0.01"
2.123411    formatted to "2.123"
2.11        formatted to "2.11"
2.1         formatted to "2.1"
0           formatted to "0"

By using .precision(3) and std::fixed, I can only achieve rule 1) and rule 2), but not rule 3)

0.01        formated to  "0.010"
2.123411    formatted to "2.123"
2.11        formatted to "2.110"
2.1         formatted to "2.100"
0           formatted to "0"

Code example is as bellow :

#include <iostream>

int main() {
    std::cout.precision(3);
    std::cout << std::fixed << 0.01 << std::endl;
    std::cout << std::fixed << 2.123411 << std::endl;
    std::cout << std::fixed << 2.11 << std::endl;
    std::cout << std::fixed << 2.1 << std::endl;
    std::cout << std::fixed << 0 << std::endl;
    getchar();
}

any idea?

回答1:

You cannot do this with the iostream library's built-in formatting.

Additionally, you don't need to apply fixed on every output because it is not reset.

You can write your own manipulator to do it:

struct MyFormatter {
  int precision;
  double value;
  MyFormatter(int precision, double value) : precision(precision), value(value) {}
  friend std::ostream& operator<<(std::ostream& s, MyFormatter const& v) {
    std::stringstream ss;
    ss << std::set_precision(v.precision) << std::fixed << v.value;
    std::string str;
    ss.str().swap(str);
    str.resize(str.find_last_not_of("0") + 1);
    if (str[str.length() - 1] == '.') str.resize(str.length() - 1);
    s << str;
    return s;
  }
};

struct MyFormat {
  int precision;
  MyFormat(int precision) : precision(precision) {}
  MyFormatter operator()(double value) const {
    return MyFormatter(precision, value);
  }
};

int main() {
  MyFormat f(3);
  std::cout << f(0) << ' ' << f(0.1) << ' ' << f(0.12345) << '\n';
  return 0;
}


回答2:

For #3, you'd need to write your own manipulator that strips off trailing zeros. There's no inbuilt manipulator that does this.