Привет, дружелюбное сообщество.
Решаю задачку в 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 не советовать, да.