iostreams - вывод чисел в двоичной с/с и прочие расширения
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 19.07.18 18:53
Оценка:
Здравствуйте!

Реально ли сделать такое без залезания в кишки iostreams, как-нибудь в сторонке?

Мне всегда не хватало такого, но как-то не заморачивался. А тут сделал подсистему вывода для своего проекта — попроще в реализации, без развесистой иерархии классов, но с той же концепцией — operator ostream inserter, методы потока и манипуляторы вывода, совместимой с iostreams по всем базовым прикладным вещам: методам потоков, флагам "ios...", манипуляторам и тп — она совместима со стандартной библиотекой. Бонус в том, что не надо много нового изучать, и по большей части можно заглянуть в доку на стандартные потоки и всё там найти.

Так вот, добавил я там немного своих расширений:


Вообщем, сделал я всё это, и понравилось мне это. И стал я активно пользоваться. Только вот код стал уже непереносим на стандартные потоки. В принципе, у меня для вывода предусмотрен интерфейс типа IWritter, и я сделал биндинги для стандартных потоков, но вот стало интересно, а можно ли стандартные потоки расширить, чтобы реализовать мои хотелки без моих прокладок, а в виде расширений стандартных потоков?

Так-то и то и то вроде как прокладки, но в текущей реализации у меня есть MyOstream и для него биндинги StdOstreamWritter/StdCoutWritter/StdCerrWritter и надо их настраивать перед стартом программы, что неудобно. А хочется, чтобы подключил какой-то хидер — и всё, все фичи присосались автоматом ко всем реализациям std::ostream
Маньяк Робокряк колесит по городу
Re: iostreams - вывод чисел в двоичной с/с и прочие расширения
От: LaptevVV Россия  
Дата: 19.07.18 19:06
Оценка:
M>Реально ли сделать такое без залезания в кишки iostreams, как-нибудь в сторонке?
Ну, посмотри в моей книжке.
В последней главе про ввод-вывод есть параграф "Написание собственных манипуляторов"
Вот отрывок оттуда:

Написать манипулятор с аргументами несколько сложнее. Собственно, для создания манипулятора, совместимого по интерфейсу со стандартными манипуляторами, нужно разобраться в стандартном механизме реализации. Однако вместо этого можно просто написать некоторый класс, для которого, как обычно, определить функцию operator<<. Джерри Шварц назвал такие классы эффекторами (см. также [12]). Например, пусть нам требуется выводить целые значения в двоичном виде. Напишем класс binary (листинг 14.13).
Листинг 14.13. «Манипулятор» для двоичного вывода

class binary
{ unsigned long k;
  public:
    binary(unsigned long k): k(k) {}
    friend ostream& operator<<(ostream& os, const binary& t);
};
inline ostream& operator<<(ostream& os, const binary& t)
{ const unsigned long MAX = numeric_limits<unsigned long>::max();
  unsigned long bit = ~(MAX >> 1);                    // старший бит
  while(bit) { os << (t.k & bit?'1':'0'); bit >>= 1; }
  return os;
}

В функции operator<< самыми важными являются две строки:
const unsigned long MAX = numeric_limits<unsigned long>::max();
unsigned long bit = ~(MAX >> 1); // старший бит
В первой строке в переменную MAX заносится максимально возможное беззнаковое целое число, определенное в стандартном классе числовых пределов numeric_limits.

Как видишь, без залезания внутрь.
Ссыль [12] — это Брюс Эккель. Философия С++, том 2.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: iostreams - вывод чисел в двоичной с/с и прочие расширения
От: watchmaker  
Дата: 19.07.18 23:55
Оценка:
Здравствуйте, LaptevVV, Вы писали:


LVV>Как видишь, без залезания внутрь.


Пример хороший. Но, если честно, то это весьма посредственный манипулятор Я бы его просто назвал классом binary, для которого перегружен оператор вывода в поток. Практически с тем же успехом можно его заменить на функцию с сигнатурой вида std::string binary(unsigned long). Хотя конечно, в приведённом варианте не создаётся временная строка, и это может быть хорошим и желаемым поведением в более сложных случаях.

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

