Существует ли unput для std::ostream, как существует unget для std::istream?

У меня есть код синтаксического анализа, который позволяет вводить escape-последовательности в строку текста:

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

Когда я анализирую его, я обрабатываю обратную косую черту и добавляю соответствующий символ в строку, которую я создаю, используя экземпляр std::ostringstream. Перевод строки, кавычки, обратная косая черта и тому подобное работают нормально. Тем не менее, я обдумывал, разрешать ли последовательность \b, и пошел посмотреть, смогу ли я «удалить» последний символ из моего ostringstream, как вы можете «удалить» из любого std::istream. Можешь ли ты сделать такое? Если функция не существует, есть ли простой способ отодвинуть позицию записи назад на один символ и просто перезаписать ее следующим символом?

Это не критично для миссии или что-то в этом роде, но мне было любопытно, сталкивался ли кто-нибудь еще с этим раньше.


person Will    schedule 10.12.2010    source источник


Ответы (4)


Потоки очень похожи на почту. каждое сообщение, отправленное в потоке, подобно письму, и сообщения могут быть поставлены в очередь в буферах, которые подобны почтовым ящикам.

Если бы вы отвечали как за отправку сообщений в почтовый ящик, так и за извлечение сообщений из него, то вы наверняка знали бы, что письмо, которое вы только что положили туда, все еще там, и вы можете забрать его обратно. Конечно, вы, вероятно, вообще не станете класть его в почтовый ящик, поскольку вы владеете обоими концами.

Если вместо этого вы кладете письмо в почтовый ящик своей подруги, у вас практически нет контроля над тем, когда она проверит свой почтовый ящик и достанет все письма. может быть, она сидит у двери и сразу же схватит письмо и прочтет его, как только оно пройдет через щель.

Скорее всего, вы на самом деле доставляете письмо в ящик, принадлежащий почтовому отделению (операционной системе). Хотя многие такие сосуды представляют собой просто мусорные ведра, и почтальон проверяет их раз в день, может случиться так, что слот подключен непосредственно к сортировочной машине, и письмо будет доставлено сразу же, как только вы его уроните.

В потоковом интерфейсе с параллелизмом нет общего способа вернуть право собственности на запись после ее записи. Если вам это нужно, вы должны поместить промежуточный буфер между вами и потоком и сбрасывать его в поток только тогда, когда вы наверняка знаете, что готовы.

person SingleNegationElimination    schedule 10.12.2010
comment
Типа догадался, что так оно и есть. Я думаю, что в долгосрочной перспективе я просто не позволю использовать \b (честно говоря, в любом случае в контексте этого приложения в этом не должно быть необходимости) и не должен беспокоиться об этом. Просто один из тех странных вопросов, я думаю, могу ли я... - person Will; 11.12.2010
comment
Вы можете настроить локальный буфер для обработки \b s; общепринято, что backspace не может отменить перевод строки, поэтому вам нужно буферизовать только строку за раз. Между прочим, командная строка уже делает это, когда передает информацию вашей программе на стандартный ввод. Или вы можете отправить буквальные символы возврата, и пусть принимающая сторона решит, как с ними обращаться. - person Karl Knechtel; 11.12.2010

Вы можете использовать seekp для установки позиции курсора в потоке (см.: http://cplusplus.com/reference/iostream/ostream/seekp/).

person Juraj Blaho    schedule 10.12.2010
comment
это была одна из моих идей. проблема может возникнуть, если backspace был последним символом в строке - даже если я seekp верну один символ, я все равно получу этот последний символ, когда я вызову str() на моем ostringstream? - person Will; 11.12.2010

Если вы хотите забрать персонажа, не отправляйте его, пока не будете уверены, что не захотите забирать его обратно. Вы можете реализовать свою собственную логику «разрешить возврат» следующим образом:

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);
}

Немного неуклюжий, но этот общий подход может быть полезен для задержки вывода в поток.

person supercat    schedule 11.12.2010
comment
Что произойдет, если он захочет более одного возврата подряд? - person Puppy; 11.12.2010
comment
Тогда нужно буферизовать больше символов, чем это. Однако аналогия с ungetc потребует только одного символа «возврата». - person supercat; 11.12.2010

Вы можете просто ввести символ возврата самостоятельно. Я сделал это в консоли Windows, по крайней мере. Это должно гарантировать, что правильное поведение соблюдается независимо от пункта назначения.

person Puppy    schedule 11.12.2010
comment
в консоли да, работает как положено, но я просто работаю с данными в памяти... строка может отображаться или не отображаться, и скорее всего в простом графическом интерфейсе. - person Will; 11.12.2010