• 使用cout进行格式化


    以下内容摘自木缥缈的博客


    使用cout进行格式化

      ostream插入运算符将值转换为文本格式。在默认情况下,格式化值的方式如下。

        *  对于char值,如果它代表的是可打印字符,则将被作为一个字符显示在宽度为一个字符的字段中。

        *  对于数值整型,将以十进制方式显示在一个刚好容纳该数字及负号(如果有的话)的字段中;

        *  字符串被显示在宽度等于该字符串长度的字段中。

      浮点数的默认行为有变化。下面详细说明了老式实现和新式实现之间的区别。

        *新式:浮点类型被显示为6位,末尾的0不显示(注意,显示的数字位数与数字被存储时精度设置没有任何关系)。数字以定点表示法显示还是科学计数法表示,取决于它的值。具体来说,当指数大于等于6或小于等于-5时,将使用科学计数法表示。另外,字段宽度恰好容纳数字和负号(如果有的话)。默认的行为对应于带%g说明符的标准C库函数fprintf()。

        *老式:浮点类型显示为带6位小数,末尾的0不显示(注意,显示的数字位数与数字被存储时的精度没有任何关系)。数字以定点表示法显示还是以科学计数法表示,取决于他的值。另外,字段宽度恰好容纳数字和负号(如果有的话)。

      因为每个值的显示宽度等于它的长度,因此必须显式地在值之间提供空格;否则,相邻的值将不会被分开。

      注意:并非所有的编译器都能生成符合当前C++标准格式的输出。另外,当前标准允许区域性变化。例如,欧洲实现可能遵循欧洲人的风格:使用逗号而不是句点来表示小数点。也就是说,2.54将被写成2,54 。区域库(头文件locale)提供了用特定的风格影响(imbuing)输入或输出流的机制,所以同一个编译器能够提供多个区域选项。本章使用美式格式。  

    (1)修改显示时使用的计数系统

      ostream类是从ios类派生来的,而后者是从ios_base派生来的。ios_base类存储了描述格式状态的信息。例如,一个类成员中某些位决定了使用的计数系统,而另一个成员则决定了字段宽度。通过使用控制符(manipulator),可以控制显示整数时使用的技术系统。通过使用ios_base的成员函数,可以控制字段宽度和小数位数。由于ios_base类是ostream的间接基类,因此可以将其方法用于ostream对象(或子代),如cout。

      注意:ios_base类中的成员和方法以前位于ios中。现在,ios_base是ios的基类。在新系统中,ios是包含char和wchar_t具体化的模板,而ios_base包含了非模板特性。

      要控制整数以十进制、十六进制还是八进制显示,可以使用dec、hex和oct控制符。例如,下面的函数调用将cout对象的计数系统格式状态设置为十六进制:

        hex(cout);

        完成上述设置后,程序将以十六进制形式打印整数值,直到将格式状态设置为其他选项为止。注意,控制符不是成员函数,因此不必通过对象来调用。

      虽然控制符实际上是函数,但它们通常的使用方式为:

        cout << hex;

        ostream类重载了<<运算符,这使得上述用法与函数调用hex(cout)等价。控制符位于名称空间std中。下面的代码演示了控制符的使用方法(注意,可以单独使用控制符,也可以将其作为一系列插入的部分):

    #include <iostream>
    
    int main()
    { using namespace std;
        cout << "输入一个数字:"; int n;
        cin >> n;
        std::string str(5,' ');
        cout << "n" << str << "n*n
    ";
        cout << n << str << n*n << "(decimal)
    "; //设置成十六进制系统
        cout << hex;
        cout << n << str;
        cout << n*n << " (hexadecimal)
    "; //设置为八进制系统
        cout << oct << n << str << n * n << " (octal)
    ";
    
        dec(cout);
        cout << n << str << n * n << " (decimal)
    "; return 0;
    }
    
    输出结果:
    输入一个数字:12 
    n     n*n 
    12     144 (decimal)
    c     90 (hexadecimal) 
    14     220 (octal) 
    12     144  (decimal)
    

    (2)调整字段宽度

      可以使用width成员函数将长度不同的数字放到宽度相同的字段中,该方法的原型为:

        int width();

        int width(int i);

      第一种格式返回字段宽度的当前设置;第二种格式将字段宽度设置为i个空格,并返回以前的字段宽度值。这使得能够保存以前的值,以便以后恢复宽度值时使用。

      width()方法之影响显示的下一个项目,然后字段宽度将恢复为默认值。由于width()是成员函数,因此必须使用对象来调用它。

      C++永远不会截短数据,因此如果试图在宽度为2的字段中打印一个7位值,C++将增宽字段,以容纳该数据。C/C++的原则是:显示所有的数据比保持列的整洁更重要;C++视内容重于形式。

     1 #include <iostream>
     2 
     3 int main() 4 {
     5     using namespace std; 6     size_t w = cout.width(30);
     7     cout << "Default field width = " << w << ":
    ";
     8     cout.width(5);
     9     cout << "N" << ':'; 
    10     cout.width(8); 
    11     cout << "N * N" << ":
    "; 
    12     
    13     for (long i = 1; i <= 100; i *= 10) { 
    14         cout.width(5); 
    15         cout << i << ':'; 
    16         cout.width(8);
    17         cout << i * i << ":
    "; 
    18 } 
    19     return 0; 
    20 }
    21 
    22 输出结果: 
    23         Default field width = 0: 
    24     N:   N * N:
    25     1:       1: 
    26    10:     100: 
    27   100:   10000:
    

      在上面的输出中,值在字段中右对齐。输出中包含空格,也就是说,cout通过加入空格来填满整个字段。右对齐时,空格被插入到值的左侧。用来填充的字符叫做填充字符(fill character)。右对齐是默认的。

    (3)填充字符

      在默认情况下,cout使用空格填充字段中未被使用的部分,可以使用fill()成员函数来改变填充字符。例如,下面的函数调用将填充字符改为星号:
        cout.fill('*');

      这对于检查打印结果,防止接收方添加数字很有用。

    #include <iostream>
    
    int main()
    {
        using namespace std;
        cout.fill('*');
        const char * staff[2] = {"iPhone6s", "iPad2"};
        long bonus[2] = {900,1350};
        for (int i = 0; i < 2; i ++) {
            cout.width(10);
            cout << staff[i] << ": $";
            cout.width(7);
            cout << bonus[i] << "
    ";
        }
        return 0;
    }
    
    输出结果:
    **iPhone6s: $****900
    *****iPad2: $***1350
    

    (4)设置浮点数的显示精度

      浮点数精度的含义取决于输出模式。在默认情况下,它指的是显示的总位数。在定点模式和科学模式下,精度指的是小数点后面的位数。已经知道,C++的默认精度为6位(但末尾的0将不显示)。precision成员函数使得能够选择其他值。例如,下面的函数调用将cout的精度设置为2:

        cout.precision(2);

      和width()的情况不同,但与fill()相似,新的精度设置将一直有效,直到被重新设置。下面的程序说明了这一点:

    #include <iostream>
    
    int main()
    {
        using namespace std;
        float price1 = 25.5;
        float price2 = 1.9 + 8.0/9.0;
        cout.width(10);
        cout << ""Apple"" << ": $" << price1 << "
    ";
        cout.width(10);
        cout << ""Flower"" << ": $" << price2 << "
    ";
        
        cout.precision(2);
        cout.width(10);
        cout << ""Apple"" << ": $" << price1 << "
    ";
        cout.width(10);
        cout << ""Flower"" << ": $" << price2 << "
    ";
        
        return 0;
    }
    
    输出结果:
       "Apple": $25.5
      "Flower": $2.78889
       "Apple": $26
      "Flower": $2.8
    

    注意,第3行没有打印小数点及其后面的内容。另外,第4行显示的总位数为2位。

    (5)打印末尾的0和小数点

      对于有些输出,希望保留末尾的0,iostream系列类没有提供专门用于完成这项任务的函数,但ios_base类提供了一个setf()函数(用于set标记),能够控制多种格式化特性。这个类还定义了多个常量,可以作为函数的参数。例如,下面的函数调用使cout显示末尾的小数点:

        cout.setf(ios_base::showpoint);

      使用默认的浮点格式时,上述语句还将导致末尾的0被显示出来。

      showpoint是ios_base类声明中定义的类级静态常量。类级意味着如果在成员函数定义的外面使用它,则必须在常量名前加上作用域运算符(::)。因此,ios_base::showpoint指的是在ios_base类中定义的一个常量。

    #include <iostream>
    
    int main()
    {
        using namespace std;
        float price1 = 25.5;
        float price2 = 1.9 + 8.0/9.0;
        cout.setf(ios_base::showpoint);
        cout.width(10);
        cout << ""Apple"" << ": $" << price1 << "
    ";
        cout.width(10);
        cout << ""Flower"" << ": $" << price2 << "
    ";
        
        cout.precision(2);
        
        cout.width(10);
        cout << ""Apple"" << ": $" << price1 << "
    ";
        cout.width(10);
        cout << ""Flower"" << ": $" << price2 << "
    ";
        
        return 0;
    }
    
    输出结果:
       "Apple": $25.5000
      "Flower": $2.78889
       "Apple": $26.
      "Flower": $2.8
    
  • 相关阅读:
    03 JVM 从入门到实战 | 简述垃圾回收算法
    02 JVM 从入门到实战 | 什么样的对象需要被 GC
    01 JVM 从入门到实战 | 什么是 JVM
    从一道面试题探究 Integer 的实现
    程序员如何写一份更好的简历
    自己动手实现分布式任务调度框架(续)
    一个excel(20M)就能干趴你的poi,你信吗?
    一个普通类就能干趴你的springboot,你信吗?
    自己动手实现springboot配置(非)中心
    自己动手实现分布式任务调度框架
  • 原文地址:https://www.cnblogs.com/elis/p/8460295.html
Copyright © 2020-2023  润新知