LVV>Ну, посмотри в моей книжке.

Не знаю о какой книжке идёт речь. Но соглашусь, что её стоит посмотреть, если там дальше описывается как с помощью xalloc зарегистрировать новый манипулятор, как через pword правильно сохранять и читать произвольные данные в стандартных потоках, и как через facets применить все эти новые правила к стандартным типам (а не только к новым пользовательским). Жалко, что в приведённом отрывке об этой тёмной стороне потоков ничего нет

  Скрытый текст
(впрочем, iostreams прокляты, и лучше с ними вообще не иметь дело, я считаю)
Re[2]: iostreams - вывод чисел в двоичной с/с и прочие расширения
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 23.07.18 18:38
Оценка:
Здравствуйте, LaptevVV, Вы писали:

M>>Реально ли сделать такое без залезания в кишки iostreams, как-нибудь в сторонке?

LVV>Ну, посмотри в моей книжке.
LVV>В последней главе про ввод-вывод есть параграф "Написание собственных манипуляторов"
LVV>Вот отрывок оттуда:

Ну, это ни разу ни манипулятор, а standalone класс для вывода в двоичном виде. Причем его надо явно вызывать. watchmaker уже все написал, добавить нечего. Такие классы я давно писал.

ЗЫ Видимо, мои хотелки нельзя реализовать
Маньяк Робокряк колесит по городу
Re[3]: iostreams - вывод чисел в двоичной с/с и прочие расши
От: watchmaker  
Дата: 23.07.18 19:33
Оценка:
Здравствуйте, Marty, Вы писали:

M>ЗЫ Видимо, мои хотелки нельзя реализовать

В смысле? xalloc + pword и вперёд! Сложно и многословно, да. Но возможно. Вот пример как сделатать собственный манипулятор bin: https://accu.org/index.php/journals/350
Отредактировано 23.07.2018 19:43 watchmaker . Предыдущая версия .
Re[4]: iostreams - вывод чисел в двоичной с/с и прочие расширения
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 23.07.18 19:44
Оценка:
Здравствуйте, watchmaker, Вы писали:

M>>ЗЫ Видимо, мои хотелки нельзя реализовать

W>В смысле? xalloc + pword и вперёд! Сложно и многословно, да. Но возможно.

Хм. А как с их помощью сделать вывод в двоичном виде для существующих типов?
Маньяк Робокряк колесит по городу
Re: iostreams - вывод чисел в двоичной с/с и прочие расширения
От: кт  
Дата: 24.07.18 07:42
Оценка:
Здравствуйте, Marty, Вы писали:

M>Здравствуйте!

M>Реально ли сделать такое без залезания в кишки iostreams, как-нибудь в сторонке?
M>Мне всегда не хватало такого, но как-то не заморачивался.

а в старину проблему вывода в двоичной не знали
test:proc main;
declare
x float(53),
y bit(64) defined(x);

x=12345.6789;

put skip edit('x=',y)(a,b4(16));// вывод в 16-ричном
put skip data(y);               // вывод в двоичном

end test;

x=40C81CD6E631F8A0
Y= '0100000011001000000111001101011011100110001100011111100010100000'b
Re[2]: iostreams - вывод чисел в двоичной с/с и прочие расширения
От: IID Россия  
Дата: 13.08.18 07:36
Оценка: +1 :)
Здравствуйте, кт, Вы писали:

кт>а в старину проблему вывода в двоичной не знали

кт>
кт>test:proc main;
кт>declare
кт>x float(53),
кт>y bit(64) defined(x);

кт>x=12345.6789;

кт>put skip edit('x=',y)(a,b4(16));// вывод в 16-ричном
кт>put skip data(y);               // вывод в двоичном

кт>end test;

кт>x=40C81CD6E631F8A0
кт>Y= '0100000011001000000111001101011011100110001100011111100010100000'b
кт>


неудивительно что это убожество издохло
kalsarikännit
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.