45940 (665245), страница 13

Файл №665245 45940 (Язык С) 13 страница45940 (665245) страница 132016-07-31СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 13)

TREEPRINT (P->RIGHT);

\)

\)

Практическое замечание: если дерево становится “несба-

лансированным” из-за того, что слова поступают не в случай-

ном порядке, то время работы программы может расти слишком

быстро. В худшем случае, когда поступающие слова уже упоря-

дочены, настоящая программа осуществляет дорогостоящую ими-

тацию линейного поиска. Существуют различные обобщения дво-

ичного дерева, особенно 2-3 деревья и AVL деревья, которые

не ведут себя так “в худших случаях”, но мы не будем здесь

на них останавливаться.

Прежде чем расстаться с этим примером, уместно сделать

небольшое отступление в связи с вопросом о распределении па-

мяти. Ясно, что в программе желательно иметь только один

распределитель памяти, даже если ему приходится размещать

различные виды объектов. Но если мы хотим использовать один

распределитель памяти для обработки запросов на выделение

памяти для указателей на переменные типа CHAR и для указате-

лей на STRUCT TNODE, то при этом возникают два вопроса. Пер-

вый: как выполнить то существующее на большинстве реальных

машин ограничение, что объекты определенных типов должны

удовлетворять требованиям выравнивания (например, часто це-

лые должны размещаться в четных адресах)? Второй: как орга-

низовать описания, чтобы справиться с тем, что функция ALLOC

должна возвращать различные виды указателей ?

  • 142 -

Вообще говоря, требования выравнивания легко выполнить

за счет выделения некоторого лишнего пространства, просто

обеспечив то, чтобы распределитель памяти всегда возвращал

указатель, удовлетворяющий всем ограничениям выравнивания.

Например, на PDP-11 достаточно, чтобы функция ALLOC всегда

возвращала четный указатель, поскольку в четный адрес можно

поместить любой тип объекта. единственный расход при этом -

лишний символ при запросе на нечетную длину. Аналогичные

действия предпринимаются на других машинах. Таким образом,

реализация ALLOC может не оказаться переносимой, но ее ис-

пользование будет переносимым. Функция ALLOC из главы 5 не

предусматривает никакого определенного выравнивания; в главе

8 мы продемонстрируем, как правильно выполнить эту задачу.

Вопрос описания типа функции ALLOC является мучительным

для любого языка, который серьезно относится к проверке ти-

пов. Лучший способ в языке “C” - объявить, что ALLOC возвра-

щает указатель на переменную типа CHAR, а затем явно преоб-

разовать этот указатель к желаемому типу с помощью операции

перевода типов. Таким образом, если описать P в виде

CHAR *P;

то

(STRUCT TNODE *) P

преобразует его в выражениях в указатель на структуру типа TNODE . Следовательно, функцию TALLOC можно записать в виде:

STRUCT TNODE *TALLOC()

\(

CHAR *ALLOC();

RETURN ((STRUCT TNODE *) ALLOC(SIZEOF(STRUCT TNODE)));

\)

это более чем достаточно для работающих в настоящее время

компиляторов, но это и самый безопасный путь с учетом будую-

щего.

Упражнение 6-4.

Напишите программу, которая читает “C”-программу и печа-

тает в алфавитном порядке каждую группу имен переменных, ко-

торые совпадают в первых семи символах, но отличаются где-то

дальше. (Сделайте так, чтобы 7 было параметром).

Упражнение 6-5.

Напишите программу выдачи перекрестных ссылок, т.е.

Программу, которая печатает список всех слов документа и для

каждого из этих слов печатает список номеров строк, в кото-

рые это слово входит.

Упражнение 6-6.

Напишите программу, которая печатает слова из своего

файла ввода, расположенные в порядке убывания частоты их по-

явления. Перед каждым словом напечатайте число его появле-

ний.

  • 143 -

6.6. Поиск в таблице.

Для иллюстрации дальнейших аспектов использования струк-

тур в этом разделе мы напишем программу, представляющую со-

бой содержимое пакета поиска в таблице. Эта программа явля-

ется типичным представителем подпрограмм управления символь-

ными таблицами макропроцессора или компилятора. Рассмотрим,

например, оператор #DEFINE языка “C”. Когда встречается

строка вида

#DEFINE YES 1

то имя YES и заменяющий текст 1 помещаются в таблицу. Позд-

нее, когда имя YES появляется в операторе вида

INWORD = YES;

Oно должно быть замещено на 1.

Имеются две основные процедуры, которые управляют имена-

ми и заменяющими их текстами. Функция INSTALL(S,T) записыва-

