Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
учебное пособие ОАиП.doc
Скачиваний:
11
Добавлен:
25.04.2019
Размер:
2.63 Mб
Скачать

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

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

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

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

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

#include <stdio.h>

#define DL 30 // max число символов в строке char

struct name{char fio[DL];}; // ФИО объекта

struct inform{ name nm; // поле ссылка на структуру name

char prof[DL]; // поле профессия

int god; // поле год рождения

float okl; // поле оклад

};

void main(void)

{ static inform mas[2]=

{ "Иванов","конструктор",1965,15000.50,

"Петров","оператор",1967,12350.50};

inform *him; // указатель на структуру

printf("адрес mas[0]: %u mas[1]: %u \n",&mas[0],&mas[1]);

him=mas; // him содержит адрес mas[0]

printf("адрес mas[0]: %u mas[1]: %u \n",him,him+1);

printf("him->okl = %.2f (*him).okl = %.2f \n",him- >okl, (*him)okl);

him++; // him содержит адрес следующей стр-ры

printf("him->okl = %.2f (*him).okl = %.2f \n",him- >okl, *him).okl);

++him->okl; // увеличение значения поля okl на 1

printf("him->okl = %.2f (*him).okl = %.2f \n",him- >okl, *him).okl);

}

Синтаксис, используемый при описании указателя на структуру, такой же, как и для других структурированных данных:

struct имя_структуры * имя_указателя;

Таким образом, раз him - указатель на структуру inform, то *him есть сама структура, а (*him).okl - одно из полей структуры.

В выражении (*him).okl используются скобки, так как приоритет операции « . » выше чем « * ». Для упрощения доступа к элементам структуры (избежания ошибок, связанных с учетом приоритета) была введена операция -> (операция косвенного получения элемента). Эта операция имеет следующую форму записи:

имя_указателя -> имя_поля_структуры;

Этот оператор состоит из двух знаков - и >. Операция -> имеет наивысший приоритет, наряду с операциями () [ ] и, таким образом, чтобы перейти к полю okl следующей структуры, необходимо записать:

(++him)->okl; или (him++)->okl;

Рассмотрим еще один пример объявления структуры:

struct

{ char * str;

float f;

} *pr;

Как и выше, *pr->str есть содержимое объекта, на который ссылается str; *pr->str++ передвинет указатель pr->str после считывания объекта, на который он указывал; (*pr->str) ++ увеличит значение объекта, на который ссылается str; *pr ++->str передвинет указатель pr после получения значения, на которое указывает str.

Структуры и функции

В функцию можно наряду со стандартными типами данных передавать и структуры.

struct men // обьявление структуры men

{ char *String;

int Number;

int Marks[10];

};

men sum(men); // первый прототип функции sum

void sum (men*); // второй прототип функции sum

Выше приведены два прототипа функции sum. В первом описывается функция, в которой создается локальная структурная переменная, в которую и производится копирование значения переменной типа структура men. Все изменения выполняемые над полями этой локальной структурной переменной локальны в функции и следовательно, что бы были видны за пределами функции sum должны быть возвращены.

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

При передаче структуры в функцию по значению она может быть передана либо вся структура целиком, либо по полям (компонентам) структуры.

Передача функции компонент структуры. В общем случае, элемент структуры является переменной (массивом) некоторого типа, и может быть передан как ар­гумент функции. Рассмотрим следующую несложную программу, выполняющую суммирование окладов нескольких профессий, и нахождение max из них:

#include <stdio.h>

float summa(float,float *);

struct str

{ char *prof[5]; // профессия

float okl[5],sm; // оклад и сумма

} ok= {"проф1","проф2","3","4","", 1.5,2.06,31.4,3.0,0,0};

void main(void)

{ float max;

int i;

for(i=0;i<5;i++) max=summa(ok.okl[i],&ok.sm);

printf("max значение =%5.2f\n сумма = %5.2f",max,ok.sm);

}

float summa(float i,float *j)

{ static float max=0;

*j+=i; // вычисление суммы

max=(max>i)?max:i; // поиск max значения

return max;

}

Рассматриваемая программа состоит из двух функций: main() и summa(). Функции summa() в качестве параметров передаются один из суммируемых окладов (ok.okl[i]) и адрес элемента структуры, куда помещается сумма (&ok.sm). Функция summa() также возвращает вычисленное максимальное значение оклада.

Передача всей структуры в функцию. В этом случае выполняется передача данных всей структуры в функцию (в стек) со всеми полями, которые в нее входят (массивы, другие структуры и т. д.).

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

#include <stdio.h>

float sr_ball(struct str );

struct str

{ char prof[15];

int oc[4];

};

main()

{ float bl;

struct str s= {"Иванов",5,4,3,5};

bl=sr_ball(s);

printf("средний балл =%5.2f",bl);

return 0;

}

float sr_ball(struct str st)

{

return (st.oc[1]+st.oc[2]+st.oc[3]+st.oc[4])/4;

}