Язык программирования Си - [54]

Шрифт
Интервал

сообщает, что pp - это указатель на структуру типа struct point. Если pp указывает на структуру point, то *pp - это сама структура, а (*pp).x и (*pp).y - ее элементы. Используя указатель pp, мы могли бы написать

>struct point origin, *pp;

>pp =&origin;

>printf("origin: (%d,%d)\n", (*pp).x, (*pp).y);

Скобки в (*pp).x необходимы, поскольку приоритет оператора . выше, чем приоритет *. Выражение *pp.x будет проинтерпретировано как *(pp.x), что неверно, поскольку pp.x не является указателем.

Указатели на структуры используются весьма часто, поэтому для доступа к ее элементам была придумана еще одна, более короткая форма записи. Если p - указатель на структуру, то

р-›>элемент-структуры

есть ее отдельный элемент. (Оператор -› состоит из знака -, за которым сразу следует знак ›.) Поэтому printf можно переписать в виде

printf("origin: (%d,%d)\n", pp-›х, pp-›y);

Операторы. и -› выполняются слева направо. Таким образом, при наличии объявления

>struct rect r, *rp = &r;

следующие четыре выражения будут эквивалентны:

>r.pt1.x rp-›pt1.x (r.pt1).x (rp-›pt1).x

Операторы доступа к элементам структуры . и -› вместе с операторами вызова функции () и индексации массива [] занимают самое высокое положение в иерархии приоритетов и выполняются раньше любых других операторов. Например, если задано объявление

>struct {int len; char *str;} *p;

то

>++p-›len

увеличит на 1 значение элемента структуры len, а не указатель p, поскольку в этом выражении как бы неявно присутствуют скобки: ++(p-›len). Чтобы изменить порядок выполнения операций, нужны явные скобки. Так, в (++р)-›len, прежде чем взять значение len, программа прирастит указатель p. В (р++)-›len указатель p увеличится после того, как будет взято значение len (в последнем случае скобки не обязательны).

По тем же правилам *p-›str обозначает содержимое объекта, на который указывает str; *p-›str++ прирастит указатель str после получения значения объекта, на который он указывал (как и в выражении *s++), (*p-›str)++ увеличит значение объекта, на который указывает str; *p++-›str увеличит p после получения того, на что указывает str.

6.3 Массивы структур

Рассмотрим программу, определяющую число вхождений каждого ключевого слова в текст Си-программы. Нам нужно уметь хранить ключевые слова в виде массива строк и счетчики ключевых слов в виде массива целых. Один из возможных вариантов - это иметь два параллельных массива:

>char *keyword[NKEYS];

>int keycount[NKEYS];

Однако именно тот факт, что они параллельны, подсказывает нам другую организацию хранения - через массив структур. Каждое ключевое слово можно описать парой характеристик

>char *word;

>int count;

Такие пары составляют массив. Объявление

>struct key {

> char *word;

> int count;

>} keytab[NKEYS];

объявляет структуру типа key и определяет массив keytab, каждый элемент которого является структурой этого типа и которому где-то будет выделена память. Это же можно записать и по-другому:

>struct key {

> char *word;

> int count;

>};

>struct key keytab[NKEYS];

Так как keytab содержит постоянный набор имен, его легче всего сделать внешним массивом и инициализировать один раз в момент определения. Инициализация структур аналогична ранее демонстрировавшимся инициализациям - за определением следует список инициализаторов, заключенный в фигурные скобки:

>struct key {

> char *word;

> int count;

>} keytab[] = {

> "auto", 0,

> "break", 0,

> "case", 0,

> "char", 0,

> "const", 0,

> "continue", 0,

> "default", 0,

> /*…*/

> "unsigned", 0,

> "void", 0,

> "volatile", 0,

> "while", 0

>};

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

>{"auto", 0},

>{"break", 0},

>{"case", 0},

>…

Однако когда инициализаторы - простые константы или строки символов и все они имеются в наличии, во внутренних скобках нет необходимости. Число элементов массива keytab будет вычислено по количеству инициализаторов, поскольку они представлены полностью, а внутри квадратных скобок "[]" ничего не задано.

Программа подсчета ключевых слов начинается с определения keytab. Программа main читает ввод, многократно обращаясь к функции getword и получая на каждом ее вызове очередное слово. Каждое слово ищется в keytab. Для этого используется функция бинарного поиска, которую мы написали в главе 3. Список ключевых слов должен быть упорядочен в алфавитном порядке.

>#include

>#include

>#include


>#define MAXWORD 100


>int getword(char *, int);

>int binsearch(char *, struct key *, int);


>/* подсчет ключевых слов Си */

>main()

>{

> int n;

> char word[MAXWORD];


> while(getword(word, MAXWORD) != EOF)

>  if (isalpha(word[0]))

>   if ((n = binsearch(word, keytab, NKEYS)) >= 0)

>    keytab[n].count++;

> for (n = 0; n < NKEYS; n++)

>  if (keytab[n].count > 0)

>   printf("%4d %s\n", keytab[n].count, keytab[n].word);

> return 0;

>}


>/* binsearch: найти слово в tab[0]...tab[n-1] */

>int binsearch(char *word, struct key tab[], int n)

>{

> int cond;

> int low, high, mid;


> low = 0;

> high = n-1;

> while (low <= high) {

>  mid = (low + high)/2;

>  if ((cond = strcmp(word, tab[mid].word)) < 0)


Еще от автора Деннис М Ритчи
UNIX — универсальная среда программирования

В книге американских авторов — разработчиков операционной системы UNIX — блестяще решена проблема автоматизации деятельности программиста, системной поддержки его творчества, выходящей за рамки языков программирования. Профессионалам открыт богатый "встроенный" арсенал системы UNIX. Многочисленными примерами иллюстрировано использование языка управления заданиями shell.Для программистов-пользователей операционной системы UNIX.


Рекомендуем почитать
Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


MFC и OpenGL

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Симуляция частичной специализации

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Обработка событий в С++

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.