Главная » Просмотр файлов » Керниган и Ритчи - Язык программирования Си

Керниган и Ритчи - Язык программирования Си (793773), страница 31

Файл №793773 Керниган и Ритчи - Язык программирования Си (Керниган и Ритчи - Язык программирования Си) 31 страницаКерниган и Ритчи - Язык программирования Си (793773) страница 312019-04-24СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

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

В простых случаях этот синтаксис хорош, однако в сложных ситуациях он вызываетзатруднения, поскольку объявления перенасыщены скобками и их невозможно читать слева направо.Проблему иллюстрирует различие следующих двух объявлений:int *f(); /* f: функция, возвращающая ук-ль на int */int (*pf)(); /* pf: ук-ль на ф-цию, возвращающую int */Приоритет префиксного оператора * ниже, чем приоритет (), поэтому во втором случае скобки необходимы.Хотя на практике по-настоящему сложные объявления встречаются редко, все же важно знать, как ихпонимать, а если потребуется, и как их конструировать.Укажем хороший способ: объявления можно синтезировать, двигаясь небольшими шагами с помощьюtypedef; этот способ рассмотрен в параграфе 6.7.

В настоящем параграфе на примере двух программ,осуществляющих преобразования правильных Си-объявлений в соответствующие им словесные описания иобратно, мы демонстрируем иной способ конструирования объявлений. Словесное описание читается слеванаправо.Первая программа, dcl, — более сложная. Она преобразует Си-объявления в словесные описания так, какпоказано в следующих примерах:char **argvargv: указ, на указ, на charint (*daytab)[13]daytab: указ, на массив[13] из int8Имеется в виду оригинал книги на английском языке. — Примеч. пер.int *(daytab)[13]daytab: массив[13] из указ, на intvoid *comp()comp: функц.

возвр. указ, на voidvoid (*comp)()comp: указ, на функц. возвр. voidchar (*(*x())[])()х: функц. возвр. указ, на массив[] из указ, на функц. возвр. charchar (*(*x[3])())[5]х: массив[3] из указ, на функц. возвр. указ. на массив[5] из charФункция dcl в своей работе использует грамматику, специфицирующую объявитель. Эта грамматика строгоизложена в параграфе 8.5 приложения А, а в упрощенном виде записывается так:объявитель:собственно-объявитель:необязательные * собственно-объявительимя( объявитель )собственно-объявитель ()собственно-объявитель [необязательный размер]Говоря простым языком, объявитель есть собственно-объявитель, перед которым может стоять * (т. е.

однаили несколько звездочек), где собственно-объявитель есть имя, или объявитель в скобках, или собственнообъявитель с последующей парой скобок, или собственно-объявитель с последующей парой квадратныхскобок, внутри которых может быть помещен размер.Эту грамматику можно использовать для грамматического разбора объявлений.

Рассмотрим, например,такой объявитель:(*pfa[])()Имя pfa будет классифицировано как имя и, следовательно, как собственно-объявитель. Затем pfa[]будет распознано как собственно-объявитель, a *pfa[]— как объявитель и, следовательно, (*pfa[])есть собственно-объявитель. Далее, (*pfa[])() есть собственно-объявитель и, таким образом,объявитель. Этот грамматический разбор можно проиллюстрировать деревом разбора, приведенным наследующей странице (где собственно-объявитель обозначен более коротко, а именно собств.-объяв.).Сердцевиной программы обработки объявителя является пара функций dcl и dirdcl, осуществляющихграмматический разбор объявления согласно приведенной грамматике.

