C++ 操作后恢复 std::cout 的状态
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2273330/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Restore the state of std::cout after manipulating it
提问by UltraInstinct
Suppose I have a code like this:
假设我有这样的代码:
void printHex(std::ostream& x){
x<<std::hex<<123;
}
..
int main(){
std::cout<<100; // prints 100 base 10
printHex(std::cout); //prints 123 in hex
std::cout<<73; //problem! prints 73 in hex..
}
My question is if there is any way to 'restore' the state of cout
to its original one after returning from the function? (Somewhat like std::boolalpha
and std::noboolalpha
..) ?
我的问题是,cout
从函数返回后,是否有任何方法可以将状态“恢复”到原来的状态?(有点喜欢std::boolalpha
和std::noboolalpha
..)?
Thanks.
谢谢。
采纳答案by Stefan Kendall
you need to #include <iostream>
or #include <ios>
then when required:
您需要#include <iostream>
或#include <ios>
在需要时:
std::ios_base::fmtflags f( cout.flags() );
//Your code here...
cout.flags( f );
You can put these at the beginning and end of your function, or check out this answeron how to use this with RAII.
回答by Chris Jester-Young
The Boost IO Stream State Saverseems exactly what you need. :-)
该升压IO流状态节电器似乎正是你需要的。:-)
Example based on your code snippet:
基于您的代码片段的示例:
void printHex(std::ostream& x) {
boost::io::ios_flags_saver ifs(x);
x << std::hex << 123;
}
回答by rr-
Note that the answers presented here won't restore the full state of std::cout
. For example, std::setfill
will "stick" even after calling .flags()
. A better solution is to use .copyfmt
:
请注意,此处提供的答案不会恢复std::cout
. 例如,std::setfill
即使在调用.flags()
. 更好的解决方案是使用.copyfmt
:
std::ios oldState(nullptr);
oldState.copyfmt(std::cout);
std::cout
<< std::hex
<< std::setw(8)
<< std::setfill('0')
<< 0xDECEA5ED
<< std::endl;
std::cout.copyfmt(oldState);
std::cout
<< std::setw(15)
<< std::left
<< "case closed"
<< std::endl;
Will print:
将打印:
case closed
rather than:
而不是:
case closed0000
回答by qbert220
I've created an RAII class using the example code from this answer. The big advantage to this technique comes if you have multiple return paths from a function that sets flags on an iostream. Whichever return path is used, the destructor will always be called and the flags will always get reset. There is no chance of forgetting to restore the flags when the function returns.
我使用此答案中的示例代码创建了一个 RAII 类。如果在 iostream 上设置标志的函数有多个返回路径,则此技术的巨大优势就来了。无论使用哪个返回路径,总是会调用析构函数并且总是会重置标志。当函数返回时,不会忘记恢复标志。
class IosFlagSaver {
public:
explicit IosFlagSaver(std::ostream& _ios):
ios(_ios),
f(_ios.flags()) {
}
~IosFlagSaver() {
ios.flags(f);
}
IosFlagSaver(const IosFlagSaver &rhs) = delete;
IosFlagSaver& operator= (const IosFlagSaver& rhs) = delete;
private:
std::ostream& ios;
std::ios::fmtflags f;
};
You would then use it by creating a local instance of IosFlagSaver whenever you wanted to save the current flag state. When this instance goes out of scope, the flag state will be restored.
然后,只要您想保存当前标志状态,就可以通过创建 IosFlagSaver 的本地实例来使用它。当此实例超出范围时,将恢复标志状态。
void f(int i) {
IosFlagSaver iosfs(std::cout);
std::cout << i << " " << std::hex << i << " ";
if (i < 100) {
std::cout << std::endl;
return;
}
std::cout << std::oct << i << std::endl;
}
回答by n.caillou
You can create another wrapper around the stdout buffer:
您可以在 stdout 缓冲区周围创建另一个包装器:
#include <iostream>
#include <iomanip>
int main() {
int x = 76;
std::ostream hexcout (std::cout.rdbuf());
hexcout << std::hex;
std::cout << x << "\n"; // still "76"
hexcout << x << "\n"; // "4c"
}
In a function:
在一个函数中:
void print(std::ostream& os) {
std::ostream copy (os.rdbuf());
copy << std::hex;
copy << 123;
}
Of course if performance is an issue this is a bit more expensive because it's copying the entire ios
object (but not the buffer) including some stuff that you're paying for but unlikely to use such as the locale.
当然,如果性能是一个问题,这会更昂贵一些,因为它复制整个ios
对象(但不是缓冲区),包括一些您付费但不太可能使用的内容,例如语言环境。
Otherwise I feel like if you're going to use .flags()
it's better to be consistent and use .setf()
as well rather than the <<
syntax (pure question of style).
否则我觉得如果你要使用.flags()
它最好保持一致并使用.setf()
而不是<<
语法(纯粹的风格问题)。
void print(std::ostream& os) {
std::ios::fmtflags os_flags (os.flags());
os.setf(std::ios::hex);
os << 123;
os.flags(os_flags);
}
As others have said you can put the above (and .precision()
and .fill()
, but typically not the locale and words-related stuff that is usually not going to be modified and is heavier) in a class for convenience and to make it exception-safe; the constructor should accept std::ios&
.
正如其他人所说,为了方便并使其异常安全,您可以将上述(和.precision()
和.fill()
,但通常不是通常不会修改且更重的语言环境和与单词相关的内容)放在一个类中;构造函数应该接受std::ios&
.
回答by whacko__Cracko
With a little bit of modification to make the output more readable :
稍加修改,使输出更具可读性:
void printHex(std::ostream& x) {
ios::fmtflags f(x.flags());
x << std::hex << 123 << "\n";
x.flags(f);
}
int main() {
std::cout << 100 << "\n"; // prints 100 base 10
printHex(std::cout); // prints 123 in hex
std::cout << 73 << "\n"; // problem! prints 73 in hex..
}