本文介绍了如何理解 C++ std::setw 的不一致行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定以下代码:

/*格式化输出**目标:练习使用 cout 将输出格式化到控制台**在三列中打印变量:**整数、浮点数、双数*/#include #include 使用命名空间标准;int main(){int a = 45;浮动 b = 45.323;双 c = 45.5468;int aa = a + 9;浮动 bb = b + 9;双cc = c + 9;int aaa = aa + 9;浮动 bbb = bb + 9;双 ccc = cc + 9;//第一次尝试:>cout<<"\n\n\n" <<//第一次尝试:>"<<"\n";cout<<12345678901234567890123456789012345678901234567890"<

...我得到以下输出:

gcc 4.6.3 版//第一次尝试:>12345678901234567890123456789012345678901234567890整数浮动双打45 45.323 45.546854 54.323 54.546863 63.323 63.5468//第二次尝试:>12345678901234567890123456789012345678901234567890整数浮动双打4545.323 45.546854 54.323 54.54686363.323 63.5468//第三次尝试:>12345678901234567890123456789012345678901234567890整数浮动双打45 45.323 45.546854 54.323 54.546863 63.323 63.546812345678901234567890123456789012345678901234567890整数浮动双打45 45.323 45.546854 54.323 54.546863 63.323 63.5468

... 注意:我故意与代码不一致",因为"我试图理解 < 的行为.iomanip> &&std::setw() 代码.

如果您查看第一次尝试的输出,您会注意到标题行字符串"输出与数据行数字"输出的偏移......而它主要"完成了对齐的目的列中的东西,既不准确,也不一致.

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

<<

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

4545.323 45.5468...6363.323 63.5468

...如何使用/执行"...

<<

...影响setw()的未来"执行?

为了完整起见,我已经在第三次尝试中表明可以正确地 &使用 && 准确对齐数据列(左或右)std::setw() ...但为什么不一致?

(@WhozCraig 的 answer 帮助我找到了我的位置,但没有深入研究以帮助我理解: (a) 为什么它伪"有效

解决方案

这是你的问题:std::setw() 不充当缓冲区,它修改了下一个表达式的获取方式评价.

您需要了解范围"这些表达式中的每一个都有.具体来说,std::setfill(int)std::left/std::right 改变了默认行为,并且似乎持续到它们被另一个 setfill()std::left/std::right 覆盖.std::setw(int) 另一方面似乎只影响它之后传递的任何内容(这很奇怪,因为我觉得我也看到它的行为类似于 std::setfill 和之前的其他人)

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

 int a = 45;浮动 b = 45.323;双 c = 45.5468;int aa = a + 9;浮动 bb = b + 9;双cc = c + 9;int aaa = aa + 9;浮动 bbb = bb + 9;双 ccc = cc + 9;std::cout <<std::endl <<std::endl <<std::endl;std::cout <<std::left <<std::setfill('~');//第一次尝试:>std::cout <<"//第一次尝试:>><<std::endl;std::cout <<《12345678901234567890123456789012345678901234567890》<<std::endl;std::cout <<std::setw(10) <<整数"<<std::setw(10) <<浮动"<<std::setw(10) <<双打"<<std::endl;std::cout <<std::setw(10) <<<<std::setw(10) <<<<std::setw(10) <<c<<std::endl;std::cout <<std::setw(10) <<aa<<std::setw(10) <<bb<<std::setw(10) <<cc<

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

Given the following code:

/*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

... I get the following output:

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

... note: I was intentionally "inconsistent" with the code, "because" I'm trying to understand the behavior of the <iomanip> && std::setw() code.

If you look at the output from the 1st attempt, you'll notice that the header row "string" output is offset from the data rows "numerical" output... and while it's "mostly" accomplishing the purpose of aligning things in columns, it's both not accurate and not consistent.

In the 2nd attempt, you'll see that I've discovered that if I prepend my row output with:

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

... then I get the row to look correctly (as seen in the header & 2nd data row) ... but now you'll notice that the 1st & 3rd data rows are very wrong:

4545.323         45.5468
...
6363.323         63.5468

... how does "using/executing" ...

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

... affect "future" executions of setw()?

For completeness' sake, I've shown in the 3rd Attempt that it's possible to correctly & accurately align columns of data (either left or right) using <iomanip> && std::setw() ... but why the inconsistencies?

(@WhozCraig's answer helped me get to where I am, but did not delve deep enough to help me understand either: (a) why it 'pseudo' works || (b) why after you make it work correctly the 'first' time, it then breaks the 'pseudo' functionality.)

解决方案

Here's your issue: std::setw() doesn't act as a buffer, it modifies the way the next expression gets evaluated.

You need to understand the "range" that each of these expressions has. Specifically, std::setfill(int) and std::left/std::right change the default behaviour, and seem last until they are overwritten by another setfill() or std::left/std::right. std::setw(int) on the other hand seems to only affect whatever is passed right after it (which is weird, because I feel like I've also seen it behave like std::setfill and the others before)

So, to sum up, what you want is something more akin to this:

    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;

(You'll notice I also changed "\n" to std::endl which additionally flushes the buffer after each line.)

这篇关于如何理解 C++ std::setw 的不一致行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-13 15:14