ет имя S и заменяющий текст T в таблицу; здесь S и T просто

символьные строки. Функция LOOKUP(S) ищет имя S в таблице и

возвращает либо указатель того места, где это имя найдено,

либо NULL, если этого имени в таблице не оказалось.

При этом используется поиск по алгоритму хеширования -

поступающее имя преобразуется в маленькое положительное чис-

ло, которое затем используется для индексации массива указа-

телей. Элемент массива указывает на начало цепочных блоков,

описывающих имена, которые имеют это значение хеширования.

Если никакие имена при хешировании не получают этого значе-

ния, то элементом массива будет NULL.

Блоком цепи является структура, содержащая указатели на

соответствующее имя, на заменяющий текст и на следующий блок

в цепи. Нулевой указатель следующего блока служит признаком

конца данной цепи.

STRUCT NLIST \( /* BASIC TABLE ENTRY */

CHAR *NAME;

CHAR *DEF;

STRUCT NLIST NEXT; / NEXT ENTRY IN CHAIN */

\);

Массив указателей это просто

DEFINE HASHSIZE 100

TATIC STRUCT NLIST HASHTAB[HASHSIZE] / POINTER TABLE */

Значение функции хеширования, используемой обеими функ-

циями LOOKUP и INSTALL , получается просто как остаток от

деления суммы символьных значений строки на размер массива.

(Это не самый лучший возможный алгоритм, но его достоинство

состоит в исключительной простоте).

  • 144 -

HASH(S) /* FORM HASH VALUE FOR STRING */

CHAR *S;

\(

INT HASHVAL;

FOR (HASHVAL = 0; *S != '\0'; )

HASHVAL += *S++;

RETURN(HASHVAL % HASHSIZE);

\)

В результате процесса хеширования выдается начальный ин-

декс в массиве HASHTAB ; если данная строка может быть

где-то найдена, то именно в цепи блоков, начало которой ука-

зано там. Поиск осуществляется функцией LOOKUP. Если функция

LOOKUP находит, что данный элемент уже присутствует, то она

возвращает указатель на него; если нет, то она возвращает

NULL.

STRUCT NLIST LOOKUP(S) / LOOK FOR S IN HASHTAB */

CHAR *S;

