
Функции форматирования
Для выполнения операций алгоритма форматирования текста в программе BOUND необходимо предусмотреть 6 прикладных функций: getword, chklimit, putword, expander, trailer и gap. Управление ими должна обеспечивать прикладная функция format, которая должна вызываться в основной функции main после инициализации потоков ввода-вывода. Единственным параметром всех функций форматирования должен быть указатель на структуру FORMBUF. Исходный код перечисленных прикладных функций должен предусматривать обращение к библиотечным функциям обработки символьных строк, форматы вызова которых декларируются в заголовочном файле <string.h> системы программирования C.
Прикладная функция getword должна обеспечивать разбиение содержимого входного буфера inbuf структуры FORMBUF на отдельные слова. Считается, что слова во входном буфере разделяют символы пробелов и табуляций, а последнее слово завершает символ перевода строки. Для выделения слов следует использовать библиотечную функцию strtok, которой передается адрес входного буфера inbuf при поиске первого слова или NULL при поиске остальных слов. Адрес очередного слова должен сохраняться в поле word структуры FORMBUF и передаваться через код возврата прикладной функции getword. Когда содержимое входного буфера inbuf исчерпано, прикладная функция getword должна возвращать значение константы NULL.
Прикладная функция chklimit должна осуществлять проверку возможности дополнить рабочий буфер wordbuf очередным словом входного буфера inbuf, которое адресует поле word структуры FORMBUF. Эта проверка основана на том, что суммарная длина слов в рабочем буфере слов не должна превышать требуемый размер строк результирующего типографического текста, который устанавливает значение поля limit структуры FORMBUF. Для вычисления длины рабочего буфера слов workbuf и текущего слова word необходимо использовать библиотечную функцию strlen. Результат проверки определяет знак разности между суммой вычисленных длин и лимитирующим значением поля limit структуры FORMBUF. Любое положительное значение разности означает невозможность дополнить рабочий буфер слов очередным словом. Полученная величина разности должны быть передана через целочисленный код возврата прикладной функции chklimit.
Прикладная функция putword должна применяться для добавления текущего слова, адресованного полем word, в рабочий буфер слов workbuf структуры FORMBUF. После слова необходимо добавить один символ пробела, чтобы обеспечить разделение слов в буфере workbuf. Для добавления слов и пробелов нужно использовать библиотечную функцию strcat. Целочисленный код возврата прикладной функции putword должен идентифицировать текущий размер рабочего буфера слов, для вычисления которого следует применить библиотечную функцию strlen.
Прикладная функция expander предназначена для выравнивания слов, которые накоплены в рабочем буфере слов wordbuf, по ширине, заданной полем limit структуры FORMBUF. Для выполнения этой процедуры нужно предварительно установить текущий размер рабочего буфера слов и количество промежутков между его словами. Текущий размер рабочего буфера слов определяется эффективной длиной поля wordbuf структуры FORMBUF, которая измеряется с помощью библиотечной функции strlen. Количество промежутков однозначно определяет число пробелов в рабочем буфере слов, потому что каждую пару слов в нем по построению разделяет один символ пробела. Число пробелов можно найти, используя циклический вызов библиотечной функции strrchr. При этом целесообразно заменить каждый пробел на символ с нулевым кодом '\0' для удобства последующей обработки завершаемых им слов.
Обладая этой информацией, можно вычислить базовый размер промежутка из пробелов между словами и остаточное число пробелов, которые должны быть равномерно распределены между словами. После этого нужно переписать все слова из рабочего буфера слов в выходной буфер, заданный полем outbuf структуры FORMBUF, дополняя их соответствующим числом промежуточных пробелов между словами. Для копирования слов и формирования промежутков между ними в выходном буфере следует организовать циклический вызов библиотечных функций strcpy, strlen и memset. При этом, копирование каждого очередного слова в выходной буфер должно осуществляться со смещением относительно предыдущего слова, величина которого учитывает размер вычисленного промежутка между словами. После последнего слова в выходной буфер вместо разделительных пробелов нужно записать символ перевода строки '\n' и инициализировать рабочий буфер слов.
Прикладная функция trailer необходима для формирования последней строки любого абзаца, которая должна быть выровнена по левой границе текста. Указанное выравнивание достигается путем копирования всех слов рабочего буфера workbuf в выходной буфер outbuf структуры FORMBUF, например, с помощью библиотечной функции strcpy. После копирования слов необходимо инициализировать рабочий буфер слов и дополнить выходной буфер парой символов перевода строки. Один символ перевода строки должен обозначать конец абзаца, а другой - завершение его последней строки. При пустом рабочем буфере в выходной буфер вместо копирования слов нужно просто записать один символ перевода строки, чтобы отобразить в результирующем типографическом тексте пустую строку исходного текста.
Распознавание пустых строк, которые не содержат других символов, кроме необязательных символов пробелов и/или табуляции, и разделяют абзацы исходного текста, должно осуществляться прикладной функцией gap. Она должна обнаруживать во входном буфере inbuf структуры FORMBUF первый символ, отличный от символов пробела и табуляции, и возвращать его код. Таким образом прикладная функция gap должна возвращать код '\n' для пустой строки входного текста или любое другое значение в противном случае. Пропуск начальных пробелов и табуляций во входном буфере должен быть реализован с помощью библиотечной функции strspn.
Вызов рассмотренных прикладных функций форматирования текста в сочетании с обращением к перегруженным операциям ввода-вывода getbuf и putbuf должна обеспечивать управляющая функция format. Ее исходный код образуют два цикла, итерации которых должны обеспечивать выполнение алгоритма форматирования текста.
Внешний цикл должен обеспечивать получение очередной строки исходного текста во входной буфер inbuf структуры FORMBUF путем вызова прикладной функции getbuf и распознавание пустой строки в конце абзаца текста по коду возврата прикладной функции gap. При обнаружении пустой входной строки должны быть вызваны прикладная функция trailer с целью обработки конца текущего абзаца текста и прикладная функция putbuf для записи его последней строки, полученной во выходном буфере outbuf структуры FORMBUF в результирующий типографический текст. Итерации внешнего цикла должны продолжаться пока при очередном вызове прикладной функции getbuf не будет обнаружен конец входного потока. После завершения внешнего цикла должен быть предусмотрен вызов прикладных функций trailer и putbuf, соответственно, для формирования и записи последней строки текста.
Внутренний цикл должен выполняться для обработки содержимого входного буфера inbuf структуры FORMBUF с целью формирования и записи строк абзаца результирующего типографического текста. В блоке внутреннего цикла управляющей функции format должен быть реализован вызов прикладных функций getword, chklimit, expander, putword и putbuf в соответствии с алгоритмом форматирования абзацев текста. Итерации внутреннего цикла должны продолжаться пока не будут обработаны все слова входного буфера.
Каждая итерация внутреннего цикла должна начинаться обращением к прикладной функции getword, чтобы получить очередное слово из входного буфера inbuf и сохранить его адрес в поле word структуры FORMBUF. Затем необходимо вызвать прикладную функцию chklimit для проверки возможности дополнить очередным словом, полученным по адресу word, рабочий буфер wordbuf структуры FORMBUF. Если ее код возврата больше нуля, то перед добавлением полученного слова следует выполнить процедуру выравнивания слов, накопленных в рабочем буфере слов workbuf, используя прикладную функцию expander, и записать сформированную в выходном буфере outbuf структуры FORMBUF строку в результирующий типографический текст с помощью прикладной функции putbuf. При этом рабочий буфер слов workbuf будет очищен и готов для размещения текущего слова, адресованного полем word структуры FORMBUF. Итерацию внутреннего цикла должен завершать вызов функции putword для добавления текущего слова в рабочий буфер слов workbuf.