如何自动将流模式设置回默认值

How to automatically set stream mode back to default

本文关键字:设置 默认值 模式 何自动      更新时间:2023-10-16

>C++ Steam 对象具有状态。如果一个人写一段代码,比如

using namespace std; 
cout << hex << setw(8) << setfill('0') << x << endl;

忘记将流状态设置回来。这将导致其他一些不相关的代码出现问题。进行"设置"和"设置"配对很繁琐。除此之外,在我看来,这也违反了RAII背后的惯例。

我的问题是:是否有可能,只有一层薄薄的包裹,使这些状态操作像RAII一样。也就是说,在表达式用分号结束之后,流状态会自动设置回默认值。

更新:按照@0x499602D2提供的链接,一种解决方法可能是类似

#include <boost/io/ios_state.hpp>
#include <ios>
#include <iostream>
#include <ostream>
#define AUTO_COUT(x) {
boost::io::ios_all_saver  ias( cout );
x;
}while(0)

然后可以使用宏,例如

AUTO_COUT(cout << hex << setw(8) << setfill('0') << x << endl);

顺便说一句,在 boost::io::ios_state 的那些保护类中添加一个锁定字段可能是个好主意,以防多线程程序中发生有趣的事情。还是他们已经这样做了?

我将提出另一种方法。操纵器适用于std::[i|o]stream实例,但它们对std::[i|o]stream管理的std::[i|o]streambuf不执行任何操作。

因此,您可以创建自己的std::[i|o]stream,它将具有自己的格式化状态,但写入同一缓冲区std::cout使用:

#include <iostream>
#include <iomanip>
int main()
{
std::cout << std::hex << 32 << "n";
std::ostream os(std::cout.rdbuf());
os << 32 << "n" << std::hex;
std::cout << std::dec;
os << 32 << "n";
std::cout << 32 << "n";
}

输出:

20
32
20
32

住在科里鲁

这仅使用标准库中的功能,并且由于未触及原始流,因此应用操纵器是线程安全的(因为每个线程在不同的流上运行)。现在,实际写入和读取的线程安全性取决于托管流缓冲区的线程安全性。

我曾经写过一个实用程序类供我个人使用。(我不知道它是否像提升代码一样完美,但它对我有用——所以,我敢分享。

#include <iostream>
#include <iomanip>
/** provides a helper class to work with streams.
*
* It stores current format states of a stream in constructor and
* recovers these settings in destructor.
*
* Example:
* <pre>
* { // backup states of std::cout
*   IOSFmtBackup stateCOut(std::cout);
*   // do some formatted output
*   std::cout
*     << "dec: " << std::dec << 123 << std::endl
*     << "hex: " << std::hex << std::setw(8) << std::setfill('0')
*     << 0xdeadbeef << std::endl;
* } // destruction of stateCOut recovers former states of std::cout
* </pre>
*/
class IOSFmtBackup {
// variables:
private:
/// the concerning stream
std::ios &_stream;
/// the backup of formatter states
std::ios _fmt;
// methods:
public:
/// @name Construction & Destruction
//@{
/** constructor.
*
* @param stream the stream for backup
*/
explicit IOSFmtBackup(std::ios &stream):
_stream(stream), _fmt(0)
{
_fmt.copyfmt(_stream);
}
/// destructor.
~IOSFmtBackup() { _stream.copyfmt(_fmt); }
// disabled:
IOSFmtBackup(const IOSFmtBackup&) = delete;
IOSFmtBackup& operator=(const IOSFmtBackup&) = delete;
//@}
};
int main()
{
{ // backup states of std::cout
IOSFmtBackup stateCOut(std::cout);
// do some formatted output
std::cout
<< "dec: " << std::dec << 123 << std::endl
<< "hex: " << std::hex << std::setw(8) << std::setfill('0')
<< 0xdeadbeef << std::endl
<< "123 in current: " << 123 << std::endl;
} // destruction of stateCOut recovers former states of std::cout
// check whether formatting is recovered
std::cout << "123 after recovered: " << 123 << std::endl;
return 0;
}

ideone上编译和测试(生活演示)。

输出:

dec: 123
hex: deadbeef
123 in current: 7b
123 after recovered: 123