Поскольку грамматика определенарекурсивно, эти функции обращаются друг к другу рекурсивно, по мере распознавания отдельных частейобъявления. Метод, примененный в обсуждаемой программе для грамматического разбора, называетсярекурсивным спуском./* dcl: разбор объявителя */void dcl(void){int ns;for (ns = 0; gettoken() == '*'; ) /* подсчет звездочек */ns++;dirdcl();while (ns-- > 0)strcat(out, " указ. на");}/* dirdcl: разбор собственно объявителя */void dlrdcl(void){int type;if (tokentype == '(') { /* ( dcl ) */dcl();if (tokentype != ')')printf( "ошибка: пропущена )\n");} else if (tokentype == NAME) /* имя переменной */strcpy(name, token);elseprintf("ошибка: должно быть name или (dcl)\n");while ((type = gettoken()) == PARENS || type == BRACKETS)if (type == PARENS)strcat(out, " функц.

возвр.");else {strcat(out, " массив");strcat(out, token);strcat(out, " из");}}Приведенные программы служат только иллюстративным целям и не вполне надежны. Что касается dcl, тоее возможности существенно ограничены. Она может работать только с простыми типами вроде char и intи не справляется с типами аргументов в функциях и с квалификаторами вроде const. Лишние пробелы длянее опасны. Она не предпринимает никаких мер по выходу из ошибочной ситуации, и поэтому неправильныеописания также ей противопоказаны. Устранение этих недостатков мы оставляем для упражнений.Ниже приведены глобальные переменные и главная программа main.#include <stdio.h>#include <string.h>#include <ctype.h>#define MAXTOKEN 100enum {NAME, PARENS, BRACKETS };void dcl(void);void dirdcl(void);int gettoken(void);int tokentype; /* тип последней лексемы */char token[MAXTOKEN]; /* текст последней лексемы */char name[MAXTOKEN]; /* имя */char datatype[MAXTOKEN]; /* тип = char, int и т.д.

*/char out[1000]; /* выдаваемый текст */main() /* преобразование объявления в словесное описание */{while (gettoken() i= EOF) { /* 1-я лексема в строке */strcpy(datatype, token); /* это тип данных */out[0] = '\0';dcl(); /* разбор остальной части строкиif (tokentype != '\n' )printf ( "синтаксическая ошибка\п" ) ;printf("%s; %s %s\n", name, out, datatype);}return 0;}Функция gettoken пропускает пробелы и табуляции и затем получает следующую лексему из ввода;"лексема" (token) — это имя, или пара круглых скобок, или пара квадратных скобок (быть может, спомещенным в них числом), или любой другой единичный символ.int gettoken(void) /* возвращает следующую лексему */{int с, getch(void);void ungetch(int);char *p = token;while ((c = getchQ) == ' ' ! ! с == ' \ t ' );if (c == '(') {if ((c = getch()) == ')') {strcpy(token, "()");return tokentype = PARENS;} else {ungetch(c);return tokentype = '(';}} else if (c == '[') {for (*p++ = c; (*p++ = getch()) != ']'; );*p = '\0' ;return tokentype = BRACKETS;} else if (isalpha(c)) {for (*p++ = c; isalnum(c = getch()); )*p++ = c;*p = '\0';ungetch(c);return tokentype = NAME;} elsereturn tokentype = c;}Функции getch и ungetch были рассмотрены в главе 4.Обратное преобразование реализуется легче, особенно если не придавать значения тому, что будутгенерироваться лишние скобки.

Программа undcl превращает фразу вроде "х есть функция, возвращающаяуказатель на массив указателей на функции, возвращающие char", которую мы будем представлять в видех () * [] * () charв объявлениеchar (*(*x())[])()Такой сокращенный входной синтаксис позволяет повторно пользоваться функцией gettoken. Функцияundcl использует те же самые внешние переменные, что и dcl./* undcl : преобразует словесное описание в объявление */main (){int type;char temp[MAXTOKEN];while (gettoken() != EOF) {strcpy(out, token);while ((type = gettoken()) != '\n')if (type == PARENS || type == BRACKETS)strcat(qut, token);else if (type == '*') {sprintf(temp, "(*%s)", out);strcpy(out, temp);} else if (type == NAME) {sprintf(temp, "%s %s", token, out);strcpy(out, temp);} elseprintf ("неверный элемент %s в фразе\n", token);printf("%s\n", out);}return 0;}Упражнение 5.18.

Видоизмените dcl таким образом, чтобы она обрабатывала ошибки во входнойинформации.Упражнение 5.19. Модифицируйте undcl так, чтобы она не генерировала лишних скобок.Упражнение 5.20. Расширьте возможности dcl, чтобы dcl обрабатывала объявления с типами аргументовфункции, квалификаторами вроде const и т.п.6. СтруктурыСтруктура — это одна или несколько переменных (возможно, различных типов), которые для удобства работыс ними сгруппированы под одним именем. (В некоторых языках, в частности в Паскале, структуры называютсязаписями.) Структуры помогают в организации сложных данных (особенно в больших программах), посколькупозволяют группу связанных между собой переменных трактовать не как множество отдельных элементов, акак единое целое.Традиционный пример структуры — строка платежной ведомости.

Она содержит такие сведения о служащем,как его полное имя, адрес, номер карточки социального страхования, зарплата и т. д. Некоторые из этиххарактеристик сами могут быть структурами: например, полное имя состоит из нескольких компонент(фамилии, имени и отчества); аналогично адрес, и даже зарплата. Другой пример (более типичный для Си) —из области графики: точка есть пара координат, прямоугольник есть пара точек и т. д.Главные изменения, внесенные стандартом ANSI в отношении структур, — это введение для них операцииприсваивания. Структуры могут копироваться, над ними могут выполняться операции присваивания, ихможно передавать функциям в качестве аргументов, а функции могут возвращать их в качестве результатов. Вбольшинстве компиляторов уже давно реализованы эти возможности, но теперь они точно оговореныстандартом.

Для автоматических структур и массивов теперь также допускается инициализация.6.1. Основные сведения о структурахСконструируем несколько графических структур. В качестве основного объекта выступает точка скоординатами х и у целого типа.Указанные две компоненты можно поместить в структуру, объявленную, например, следующим образом:struct point {int x;int у;};Объявление структуры начинается с ключевого слова struct и содержит список объявлений, заключенный вфигурные скобки. За словом struct может следовать имя, называемое тегом9 структуры, (point в нашемслучае). Тег дает название структуре данного вида и далее может служить кратким обозначением той частиобъявления, которая заключена в фигурные скобки.Перечисленные в структуре переменные называются элементами (members)10.

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

Тип файла
PDF-файл
Размер
2,25 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

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