LINUX.ORG.RU

KnR задание 5.19 «умный alloc»

 ,


0

4

Привет, дружелюбное сообщество.

Решаю задачку в KnR номер 5.19 (глава 5.10):

/***********************************************************************************/
/* Напишите программу tail для вывода последних п строк ее входного потока данных. */
/* Пусть значение п по умолчанию будет равно, скажем, десяти, но сделайте так,     */
/* 	чтобы его можно было изменить необязательным аргументом.                   */
/* Пусть следующая командная строка задает вывод последних п строк:                */
/*   tail -п                                                                       */
/* Программа должна вести себя устойчиво и рационально даже с самыми нелепыми      */
/* 	значениями п и содержимым входного потока. Напишите ее так, чтобы она      */
/* 	максимально экономно использовала память: строки должны храниться таким    */
/* 	образом, как в программе сортировки из раздела 5.6, а не в двумерном       */
/* 	массиве фиксированного размера.                                            */
/***********************************************************************************/

На clc-wiki мне не понравились варианты - http://clc-wiki.net/wiki/K&R2_solutions:Chapter_5:Exercise_13

Первый - это дичайший оверхэд, во втором чувак использует malloc (а я ищу решения категории 0). Третье и четвертое - по сути одно и то же. Буду рассматривать четвертое. Это первое что пришло в голову - сделать как в главе 5.6, а потом взять последние n строк. Если коротко, то создается allocbuf, на каждую строку вызывается p=alloc(len), строка копируется по адресу p. а указатель p записывается в lineptr[i] - массив указателей.

Но. В задании же сказано про максимальную экономию памяти! Недостаток предложенного способа в том, что allocbuf расходуется расточительно. Предположим, произошло его заполнение, а есть еще необработанные строки. Почему бы не «стереть» все строки кроме последних n (interest blocks) и продолжить работу? Для этого просто сдвигаем последние n строк (посимвольно) вначало allocbuf (запоминаем разницу = `diff`), и в массиве указателей для последних n указателей - «сдвигаем» на разницу `diff` их значения.

Что получилось (работает, но экстремально не тестировал):
main.c http://pastebin.com/3V4sw41g
alloc.c http://pastebin.com/MN67M9jX
getline.c http://pastebin.com/sKtCZLJe

Зачем я все это это написал - есть ряд вопросов:

Насколько кривая идея?

Насколько ужасная реализация?

Какие вещи в коде бросаются в глаза / что исправить, чтобы было «нормально»? (я начинающий)

В каких местах код непонятен? Где нужны комментарии?

мне убиться об стену?

p.s. В задании предполагается, что читатель знает только определенный объем знаний (до KnR раздела 5.10 включительно). То есть malloc не советовать, да.



Последнее исправление: cetjs2 (всего исправлений: 1)

5.4 Адресная арифметика. Там alloc разжеван.

int13h ★★★★★
()

п

Язабан

чувак использует malloc (а я ищу решения категории 0)

Кажется, ты не понимаешь, в чем заключается мастерство программиста.

buddhist ★★★★★
()

Но. В задании же сказано про максимальную экономию памяти! Недостаток предложенного способа в том, что allocbuf расходуется расточительно. Предположим, произошло его заполнение, а есть еще необработанные строки. Почему бы не «стереть» все строки кроме последних n (interest blocks) и продолжить работу? Для этого просто сдвигаем последние n строк (посимвольно) вначало allocbuf (запоминаем разницу = `diff`), и в массиве указателей для последних n указателей - «сдвигаем» на разницу `diff` их значения.

тут уже сказали про кольцевой буфер. Делай N строчек в буфере, и когда индекс станет N, ставь его в 0. Новые строчки будут сами затирать старые, и ничего не нужно никуда двигать.

emulek
()
Ответ на: комментарий от buddhist

а что не так-то? Можно поконкретнее претензию? Ну читает товарищ K&R, тебе завидно что-ли?

emulek
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.