std :: cout 조작 후 상태 복원
다음과 같은 코드가 있다고 가정합니다.
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..
}
내 질문은 cout
함수에서 돌아온 후 상태를 원래 상태로 '복원'할 방법이 있는지 여부입니다 . (어느 정도 std::boolalpha
와 std::noboolalpha
..)?
감사.
필요 #include <iostream>
하거나 #include <ios>
필요할 때 :
std::ios_base::fmtflags f( cout.flags() );
//Your code here...
cout.flags( f );
함수의 시작과 끝에 넣거나 RAII 와 함께 사용하는 방법에 대한 이 답변 을 확인할 수 있습니다 .
부스트 IO 스트림 주립 보호기는 당신이 필요로 정확히 보인다. :-)
코드 스 니펫을 기반으로 한 예 :
void printHex(std::ostream& x) {
boost::io::ios_flags_saver ifs(x);
x << std::hex << 123;
}
여기에 제시된 답변은의 전체 상태를 복원하지 않습니다 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;
다음을 인쇄합니다.
case closed
보다는 :
case closed0000
이 답변의 예제 코드를 사용하여 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;
};
그런 다음 현재 플래그 상태를 저장하고 싶을 때마다 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;
}
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..
}
You can create another wrapper around the stdout buffer:
#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.
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).
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&
.
참고URL : https://stackoverflow.com/questions/2273330/restore-the-state-of-stdcout-after-manipulating-it
'programing tip' 카테고리의 다른 글
margin : auto 이미지를 중앙에 배치하지 않는 이유는 무엇입니까? (0) | 2020.09.05 |
---|---|
디버깅 할 때 인수로 프로그램을 시작하려면 어떻게합니까? (0) | 2020.09.05 |
원격 JMX 연결 (0) | 2020.09.05 |
C #에서 XmlReader로 Xml 읽기 (0) | 2020.09.05 |
OrderBy 파이프 문제 (0) | 2020.09.05 |