gpt4 book ai didi

c++ - 哪些 iomanip 操纵器是 'sticky' ?

转载 作者:IT老高 更新时间:2023-10-28 11:33:12 24 4
gpt4 key购买 nike

我最近在创建 stringstream 时遇到了问题,因为我错误地假设 std::setw() 会影响每次插入的字符串流,直到我更改它明确地。但是,插入后始终未设置。

// With timestruct with value of 'Oct 7 9:04 AM'
std::stringstream ss;
ss.fill('0'); ss.setf(ios::right, ios::adjustfield);
ss << setw(2) << timestruct.tm_mday;
ss << timestruct.tm_hour;
ss << timestruct.tm_min;
std::string filingTime = ss.str(); // BAD: '0794'

所以,我有几个问题:

  • setw() 为什么会这样呢?
  • 还有其他操作者这样吗?
  • std::ios_base::width()std::setw() 之间的行为有区别吗?
  • 最后是否有明确记录这种行为的在线引用资料?我的供应商文档(MS Visual Studio 2005)似乎没有清楚地表明这一点。

最佳答案

来自以下评论的重要说明:

马丁:

@Chareles: Then by this requirement all manipulators are sticky. Except setw which seems to be reset after use.

查尔斯:

Exactly! and the only reason that setw appears to behave differently is because there are requirements on formatted output operations to explicitly .width(0) the output stream.

以下是得出上述结论的讨论:


查看代码,以下操纵器返回对象而不是流:

setiosflags
resetiosflags
setbase
setfill
setprecision
setw

这是一种将操作仅应用于应用于流的下一个对象的常用技术。不幸的是,这并不排除它们具有粘性。测试表明除了 setw 之外的所有这些都是粘性的。

setiosflags:  Sticky
resetiosflags:Sticky
setbase: Sticky
setfill: Sticky
setprecision: Sticky

所有其他操纵器都返回一个流对象。因此,它们更改的任何状态信息都必须记录在流对象中,因此是永久性的(直到另一个操纵器更改状态)。因此,以下操纵器必须是 Sticky 操纵器。

[no]boolalpha
[no]showbase
[no]showpoint
[no]showpos
[no]skipws
[no]unitbuf
[no]uppercase

dec/ hex/ oct

fixed/ scientific

internal/ left/ right

这些操纵器实际上对流本身而不是流对象执行操作(尽管从技术上讲,流是流对象状态的一部分)。但我不相信它们会影响流对象状态的任何其他部分。

ws/ endl/ ends/ flush

结论是 setw 似乎是我的版本中唯一不粘人的操纵器。

对于查尔斯来说,一个简单的技巧只影响链中的下一个项目:
这是一个示例,如何使用对象临时更改状态,然后通过使用对象将其恢复:

#include <iostream>
#include <iomanip>

// Private object constructed by the format object PutSquareBracket
struct SquareBracktAroundNextItem
{
SquareBracktAroundNextItem(std::ostream& str)
:m_str(str)
{}
std::ostream& m_str;
};

// New Format Object
struct PutSquareBracket
{};

// Format object passed to stream.
// All it does is return an object that can maintain state away from the
// stream object (so that it is not STICKY)
SquareBracktAroundNextItem operator<<(std::ostream& str,PutSquareBracket const& data)
{
return SquareBracktAroundNextItem(str);
}

// The Non Sticky formatting.
// Here we temporariy set formating to fixed with a precision of 10.
// After the next value is printed we return the stream to the original state
// Then return the stream for normal processing.
template<typename T>
std::ostream& operator<<(SquareBracktAroundNextItem const& bracket,T const& data)
{
std::ios_base::fmtflags flags = bracket.m_str.flags();
std::streamsize currentPrecision = bracket.m_str.precision();

bracket.m_str << '[' << std::fixed << std::setprecision(10) << data << std::setprecision(currentPrecision) << ']';

bracket.m_str.flags(flags);

return bracket.m_str;
}


int main()
{

std::cout << 5.34 << "\n" // Before
<< PutSquareBracket() << 5.34 << "\n" // Temp change settings.
<< 5.34 << "\n"; // After
}


> ./a.out
5.34
[5.3400000000]
5.34

关于c++ - 哪些 iomanip 操纵器是 'sticky' ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1532640/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com