Урок 8.1.2. Операции над структурами

8.1.2. Операции над структурами

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

Название операции Знак операции
выбор элемента через имя (селектор) . (точка)
выбор элемента через указатель (селектор) -> (минус и знак больше)
присваивание =
взятие адреса &

1. Для получения доступа к элементу структурной переменной через ее имя используется символ точка, обозначающий операцию выбор поля структуры. Например, для структурных переменных pos, pos1 и массива pos2, описанных как

struct RECORD
{  int num;                 /* Табельный номер */
char name[20];     /* Имя служащего    */
float wage;              /* Зарплата в месяц */
};

struct RECORD pos, pos1, pos2[5];

pos.num осуществляет доступ к полю num структурной переменной pos, а pos1.num – то же поле, но в составе структурной переменной pos1. Эти элементы можно записывать в любых выражениях Cи, допускающих использование переменных целого типа, так как элемент num структурного шаблона RECORD имеет тип int:

pos.num=67;
if((pos.num < 1330)&&(pos1.num == 1340))...

Аналогично pos.wage и pos1.wage – переменные с плавающей точкой, а pos.name и pos1.name есть констаны-указатели на символьные строки, ибо name – это имя массива.

Для массива структур перед выделением элемента структуры необходимо указать номер элемента массива, для которого выделяется элемент структуры:

pos2[0].num - элемент num из первого элемента массива;
pos2[3].wage - элемент wage из четвертого элемента массива.

Обратите внимание, что индекс массива записывается сразу после имени массива, а не в конце выражения, то есть запись pos2.num[0] – неверна.

В случае вложенных структур операция выделения элемента применяется необходимое число раз. Например, для уже встречавшихся описаний:

struct NAME
{ char fam[10];    //фамилия
   char im[10];      //имя
};

struct RECORD
{ int num;
  struct NAME name;
  float wage;
};

struct RECORD pos, pos1, pos2[5];

выражение pos.name.fam адресует элемент fam структурной переменной name, которая входит в структурную переменную pos.

2. Присваивание. Можно использовать имена структурных переменных в качестве операндов операции присваивания. При этом обе структурные переменные (слева и справа от знака операции присваивания = ) должны быть описаны с помощью одного и того же структурного шаблона. Так, для структурных переменных pos, pos1 и массива pos2, описанных выше, допустимы следующие операторы:

pos=pos1;
pos1=pos2[1];
pos2[2]=pos;

Выполнение подобных присваиваний заключается в копировании значений всех элементов (в том числе и массивов) правой структурной переменной в соответствующие элементы левой структурной переменной, то есть мы обращаемся к структурной переменной как к единой совокупности значений.

3. К структурным переменным, точно так же, как и к обычным переменным, применима операция взятия адреса, обозначаемая знаком & . В качестве примера использования операции взятия адреса рассмотрим все тот же структурный шаблон RECORD и описание структурной переменной w:

struct RECORD
{ int num;
  char name[20];
  float wage;
};

struct RECORD w;

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

struct RECORD *ptrw;

Итак, у нас описаны структурная переменная w типа struct RECORD и указатель ptrw на тип struct RECORD. Теперь к структурной переменной w мы можем применить операцию взятия адреса и присвоить полученный адрес указателю рtrw:

ptrw = &w;

Заметим, что то же самое можно сделать и по-другому. При описании указатель может быть инициализирован адресом любой структурной переменной соответствующего типа, например, в нашем случае так:

struct RECORD *ptrw=&w;

Теперь ptrw ссылается на структурную переменную w. Каким же образом можно использовать указатель ptrw для получения значения элемента структурной переменной w? . Отвечая на этот вопрос, рассмотрим операцию выделения элемента через указатель.

4. Выделение элемента структурной переменной через указатель можно осуществить двумя способами. Первый, наиболее часто применяемый способ, использует знак операции -> (операция -> записывается как минус, за которым следует символ отношения больше ). Действие операции -> заключается в следующем:

Если P есть указатель на структурный тип и P содержит адрес переменной S такого же структурного типа, тогда обращение P-><элемент_структуры> относится к конкретному элементу структурной переменной S.

В условиях предыдущего описания данных и инициализации указателя получим обращения :
ptrw->num к элементу num структурной переменной w;
ptrw->name к элементу name структурной переменной w;
ptrw->wage к элементу wage структурной переменной w.

Обратим внимание на то, что в данном случае для обращения к элементу нельзя записать, например, ptrw.num, так как ptrw не является именем структурной переменной.

Рассмотрим второй способ. Второй способ обращения к элементу структурной переменной через ее указатель заключается в применении уже известной нам операции косвенной адресации. Суть состоит в следующем: поскольку ptrw является указателем на структурную переменную w, то, по определению операции косвенной адресации, использование выражения *ptrw равносильно использованию переменной w: и то и другое реализует обращение к одному и тому же полю памяти. Следовательно, (*ptrw).num представляет собой обращение к элементу num структурной переменной w. Скобки здесь обязательны, так как операция . (точка) имеет приоритет выше чем операция * (звездочка). Таким образом, обращения к полям переменной w можно переписать так:

(*ptrw).num к элементу num структурной переменной w;
(*ptrw).name к элементу name структурной переменной w;
(*ptrw).wage к элементу wage структурной переменной w.

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

5. Обращаться к полям структурной переменной можно и при помощи полей-функций. При этом функции имеют прямой доступ к полям структурной переменной, операцию селектор использовать не надо. Ниже приведен фрагмент программы, в которой поля–функции исполюзуются для печати значений перменной (функция print_rec()) и для изменения значения поля wage (функция wage_raise()).

struct RECORD{ 
int num;        // Табельный номер 
char name[20];  // Имя служащего    
float wage;     // Зарплата в месяц 
 
    void print_rec()
    {
      printf("num=%d\n name=%s\nwage = %f \n\n",num,name,wage);
    }
    void init(int num1, char *name1, float wage1)
    {
      num = num1; strcpy(name,name1); wage = wage1;
    }
    float wage_raise(int d)
    {
      return wage = wage*d;
    }
};
 
//объявление и инициализация стрктурной переменной
RECORD r ={1328, "Ivanov Ivan",2};
//печать значений стрктурной переменной
printf(" %d \n %s \n %f \n\n",r.num,r.name, r.wage);
 
//инициализация структурной переменной
r.init(1329, "Petrov Petr", 20);
//печать значений структурной переменной
r.print_rec();
 
//изменение значения поля структурной переменной
r.wage = r.wage * 5;
 
//изменение значения поля структурной переменной
r.wage_raise(5);
wage_raise(5);  //ошибка, обращаться к полям–функциям 
                //можно только через структурную переменную

 

рассказать друзьям и получить подарок

Оставить комментарий

Ваш email не будет опубликован. Обязательные поля отмечены *

Вы можете использовать это HTMLтеги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Translate Переводчик

Подписка на новости

SmartResponder.ru
Ваш e-mail: *
Ваше имя: *

Хостинг для Wordpress сайтов