어떤 iomanip 조작자가 '고정적'입니까?
최근에 명시 적으로 변경할 때까지 모든 삽입에 대해 문자열 스트림에 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 : 그런 다음이 요구 사항에 따라 모든 조작자가 끈적 거리게됩니다. 사용 후 리셋 된 것으로 보이는 setw를 제외하고.
찰스
바로 그거죠! setw가 다르게 동작하는 유일한 이유는 출력 스트림을 명시 적으로 .width (0)하기위한 형식화 된 출력 작업에 대한 요구 사항이 있기 때문입니다.
다음은 위의 결론으로 이어지는 논의입니다.
다음 조작자는 코드를 보면 스트림이 아닌 객체를 반환합니다.
setiosflags
resetiosflags
setbase
setfill
setprecision
setw
이것은 스트림에 적용되는 다음 객체에만 작업을 적용하는 일반적인 기술입니다. 불행히도 이것은 끈적 거리는 것을 배제하지 않습니다. 테스트 결과를 제외하고 setw
는 모두 끈적임을 나타냅니다 .
setiosflags: Sticky
resetiosflags:Sticky
setbase: Sticky
setfill: Sticky
setprecision: 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가 내 버전에서 끈적 거리지 않는 유일한 조작자 인 것 같습니다.
Charles에게 체인의 다음 항목에만 영향을 미치는 간단한 트릭 :
다음은 오브젝트를 사용하여 상태를 일시적으로 변경 한 다음 오브젝트를 사용하여 다시 되돌릴 수있는 예제입니다.
#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
width
'고정적'으로 보이지 않는 이유 는 특정 작업이 .width(0)
출력 스트림 을 호출하도록 보장하기 때문 입니다. 사람들은:
21.3.7.9 [lib.string.io] :
template<class charT, class traits, class Allocator>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os,
const basic_string<charT,traits,Allocator>& str);
22.2.2.2.2 [lib.facet.num.put.virtuals]: All do_put
overloads for the num_put
template. These are used by overloads of operator<<
taking a basic_ostream
and a built in numeric type.
22.2.6.2.2 [lib.locale.money.put.virtuals]: All do_put
overloads for the money_put
template.
27.6.2.5.4 [lib.ostream.inserters.character]: Overloads of operator<<
taking a basic_ostream
and one of the char type of the basic_ostream instantiation or char
, signed char
or unsigned char
or pointers to arrays of these char types.
To be honest I'm not sure of the rationale for this, but no other states of an ostream
should be reset by formatted output functions. Of course, things like badbit
and failbit
may be set if there is a failure in the output operation, but that should be expected.
The only reason that I can think of for resetting the width is that it might be surprising if, when trying to output some delimited fields, your delimiters were padded.
E.g.
std::cout << std::setw(6) << 4.5 << '|' << 3.6 << '\n';
" 4.5 | 3.6 \n"
To 'correct' this would take:
std::cout << std::setw(6) << 4.5 << std::setw(0) << '|' << std::setw(6) << 3.6 << std::setw(0) << '\n';
whereas with a resetting width, the desired output can be generated with the shorter:
std::cout << std::setw(6) << 4.5 << '|' << std::setw(6) << 3.6 << '\n';
setw()
only affects the next insertion. That's just the way setw()
behaves. The behavior of setw()
is the same as ios_base::width()
. I got my setw()
information from cplusplus.com.
You can find a full list of manipulators here. From that link, all the stream flags should say set until changed by another manipulator. One note about the left
, right
and internal
manipulators: They are like the other flags and do persist until changed. However, they only have an effect when the width of the stream is set, and the width must be set every line. So, for example
cout.width(6);
cout << right << "a" << endl;
cout.width(6);
cout << "b" << endl;
cout.width(6);
cout << "c" << endl;
would give you
> a
> b
> c
but
cout.width(6);
cout << right << "a" << endl;
cout << "b" << endl;
cout << "c" << endl;
would give you
> a
>b
>c
The Input and Output manipulators are not sticky and only occur once where they are used. The parametrized manipulators are each different, here's a brief description of each:
setiosflags
lets you manually set flags, a list of which can be fount here, so it is sticky.
resetiosflags
behaves the similar to setiosflags
except it unsets the specified flags.
setbase
sets the base of integers inserted into the stream (so 17 in base 16 would be "11", and in base 2 would be "10001").
setfill
sets the fill character to insert in the stream when setw
is used.
setprecision
sets the decimal precision to be used when inserting floating point values.
setw
makes only the next insertion the specified width by filling with the character specified in setfill
참고URL : https://stackoverflow.com/questions/1532640/which-iomanip-manipulators-are-sticky
'Programming' 카테고리의 다른 글
의미 (0) | 2020.07.01 |
---|---|
ActivityManager의 이상한 기능 : isUserAMonkey. (0) | 2020.07.01 |
λ- 미적분 최적 평가자가 공식없이 큰 모듈 식 지수를 계산할 수있는 이유는 무엇입니까? (0) | 2020.07.01 |
ES6 모듈 가져 오기에 옵션 전달 (0) | 2020.07.01 |
AngularJS와 $ http를 동기화하는 방법 (0) | 2020.07.01 |