@random-guy

Можно ли/как получить хвост вывода sprintf?

TL;DR: можно ли используя какой-нибудь из вариантов sprintf и не используя дополнительную память получить последние n символов вывода?

Детали: имеется система с очень ограниченной памятью. Часть этой памяти выделена для ring-буфера, в который выводят символы переопределённые функции из семейства printf. Т.е. printf("Hello world\n"); помещает Hello world\n в текущую позицию записи в этот кольцевой буфер и продвигает текущую позицию вперёд. Когда указатель подходит к концу буфера и длина выводимой строки оказывается больше, чем доступно места, строка должна "сломаться", т.е. начало строки должно оказаться в конце буфера, а конец строки -- в начале (полагая, что место в начале уже освобождено), т.е. должно получиться, например, так: char buf[16] = "orld\n\0\0\0\0Hello w"; Чтобы отрезать хвост выводимой строки я могу использовать snprintf, но каким образом я могу отрезать голову выводимой строки? И, да, конечно, ответ в стиле "отступи n байт от начала строки и печатай" не подходит, потому что в строке будет не Hello world, а "%s: a[%d] = %d".
Я подозреваю, что сделать этого нельзя, но мало ли, вдруг есть способ?
  • Вопрос задан
  • 144 просмотра
Решения вопроса 1
@forspamonly2
интересный вопрос, редкость тут.

приходит в голову два варианта организации кольцевого буфера прозрачно для остального стдлиба.

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

второй вариант: можно сделать свой стрим (man fopencookie). для вашей цели достаточно написать только обработчик записи, который собственно и будет закольцовывать буфер: копировать сколько влезло в конец, а остальное в начало. и выводить всё в этот стрим fsprinf-ами и прочими функциями работы с потоками. может быть даже получится перенаправить stdout в этот самодельный поток, тогда и обычные printf'ы заработают.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
zoonman
@zoonman
⋆⋆⋆⋆⋆
Если у вас терминирующий символ, например 0x00, то можно сканировать буфер и при обнаружении перехода с 0x00 на что-то другое начинать считывать по кругу, пока не упретесь до 0x00 снова.

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

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы