2015-06-17 5 views
18

Używam obszernie std::stringstream do generowania kodu. Podczas ustawiania treści przy pomocy funkcji str() napotkam pewne wątpliwe zachowanie, a następnie używam operator<<. Czy ktoś może mi wyjaśnić to zachowanie? Byłbym bardzo wdzięczny - dzięki.Ustawienie zawartości std :: stringstream z str (const char *) ma dziwne konsekwencje

Przykład pierwszy:

std::stringstream ssa; 
ssa.str("Setting string"); 
std::cout << ssa.str() << std::endl; 
ssa << " adding to string"; 
std::cout << ssa.str() << std::endl; 

wyjściowa:

Ustawienie ciąg

dodając ciąg

spodziewanych:

Ustawienie ciąg

Ustawianie ciąg dodając ciąg

Więc po kawałku czytania na dokumentacji znalazłem, że należy ustawić tryb otwarty do ios_base::ate:

std::stringstream ssb(std::ios_base::ate); 
ssb.str("Setting string"); 
std::cout << ssb.str() << std::endl; 
ssb << " adding to string"; 
std::cout << ssb.str() << std::endl; 

Output :

Łańcuch ustawień

Ustawienie ciąg

Again (lub teraz) spodziewałbym:

Ustawienie ciąg

Ustawienie ciąg dodając ciąg

Dlaczego otrzymuję wyników I jestem i jak mogę uzyskać pożądany rezultat? E.i. Czy można ustawić początkowe string z stringstream i dołączyć do tego string?

Mam świadomość, że mogę po prostu ustawić zawartość na pustą string(""), a następnie użyć tylko <<operator. Jest to w rzeczywistości obejście, którego używam. Po prostu nie rozumiem zaobserwowanego zachowania. A obejście to sprawia, że ​​mój kod jest bardziej brudny.

+1

Na drugim, albo zrobić 'std :: ios_base :: out | std :: ios_base :: ate' lub użyj 'ostringstream'. –

Odpowiedz

6

zapomniałeś ustawić tryb flag std::ios_base::out. to będzie działać:

std::stringstream ssb(std::ios_base::out | std::ios_base::ate); 
ssb.str("Setting string"); 
std::cout << ssb.str() << std::endl; 
ssb << " adding to string"; 
std::cout << ssb.str() << std::endl; 

wyjściowa:

Setting string 
Setting string adding to string 
+1

Dlatego wolę używać 'std :: istreamstream' i' std :: ostringstream' zamiast 'std :: stringstream', wtedy nie ma wątpliwości co do trybu wejścia/wyjścia. –

+0

Czy czytanie z 'str()' zamyka i ponownie otwiera strumień? Czy właśnie dlatego 'std :: ios_base :: ate' jest potrzebny, aby to działało? Bez niego, "<<" dodanie do napisu "' nadpisuje, zamiast dołącza, dane ustawione przez poprzednie 'str (" Setting string ")'. –

+0

@RemyLebeau tak, dodano do odpowiedzi, nadpisuje się bez ios_base :: zjadł –

11

Domyślnym trybem otwartym dla obiektu std::stringstream jest in | out. Użycie innego trybu zastępuje te opcje. Ponieważ strumienia nie można zapisać, operator wstawiania nie może być używany do zapisu do strumienia. Dlatego str() daje ten sam wynik dwukrotnie.

być konieczne ręczne otwarcie strumienia w trybie wyjściowym, a także:

std::stringstream ssb("Setting string", std::ios_base::out | std::ios_base::ate); 

Live Demo

Alternatywnie użyć std::ostringstream, który inicjuje wewnętrzny std::stringbuf podobiekt z out | mode.

std::ostringstream("Setting string", std::ios_base::ate); 

Live Demo

+0

tylko z ciekawości, jaki jest sens posiadania 'streamstream' w/o' in' i 'out' tryby? Ok, mogę sobie wyobrazić, że można je dodać później. Ale dlaczego operator wyjściowy nie rzuca wyjątku, jeśli 'streamstream' nie ma trybu 'out'? Ignorowanie w trybie cichym nie wygląda dobrze –

+0

@AndyT Konkretne klasy 'std :: iostream' (' std :: fstream' i 'std :: stringstream') są tworzone przy założeniu, że wiesz jak je zainicjować. Więc przekazuje tryb do bazowego bufora, tak jak jest, ponieważ nie może założyć, że chcesz czegoś konkretnego. Nie mogę wymyślić żadnego przypadku użycia dla strumienia, który nie może wykonać wejścia ani wyjścia. Ponadto strumienie nie generują wyjątków domyślnie, ale można włączyć wyjątki przy użyciu maski 'std :: basic_ios :: exceptions()'. – 0x499602D2

Powiązane problemy