Создание структуры данных в языке С
Необычный вызов sprintf связан с досадной проблемой, присущей f scant, – если бы не эта проблема, функция fscanf идеально подошла бы для нашего случая. Все дело в том, что вызов fscanf с форматом %s считывает следующее ограниченное пробелами слово из файла в буфер, но без проверки его длины: слишком длинное слово может переполнить входной буфер, что приведет к разрушительным последствиям. Если буфер имеет размер 100 байтов (что гораздо больше того, что ожидаешь встретить в нормальном тексте), мы можем использовать формат %99s (оставляя один байт на заключительный ' \0'), что будет означать для fscanf приказ остановиться после 99 байт. Тогда длинное слово окажется разбитым на части, что некстати, но вполне безопасно.
Мы могли бы написать:
? enum { BUFSIZE = 100 }; ? char fmtrj = "%99s"; /1 BUFSIZE-1./
Однако это потребовало бы двух констант для одного, довольно произвольного значения – размера буфера; обе эти константы пришлось бы поддерживать в непротиворечивом состоянии. Проблему можно решить раз и навсегда, создавая форматную строку динамически – с помощью sprintf, и именно так мы и поступили.
Аргументы build – массив prefix, содержащий предыдущие NPREF введенных слов и указатель FILE. Массив prefix и копия введенного слова передаются в add, которая добавляет новый элемент в хэш-таблицу и обновляет префикс:
Вызов memmove – идиоматический способ удаления из массива. В префиксе элементы с 1 по NPREF-1 сдвигаются вниз на позиции с 0 по NPREF-2, удаляя первое слово и освобождая место для нового слова в конце.
Функция addsuffix добавляет новый суффикс:
Мы разделили процесс обновления состояния на две функции – add просто добавляет суффикс к префиксу, тогда как addsuffix выполняет тесно связанное с реализацией действие – добавляет слово в список суффиксов. Функция add вызывается из build, но addsuffix используется только изнутри add – это та часть кода, которая может быть впоследствии изменена, поэтому лучше выделить ее в отдельную функцию, даже если вызываться она будет лишь из одного места.