【问题标题】:Problems with cout in C++C++中的cout问题
【发布时间】:2020-08-19 10:40:51
【问题描述】:

首先,我想在下面向您展示我的代码。

#include<iostream>

int main()
{
    float num = 3;
    std::ios_base::fmtflags initial;
    initial = std::cout.setf(std::ios_base::fixed);
    std::cout.setf(initial);
    std::cout<<num;
}

输出为 3.000000。只有第一行和最后一行输出为 3。我的书说“setf() 方法返回所有在 打了电话。 std::ios_base::fmtflags 是存储它所需的类型的花哨名称 信息。所以对 initial 的赋值存储了之前的设置 调用了 setf 函数。然后可以将初始变量用作 setf() 的参数,以将所有格式设置重置为此原始值。”但正如您所见,它不起作用。有什么问题?

【问题讨论】:

  • 这并没有解决问题,而是养成使用有意义的值初始化对象的习惯,而不是使用默认值创建它们并立即覆盖默认值。在这种情况下,这意味着将std::ios_base::fmtflags initial; initial = std::cout.setfstd::ios_base::fixed); 更改为std::ios_base::fmtflags initial = std::cout.setfstd::ios_base::fixed);

标签: c++ c++11 ostream


【解决方案1】:

来自std::ios_base::setf

fmtflags setf( fmtflags flags ); (1)
fmtflags setf( fmtflags flags, fmtflags mask ); (2)
将格式化标志设置为指定的设置。

  1. 设置由标志标识的格式化标志。有效地执行了以下操作 fl = fl | flags 其中 fl 定义了内部格式化标志的状态。
  2. 清除掩码下的格式化标志,并将清除的标志设置为标志指定的标志。有效地执行了以下操作 fl = (fl & ~mask) | (flags & mask) 其中 fl 定义了内部格式化标志的状态。

(强调是我的。)

所以,std::ios::setf() 是设置单个标志的好选择,但一次设置所有标志是一个糟糕的选择。

为此,std::ios_base::flags 是正确的工具:

fmtflags flags() const; (1)
fmtflags flags( fmtflags flags ); (2)
管理格式标志。

  1. 返回当前格式设置

  2. 用给定的设置替换当前设置。

示例:

#include<iostream>

int main()
{
    float num = 3;
    std::cout<<num<<'\n';
    std::ios_base::fmtflags initial;
    initial = std::cout.setf(std::ios_base::fixed);
    std::cout.flags(initial); // <-- the fix
    std::cout<<num<<'\n';
}

输出:

3
3

Live Demo on coliru

【讨论】:

    【解决方案2】:

    某些格式标志是相互互斥的

    例如std::ios_base::left不能和std::ios_base::right一起使用。 std::ios_base::fixed 也是一个专有标志。它不能与std::ios_base::scientific 一起使用。要专门设置格式标志,std::ios_base::setf() 将附加位组标志作为其第二个参数。然后,您可以正确设置格式标志。 std::ios_base::fixed 是一组std::ios_base::floatfield,在调用 setf() 时应将其设置为第二个参数。

    #include <iostream>
    
    int main(void)
    {
        float num = 3;
    
        std::ios_base::fmtflags initial;
        initial = std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
        std::cout.setf(initial, std::ios_base::floatfield);
    
        std::cout << num;  // 3 printed on VS2019
    
        return 0;
    }
    

    【讨论】:

    • 参考了《Standard C++ IOStreams and Locales - 1.2.3 The Format Parameters of a Stream》一书来回答这个问题。
    【解决方案3】:

    setf 用于设置特定格式标志。因此,当您调用 std::cout.setf(initial); 时,它不会重置设置的 fixed 标志 您可能想改用flags 函数:

    #include <iostream>
    
    int main()
    {
        const double num = 3.0;
        std::cout << num << '\n';
        const auto initial_flags = std::cout.flags(std::ios_base::fixed);
        std::cout << num << '\n';
        std::cout.flags(initial_flags);
        std::cout << num << '\n';
    }
    

    输出:

    3
    3.000000
    3
    

    【讨论】:

      【解决方案4】:

      您也可以简单地使用 io manipulators。 (这也是更易读的代码):

      #include<iostream>
      
      int main()
      {
          float num = 3;
          
          std::cout<< std::fixed;
          
          std::cout << num<<'\n';
          std::cout<<num<<'\n';
          
          std::cout << std::scientific;
      
          std::cout << num<<'\n';
          std::cout<<num<<'\n';
          
          std::cout << std::defaultfloat;
      
          std::cout << num<<'\n';
          std::cout<<num<<'\n';
          
          
      

      }

      Live on coliru

      输出:

      3.000000
      3.000000
      3.000000e+00
      3.000000e+00
      3
      3
      

      【讨论】:

        猜你喜欢
        • 2019-08-11
        • 1970-01-01
        • 2011-01-26
        • 2013-06-27
        • 1970-01-01
        • 1970-01-01
        • 2011-02-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多