如何理解C ++ std :: setw的不一致行为?

时间:2018-04-13 20:52:10

标签: c++ std iomanip setw

给出以下代码:

/*Formatting Output 
**Goal: practice using cout to format output to console
**Print the variables in three columns:
**Ints, Floats, Doubles
*/

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    int a = 45;
    float b = 45.323;
    double c = 45.5468;
    int aa = a + 9;
    float bb = b + 9;
    double cc = c + 9;
    int aaa = aa + 9;
    float bbb = bb + 9;
    double ccc = cc + 9;

    // 1st attempt :>

    cout << "\n\n\n" << "// 1st attempt :>" << "\n";
    cout << "12345678901234567890123456789012345678901234567890" << "\n";
    cout << "Ints" << setw(15) << "Floats" << setw(15) << "Doubles" << "\n";
    cout << a << setw(15) << b << setw(15) << c << "\n";
    cout << aa << setw(15) << bb << setw(15) << cc << "\n";
    cout << aaa << setw(15) << bbb << setw(15) << ccc << "\n";


    // 2nd attempt :>

    cout << "\n\n\n" << "// 2nd attempt :>" << "\n";
    cout << "12345678901234567890123456789012345678901234567890" << "\n";
    cout << std::left << std::setfill(' ') << std::setw(15)  << "Ints" << setw(15) << "Floats" << setw(15) << "Doubles" << "\n";
    cout << a << setw(15) << b << setw(15) << c << "\n";
    cout << std::left << std::setfill(' ') << setw(15) << aa << setw(15) << bb << setw(15) << cc << "\n";
    cout << aaa << setw(15) << bbb << setw(15) << ccc << "\n";

    // 3rd attempt :>

    cout << "\n\n\n" << "// 3rd attempt :>" << "\n";
    cout << "12345678901234567890123456789012345678901234567890" << "\n";
    cout << std::left << std::setfill(' ') << std::setw(15) << "Ints" << setw(15) << "Floats" << setw(15) << "Doubles" << "\n";
    cout << std::left << std::setfill(' ') << std::setw(15) << a << setw(15) << b << setw(15) << c << "\n";
    cout << std::left << std::setfill(' ') << std::setw(15) << aa << setw(15) << bb << setw(15) << cc << "\n";
    cout << std::left << std::setfill(' ') << std::setw(15) << aaa << setw(15) << bbb << setw(15) << ccc << "\n";
    cout << "12345678901234567890123456789012345678901234567890" << "\n";
    cout << std::right << std::setfill(' ') << std::setw(15) << "Ints" << setw(15) << "Floats" << setw(15) << "Doubles" << "\n";
    cout << std::right << std::setfill(' ') << std::setw(15) << a << setw(15) << b << setw(15) << c << "\n";
    cout << std::right << std::setfill(' ') << std::setw(15) << aa << setw(15) << bb << setw(15) << cc << "\n";
    cout << std::right << std::setfill(' ') << std::setw(15) << aaa << setw(15) << bbb << setw(15) << ccc << "\n";

    return 0;
}
// https://repl.it/@Tredekka/Cpp-Understanding-stdsetw

...我得到以下输出:

gcc version 4.6.3

// 1st attempt :>
12345678901234567890123456789012345678901234567890
Ints         Floats        Doubles
45         45.323        45.5468
54         54.323        54.5468
63         63.323        63.5468



// 2nd attempt :>
12345678901234567890123456789012345678901234567890
Ints           Floats         Doubles        
4545.323         45.5468        
54             54.323         54.5468        
6363.323         63.5468        



// 3rd attempt :>
12345678901234567890123456789012345678901234567890
Ints           Floats         Doubles        
45             45.323         45.5468        
54             54.323         54.5468        
63             63.323         63.5468        
12345678901234567890123456789012345678901234567890
           Ints         Floats        Doubles
             45         45.323        45.5468
             54         54.323        54.5468
             63         63.323        63.5468

... 注意 :我故意&#34;不一致&#34;使用代码,&#34;因为&#34;我试图理解<iomanip>&amp;&amp;的行为。 std::setw()代码。

如果您查看第一次尝试的输出,您会注意到标题行&#34; string&#34;输出偏离数据行&#34;数字&#34;输出......而它的主要是&#34;&#34;为了完成在列中对齐事物的目的,它既不准确也不一致。

在第二次尝试中,您会发现我已经发现如果我在行前面输出:

<< std::left << std::setfill(' ') << setw(15)

...然后我让行看起来正确(如标题和第二个数据行中所示)...但现在你会注意到第一个&amp;第三个数据行非常错误:

4545.323         45.5468        
...       
6363.323         63.5468      

...&#34;如何使用/执行&#34; ...

<< std::left << std::setfill(' ') << setw(15)

...影响&#34;未来&#34;执行setw()

为了完整性&#39;为了清楚起见,我在第3次尝试中表明它可能是正确的&amp; amp;使用<iomanip>&amp;&amp; amp;准确对齐数据列(左侧或右侧) std::setw() ...但为什么会出现不一致?

(@ WhozCraig&#39; s answer帮助我到达了我的位置,但没有深入研究以帮助我理解:(a)为什么它会伪造的? |(b)为什么在第一次使其正常工作之后,它会破坏“伪”功能。)

1 个答案:

答案 0 :(得分:0)

这是您的问题:std::setw() 不充当缓冲区,它会修改下一个表达式的求值方式。

您需要了解每个表达式的“范围”。具体来说,std::setfill(int)std::left/std::right 会更改默认行为,并且在它们被另一个 setfill()std::left/std::right 覆盖之前似乎一直存在.另一方面,std::setw(int) 似乎只影响它之后传递的任何内容(这很奇怪,因为我觉得我也看到它的行为像 std::setfill 和其他人之前)

所以,总而言之,您想要的是更类似于此的内容:

    int a = 45;
    float b = 45.323;
    double c = 45.5468;
    int aa = a + 9;
    float bb = b + 9;
    double cc = c + 9;
    int aaa = aa + 9;
    float bbb = bb + 9;
    double ccc = cc + 9;


    std::cout << std::endl << std::endl << std::endl;

    std::cout << std::left << std::setfill('~');

    // 1st attempt :>
    std::cout << "// 1st attempt :>" << std::endl;
    std::cout << "12345678901234567890123456789012345678901234567890" << std::endl;
    std::cout << std::setw(10) << "Ints" << std::setw(10) << "Floats" << std::setw(10) << "Doubles" << std::endl;
    std::cout << std::setw(10) << a   << std::setw(10) << b   << std::setw(10) << c   << std::endl;
    std::cout << std::setw(10) << aa  << std::setw(10) << bb  << std::setw(10) << cc  << std::endl;
    std::cout << std::setw(10) << aaa << std::setw(10) << bbb << std::setw(10) << ccc << std::endl;


    std::cout << std::endl << std::endl << std::endl << std::setfill('*');


    // 2nd attempt :>
    std::cout << "// 2nd attempt :>" << std::endl;
    std::cout << "12345678901234567890123456789012345678901234567890" << std::endl;
    std::cout << std::setw(10) << "Ints" << std::setw(10) << "Floats" << std::setw(10) << "Doubles" << std::endl;
    std::cout << std::setw(10) << a   << std::setw(10) << b   << std::setw(10) << c   << std::endl;
    std::cout << std::setw(10) << aa  << std::setw(10) << bb  << std::setw(10) << cc  << std::endl;
    std::cout << std::setw(10) << aaa << std::setw(10) << bbb << std::setw(10) << ccc << std::endl;


    std::cout << std::endl << std::endl << std::endl;


    // 3rd attempt :>
    std::cout << "// 3rd attempt :>" << std::endl;
    std::cout << "12345678901234567890123456789012345678901234567890" << std::endl;
    std::cout << std::setw(10) << "Ints" << std::setw(10) << "Floats" << std::setw(10) << "Doubles" << std::endl;
    std::cout << std::setw(10) << a   << std::setw(10) << b   << std::setw(10) << c   << std::endl;
    std::cout << std::setw(10) << aa  << std::setw(10) << bb  << std::setw(10) << cc  << std::endl;
    std::cout << std::setw(10) << aaa << std::setw(10) << bbb << std::setw(10) << ccc << std::endl;

    std::cout << "12345678901234567890123456789012345678901234567890" << std::endl;
    std::cout << std::right << std::setfill(' ');
    std::cout << std::setw(10) << "Ints" << std::setw(10) << "Floats" << std::setw(10) << "Doubles" << std::endl;
    std::cout << std::setw(10) << a   << std::setw(10) << b   << std::setw(10) << c   << std::endl;
    std::cout << std::setw(10) << aa  << std::setw(10) << bb  << std::setw(10) << cc  << std::endl;
    std::cout << std::setw(10) << aaa << std::setw(10) << bbb << std::setw(10) << ccc << std::endl;

    std::cout << std::endl << std::endl << std::endl;

(您会注意到我还将 "\n" 更改为 std::endl,这会在每行之后额外刷新缓冲区。)