【问题标题】:std::cout formatting in Cpp 98 standardCpp 98 标准中的 std::cout 格式
【发布时间】:2015-01-27 23:34:37
【问题描述】:

以下每一项都与独特的ostream 格式有关。如何将其恢复为默认值?

#include <iostream>
int main()
{
    std::cout << std::fixed;
    std::cout << std::setprecision(5) << f << '\n';
    std::cout << "scientific:\n" << std::scientific;
    /*Cpp 11 standard only*/
    std::cout << " hexfloat: " << std::hexfloat << 0.01 << '\n';
    "The number 0.01 in default: " << std::defaultfloat << 0.01; }
}

如:

std::set_default?;

还有我该怎么做

hexfloat and defaultfloat

在 Cpp 98 标准中?

setwidth 和 setprecision 之间的技术区别是什么?

【问题讨论】:

标签: c++ c++11 hex iostream fixed


【解决方案1】:

互斥选项std::fixed, std::scientific, std::hexfloat and std::defaultfloat的默认设置是std::defaultfloat

std::setprecision 的默认值为 6

std::setw 的确切效果必须分别为每个流插入器查找。

用 pre-C++11 替换 std::defaultfloat 很简单:

std::ios_base& defaultfloat(std::ios_base& str) {
    str.unsetf(std::ios_base::floatfield);
    return str;
}

编写std::hexfloat 同样容易,但流操作员不知道如何处理这些标志。
解决这个问题并非易事。

【讨论】:

  • 难道不是setf 而不是unsetf
  • 没有?我不想设置标志,我想取消设置。
【解决方案2】:

恢复原始格式的简单方法是保留流而不进行任何修改,只需使用copyfmt(),例如:

int main() {
    std::ostream restore(0);

    restore.copyfmt(std::cout);
    std::cout.precision(8);
    std::cout.copyfmt(restore);
}

这种方法将恢复所有不同的格式,包括使用pword()iword() 存储的值。如果您想将此功能打包为set_default 操纵器(您不能将其放入命名空间std,因为只有实现者才允许将名称放入其中),您可以使用如下内容:

template <typename cT, typename Traits>
std::basic_ostream<cT, Traits>& set_default(std::basic_ostream<cT, Traits>& out) {
    static std::basic_ostream<cT, Traits> dfault(0);
    out.copyfmt(dfault);
    return out;
}

它将像任何其他操纵器一样使用,例如:

std::cout << set_default;

您可以只使用一个流来恢复原始值。或者,您可以保持std::cout 的格式不变,而是使用相同的缓冲区但不同的格式创建一个单独的流,例如

std::ostream out(std::cout.rdbuf());
out.precision(8);
out << value;

此流将写入与std::cout 相同的流,但使用不同的格式标志。您甚至可以混合它们,因为流不直接存储任何字符:这是共享流缓冲区的工作:

std::cout << "value=";
out << value;
std::cout << '\n';

回答您关于 defaultfloat 等行为的问题:这些只是操纵器功能。如果你想在没有 C++11 的情况下使用它们,你可以定义一个相应的函数,例如:

template <typename cT, typename Traits>
std::basic_ostream<cT, Traits>& defaultfloat(std::basic_ostream<cT, Traits>& out) {
    out.unsetf(std::ios_base::floatfield);
    return out;
}

【讨论】:

  • 一件事:在第一个模板函数中将typemame改为typename
【解决方案3】:

如果返回默认值,我该如何返回

auto oldflags = std::cout.flags(); 
auto oldwidth = std::cout.width(); 
auto oldprecision = std::cout.precision();
auto oldloc = std::cout.getloc();
auto oldfill = std::cout.fill();
//**************************************************
std::cout << std::fixed;
std::cout << std::setprecision(5) << f << '\n';
std::cout << "scientific:\n" << std::scientific;
/*Cpp 11 standard only*/
std::cout << " hexfloat: " << std::hexfloat << 0.01 << '\n';
"The number 0.01 in default: " << std::defaultfloat << 0.01; 
//**********************************************************
std::cout.flags(oldflags); 
std::cout.width(oldwidth); 
std::cout.precision(oldprecision);
std::cout.imbue(oldloc);
std::cout.fill(oldfill);

有点头疼。

另外,如何在 Cpp 98 标准中执行 hexfloat 和 defaultfloat?

自己编写类似的函数。更让人头疼。

setwidth 和 setprecision 之间的技术区别是什么?

他们做的事情完全不同:

  • width - 字段宽度决定了在某些输出表示中要写入的最少字符数。如果表示的标准宽度小于字段宽度,则表示在由格式标志调整字段(左、右或内部之一)确定的点处用填充字符填充。
  • precision - 浮点精度决定了在插入操作中写入以表示浮点值的最大位数。如何解释这取决于 floatfield 格式标志是设置为特定表示法(固定或科学)还是未设置(使用默认表示法,不一定等同于固定或科学)。对于默认语言环境:
    • 使用默认的浮点表示法,精度字段指定有意义的数字的最大数量,以计算小数点前后的总数。请注意,它不是最小值,因此如果数字可以显示的位数少于精度,则它不会用尾随零填充显示的数字。
    • 在固定计数法和科学计数法中,精度字段指定精确显示小数点后的位数,即使这包括尾随小数点零。在这种情况下,小数点前的数字与精度无关。

【讨论】:

  • @Deduplicator:嗯,是的,但是流忽略了这些标志。您必须编写一个独立的函数来自己进行 float->hex 转换,这很重要,而且我不知道将它“挂钩”到这些标志。
  • 好吧,在这种情况下,至少std::defaultfloat 仍然可以工作。
猜你喜欢
  • 2017-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
  • 2011-08-05
相关资源
最近更新 更多