Czy istnieje unput dla std::ostream, tak jak istnieje unget dla std::istream?

Mam kod analizujący, który pozwala na wprowadzenie sekwencji ucieczki do ciągu tekstowego:

// In a file or large, multi-line string ...
my_parameter="A setting for the parameter\nthat contains \"escape sequence\" characters"

Kiedy go analizuję, obsługuję ukośniki odwrotne i dodaję odpowiedni znak do ciągu, który buduję, używając instancji std::ostringstream. Przesuwy wierszy, cudzysłowy, ukośniki odwrotne i tym podobne działają dobrze. Jednakże zastanawiałem się, czy zezwolić na sekwencję \b, czy nie, i zacząłem sprawdzać, czy mogę „usunąć” ostatni znak z mojego ostringstream, tak jak można „usunąć” z dowolnego std::istream. Czy potrafisz zrobić coś takiego? Jeśli funkcja nie istnieje, czy istnieje prosty sposób na cofnięcie pozycji zapisu o jeden znak i po prostu nadpisanie jej przez następny znak?

Nie jest to kwestia krytyczna dla misji ani nic w tym stylu, ale byłem ciekawy, czy ktoś inny spotkał się z tym wcześniej.


person Will    schedule 10.12.2010    source źródło


Odpowiedzi (4)


Strumienie są bardzo podobne do poczty. każda wiadomość wysłana w strumieniu jest jak list, a wiadomości można umieścić w kolejce w buforach, które działają jak skrzynki pocztowe.

Jeśli byłeś odpowiedzialny zarówno za umieszczanie wiadomości w skrzynce pocztowej, jak i za jej wyjmowanie, z pewnością wiedziałbyś, że list, który właśnie tam wrzuciłeś, wciąż tam jest i możesz go odebrać. Oczywiście prawdopodobnie w ogóle nie zadałbyś sobie trudu wrzucenia go do skrzynki pocztowej, ponieważ oba końce są własnością Ciebie.

Jeśli zamiast tego wrzucisz list do skrzynki pocztowej swojej dziewczyny, tak naprawdę nie masz dużej kontroli nad tym, kiedy ona sprawdzi swoją skrzynkę pocztową i wyjmie wszystkie listy. możliwe, że siedzi przy drzwiach i od razu chwyta list i czyta go, gdy tylko przejdzie przez szczelinę.

Bardziej prawdopodobne jest, że faktycznie dostarczasz list do skrzynki należącej do poczty (systemu operacyjnego). Chociaż wiele takich pojemników to po prostu kosze i listonosz sprawdza je raz dziennie, może się zdarzyć, że szczelina będzie podłączona bezpośrednio do maszyny sortującej i list zostanie dostarczony natychmiast po jego upuszczeniu.

W interfejsie przesyłania strumieniowego ze współbieżnością nie ma ogólnego sposobu na odzyskanie własności po zapisaniu. Jeśli tego potrzebujesz, powinieneś umieścić bufor pośredni między tobą a strumieniem i wypuścić go do strumienia tylko wtedy, gdy wiesz na pewno, że jesteś gotowy.

person SingleNegationElimination    schedule 10.12.2010
comment
Chyba tak właśnie było. Myślę, że na dłuższą metę po prostu nie pozwolę na używanie \b (szczerze mówiąc, tak naprawdę nie powinno być takiej potrzeby w kontekście tej aplikacji) i nie muszę się tym martwić. Tylko jedno z tych dziwnych pytań, zastanawiam się, czy mogę…. - person Will; 11.12.2010
comment
Można skonfigurować lokalny bufor do przetwarzania \b s; ogólnie przyjmuje się, że Backspace nie może cofnąć znaku nowej linii, więc wystarczy buforować tylko jedną linię na raz. Nawiasem mówiąc, wiersz poleceń już to robi, przekazując informacje do programu na standardowe wejście. Możesz też wysłać dosłowne znaki Backspace i pozwolić odbiorcy zdecydować, jak sobie z nimi poradzić. - person Karl Knechtel; 11.12.2010

Możesz użyć seekp, aby ustawić pozycję kursora w strumieniu (patrz: http://cplusplus.com/reference/iostream/ostream/seekp/).

person Juraj Blaho    schedule 10.12.2010
comment
to był jeden z pomysłów, jaki miałem. problem może wystąpić, jeśli backspace był ostatnim znakiem w ciągu - nawet jeśli seekp cofnę jeden znak, czy nadal otrzymam ten ostatni znak, gdy wywołam str() na moim ostringstream? - person Will; 11.12.2010

Jeśli chcesz odzyskać postać, nie wysyłaj jej, dopóki nie będziesz pewien, że nie będziesz chciał jej przyjąć. Możesz zaimplementować własną logikę „zezwalaj na zwroty” w ten sposób:

int pending_ch = -1;
void output_char(int ch)
{
  if (pending_ch >= 0)
    putch(F, ch);
  pending_ch = ch;    
}
void unput_char(void)
{
  pending_ch = -1;
}
void force_put_char(void)
{
  output_char(-1);
}

Trochę niezgrabne, ale to ogólne podejście może być przydatne do opóźniania wyjścia do strumienia.

person supercat    schedule 11.12.2010
comment
Co się stanie, jeśli będzie chciał więcej niż jednego Backspace z rzędu? - person Puppy; 11.12.2010
comment
Następnie trzeba buforować więcej znaków. Jednakże analogia do ungetc wymagałaby tylko jednego znaku „odbioru”. - person supercat; 11.12.2010

Możesz po prostu samodzielnie wprowadzić znak Backspace. Przynajmniej zrobiłem to w konsoli Windows. Powinno to zapewnić przestrzeganie prawidłowego zachowania niezależnie od miejsca docelowego.

person Puppy    schedule 11.12.2010
comment
na konsoli tak, działa zgodnie z oczekiwaniami, ale po prostu pracuję z danymi w pamięci ... ciąg może być wyświetlany lub nie, i najprawdopodobniej w prostym GUI. - person Will; 11.12.2010