哪些iomanip操纵器是'粘性'? [英] Which iomanip manipulators are 'sticky'?

查看:285
本文介绍了哪些iomanip操纵器是'粘性'?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近有一个问题创建一个字符串流,由于我错误地假设std :: setw()将影响每个插入的字符串流,直到我明确地更改它。

I recently had a problem creating a stringstream due to the fact that I incorrectly assumed std::setw() would affect the stringstream for every insertion, until I changed it explicitly. However, it is always unset after the insertion.

// 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)似乎没有清楚地显示这一点。

  • Why is setw() this way?
  • Are any other manipulators this way?
  • Is there a difference in behavior between std::ios_base::width() and std::setw()?
  • Finally is there an online reference that clearly documents this behavior? My vendor documentation (MS Visual Studio 2005) doesn't seem to clearly show this.

推荐答案

以下注释中的重要注释:

Important notes from the comments below:

由Martin提供:


@Chareles :然后通过这个要求所有的操纵器都是粘的。

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

由Charles:


确切!并且setw看起来有不同行为的唯一原因是因为对格式化输出操作有明确的.width(0)输出流的要求。

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.

以下是导致上述结论的讨论:

The following is the discussion that lead to the above conclusion:

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

Looking at the code the following manipulators return an object rather than a stream:

setiosflags
resetiosflags
setbase
setfill
setprecision
setw

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

This is a common technique to apply an operation to only the next object that is applied to the stream. Unfortunately this does not preclude them from being sticky. Tests indicate that all of them except setw are sticky.

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

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

All the other manipulators return a stream object. Thus any state information they change must be recorded in the stream object and is thus permanent (until another manipulator changes the state). Thus the following manipulators must be Sticky manipulators.

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

dec/ hex/ oct

fixed/ scientific

internal/ left/ right

$ b b

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

These manipulators actually perform an operation on the stream itself rather than the stream object (Though technically the stream is part of the stream objects state). But I do not believe they affect any other part of the stream objects state.

ws/ endl/ ends/ flush

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

The conclusion is that setw seems to be the only manipulator on my version that is not sticky.

对于Charles来说,一个简单的技巧只影响链中的下一个项目:

这里是一个对象如何被用来暂时改变状态,通过使用对象返回:

For Charles a simple trick to affect only the next item in the chain:
Here is an Example how an object can be used to temporaily change the state then put it back by the use of an object:

#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

这篇关于哪些iomanip操纵器是'粘性'?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