\(

STRUCT NLIST *NP;

FOR (NP = HASHTAB[HASH(S)]; NP != NULL;NP=NP->NEXT)

IF (STRCMP(S, NP->NAME) == 0)

RETURN(NP); /* FOUND IT */

RETURN(NULL); /* NOT FOUND */

Функция INSTALL использует функцию LOOKUP для определе-

ния, не присутствует ли уже вводимое в данный момент имя;

если это так, то новое определение должно вытеснить старое.

В противном случае создается совершенно новый элемент. Если

по какой-либо причине для нового элемента больше нет места,

то функция INSTALL возвращает NULL.

STRUCT NLIST INSTALL(NAME, DEF) / PUT (NAME, DEF) */

CHAR *NAME, *DEF;

\(

STRUCT NLIST *NP, *LOOKUP();

CHAR *STRSAVE(), *ALLOC();

INT HASHVAL;

IF((NP = LOOKUP(NAME)) == NULL) \( /* NOT FOUND */

NP = (STRUCT NLIST *) ALLOC(SIZEOF(*NP));

IF (NP == NULL)

RETURN(NULL);

IF ((NP->NAME = STRSAVE(NAME)) == NULL)

RETURN(NULL);

HASHVAL = HASH(NP->NAME);

NP->NEXT = HASHTAB[HASHVAL];

HASHTAB[HASHVAL] = NP;

\) ELSE /* ALREADY THERE */

FREE((NP->DEF);/* FREE PREVIOUS DEFINITION */

IF ((NP->DEF = STRSAVE(DEF)) == NULL)

RETURN (NULL);

RETURN(NP);

\)

  • 145 -

Функция STRSAVE просто копирует строку, указанную в ка-

честве аргумента, в место хранения, полученное в результате

обращения к функции ALLOC. Мы уже привели эту функцию в гла-

ве 5. Так как обращение к функции ALLOC и FREE могут проис-

ходить в любом порядке и в связи с проблемой выравнивания,

простой вариант функции ALLOC из главы 5 нам больше не под-

ходит; смотрите главы 7 и 8.

Упражнение 6-7.

Напишите процедуру, которая будет удалять имя и опреде-

ление из таблицы, управляемой функциями LOOKUP и INSTALL.

Упражнение 6-8.

Разработайте простую, основанную на функциях этого раз-

дела, версию процессора для обработки конструкций #DEFINE ,

пригодную для использования с “C”-программами. Вам могут

также оказаться полезными функции GETCHAR и UNGETCH.

6.7. Поля.

Когда вопрос экономии памяти становится очень существен-

ным, то может оказаться необходимым помещать в одно машинное

слово несколько различных объектов; одно из особенно расп-

росраненных употреблений - набор однобитовых признаков в

применениях, подобных символьным таблицам компилятора. внеш-

не обусловленные форматы данных, такие как интерфейсы аппа-

ратных средств также зачастую предполагают возможность полу-

чения слова по частям.

Представьте себе фрагмент компилятора, который работает

с символьной таблицей. С каждым идентификатором программы

связана определенная информация, например, является он или

нет ключевым словом, является ли он или нет внешним и/или

статическим и т.д. Самый компактный способ закодировать та-

кую информацию - поместить набор однобитовых признаков в от-

дельную переменную типа CHAR или INT.

Обычный способ, которым это делается, состоит в опреде-

лении набора “масок”, отвечающих соответствущим битовым по-

зициям, как в

#DEFINE KEYWORD 01

#DEFINE EXTERNAL 02

#DEFINE STATIC 04

(числа должны быть степенями двойки). Тогда обработка битов

сведется к “жонглированию битами” с помощью операций сдвига,

маскирования и дополнения, описанных нами в главе 2.

Некоторые часто встречающиеся идиомы:

FLAGS \!= EXTERNAL \! STATIC;

включает биты EXTERNAL и STATIC в FLAGS, в то время как

FLAGS &= \^(еXTERNAL \! STATIC);

  • 146 -

их выключает, а

IF ((FLAGS & (EXTERNAL \! STATIC)) == 0) ...

истинно, если оба бита выключены.

Хотя этими идиомами легко овладеть, язык “C” в качестве

альтернативы предлагает возможность определения и обработки

полей внутри слова непосредственно, а не посредством побито-

вых логических операций. Поле - это набор смежных битов

внутри одной переменной типа INT. Синтаксис определения и

обработки полей основывается на структурах. Например, сим-

вольную таблицу конструкций #DEFINE, приведенную выше, можно

бы было заменить определением трех полей:

STRUCT \(

UNSIGNED IS_KEYWORD : 1;

UNSIGNED IS_EXTERN : 1;

UNSIGNED IS_STATIC : 1;

\) FLAGS;

Здесь определяется переменная с именем FLAGS, которая содер-

жит три 1-битовых поля. Следующее за двоеточием число задает

ширину поля в битах. Поля описаны как UNSIGNED, чтобы под-

черкнуть, что они действительно будут величинами без знака.

На отдельные поля можно ссылаться, как FLAGS.IS_STATIE,

FLAGS. IS_EXTERN, FLAGS.IS_KEYWORD И т.д., то есть точно так

же, как на другие члены структуры. Поля ведут себя подобно

небольшим целым без знака и могут участвовать в арифметичес-

ких выражениях точно так же, как и другие целые. Таким обра-

зом, предыдущие примеры более естественно переписать так:

FLAGS.IS_EXTERN = FLAGS.IS_STATIC = 1;

для включения битов;

FLAGS.IS_EXTERN = FLAGS.IS_STATIC = 0;

для выключения битов;

IF (FLAGS.IS_EXTERN == 0 &&FLAGS.IS_STATIC == 0)...

для их проверки.

Поле не может перекрывать границу INT; если указанная

ширина такова, что это должно случиться, то поле выравнива-

ется по границе следующего INT. Полям можно не присваивать

имена; неименованные поля (только двоеточие и ширина) ис-

пользуются для заполнения свободного места. Чтобы вынудить

выравнивание на границу следующего INT, можно использовать

специальную ширину 0.

  • 147 -

При работе с полями имеется ряд моментов, на которые

следует обратить внимание. По-видимому наиболее существенным

является то, что отражая природу различных аппаратных сред-

ств, распределение полей на некоторых машинах осуществляется

слева направо, а на некоторых справа налево. Это означает,

что хотя поля очень полезны для работы с внутренне опреде-

ленными структурами данных, при разделении внешне определяе-

мых данных следует тщательно рассматривать вопрос о том, ка-

кой конец поступает первым.

Характеристики

Тип файла
Документ
Размер
2,35 Mb
Материал
Тип материала
Учебное заведение
Неизвестно

Список файлов реферата

Свежие статьи
Популярно сейчас
А знаете ли Вы, что из года в год задания практически не меняются? Математика, преподаваемая в учебных заведениях, никак не менялась минимум 30 лет. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6521
Авторов
на СтудИзбе
302
Средний доход
с одного платного файла
Обучение Подробнее