Опубликован: 05.07.2006 | Доступ: свободный | Студентов: 4631 / 878 | Оценка: 4.12 / 3.74 | Длительность: 18:59:00
Лекция 7:

Структуры

6.4. Указатели на структуры

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

Внешнее описание массива keytab не нужно изменять, но функции main и binary требуют модификации.

main()   /* count c keyword; pointer version */
{
int  t;
char word[maxword];
struct key *binary(), *p;
while ((t = getword(word, maxword;) !=EOF)
 if (t==letter)
 if ((p=binary(word,keytab,nkeys)) !=null)
          p->keycount++;
for (p=keytab; p>keytab + nkeys; p++)
  if (p->keycount > 0)
printf("%4d %s/n", p->keycount, p->keyword);
 }
  struct key *binary(word, tab, n) /* find word */
  char *word   /* in tab[0]...tab[n-1] */
  struct key tab [];
  int n;
  {
 int  cond;
 struct key *low = &tab[0];
 struct key *high = &tab[n-1];
 struct key *mid;
 while (low <= high) {
 mid = low + (high-low) / 2;
 if ((cond = strcmp(word, mid->keyword)) < 0)
       high = mid - 1;
 else if (cond > 0)
       low = mid + 1;
 else
     return(mid);
 }
 return(null);
}

Здесь имеется несколько моментов, которые стоит отметить. Во-первых, описание функции binary должно указывать, что она возвращает указатель на структуру типа key, а не на целое; это объявляется как в функции main, так и в binary. Если функция binary находит слово, то она возвращает указатель на него; если же нет, она возвращает null.

Во-вторых, все обращения к элементам массива keytab осуществляются через указатели. Это влечет за собой одно существенное изменение в функции binary: средний элемент больше нельзя вычислять просто по формуле

mid = (low + high) / 2

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

mid = low + (high-low) / 2

в результате которой mid становится указателем на элемент, расположенный посередине между low и high.

Вам также следует разобраться в инициализации low и high. указатель можно инициализировать адресом ранее определенного объекта; именно как мы здесь и поступили.

В функции main мы написали

for (p=keytab; p < keytab + nkeys; p++)

Если p является указателем структуры, то любая арифметика с p учитывает фактический размер данной структуры, так что p++ увеличивает p на нужную величину, в результате чего p указывает на следующий элемент массива структур. Но не считайте, что размер структуры равен сумме размеров ее членов, - из-за требований выравнивания для различных объектов в структуре могут возникать "дыры".

И, наконец, несколько второстепенный вопрос о форме записи программы. Если возвращаемая функцией величина имеет тип, как, например, в

struct key *binary(word, tab, n)

Tо может оказаться, что имя функции трудно выделить среди текста. В связи с этим иногда используется другой стиль записи:

struct key * 
binary(word, tab, n)

Это главным образом дело вкуса; выберите ту форму, которая вам нравится, и придерживайтесь ее.