Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие2013_09_28.doc
Скачиваний:
24
Добавлен:
20.05.2015
Размер:
2.72 Mб
Скачать

13. Структуры

Структура – пользовательский тип данных. Состоит, как и масив, из фиксированного числа компонентов, называемых элементами структуры (полями). Но в отличие от массивов, компоненты (поля) структуры могут быть различных типов и не могут непосредственно индексироваться. Каждое поле имеет уникальное имя, по которому на него ссылаются.

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

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

structanketa//Имя типа

{ charfio[30] ; // фамилия

inttabn; // табельный номер

floattarif; //часовая тарифная сетка

intwork; //отработано часов

floatsum; // зарплата

} ;

Здесь anketaимя нового типа (т. н. дескриптор). При определении шаблона память не выделяется, реальных структур в памяти еще нет. Это имя типа используется в дальнейшем для создания конкретного объекта.

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

На втором шаге определяют переменные структурного типа:

[struct] anketa a0, a1, a2;

Это оператор выделяет место в памяти под три структуры типа anketa и дает им имена a0,a1,a2.

Дескриптор шаблона необходим, если описание структурного типа происходит в одном месте, а определение переменных структурного типа – в другом (т.е. как в приведенном выше примере). Обратите внимание на точку с запятой в конце шаблона. Дело в том, что в некоторых случаях описание структурного типа и определение структурных переменных можно объединить. В этом случае список переменных располагается в конце шаблона, как показано ниже. Здесь дескриптор может отсутствовать.

struct

{ charfio[30] ;

inttabn;

floattarif;

int work ;

float sum ;

} a0, a1, a2;

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

typedef <спецификатор типа> <новое имя> ;

С его помощью можно присвоить новое имя некоторому стандартному типу и изменить программу до неузнаваемости:

typedef float REAL;

REAL tarif, sum;

Определение структурного типа anketa с помощью оператора typedef может выглядеть так:

typedef struct

{ char fio[30];

int tabn ;

REAL tarif;

int work;

REAL sum;

} anketa;

И тогда структурные переменные a0, a1, a2 определяются привычным способом:

anketaa0,a1,a2;

Начальная инициализация.

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

anketa a0={“Иванов А. П.”, 2345, 21.5, 100};

Доступ к полям структуры.

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

a1.sum = a1.tarif * a1.work;

strcpy (a1.fio, “Леонов Л.М.”);

cin.getline (a1.fio, 30);

Структуры могут быть вложенными, и тогда уточненное (составное) имя содержит цепочку имен, разделяемых точками – от старшей структуры до имени поля.

К структурам одного типа как единому целому применима только операция присваивания, например

a2=a1;

Остальные действия со структурами (ввод-вывод, сравнение и др.) осуществляются поэлементно (над отдельными полями) . При вводе элементы структуры вводятся последовательно по одному. Заполнять их можно в любом порядке.

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

Одиночные структуры используются редко при обработке данных. Наиболее часто они выступают как компоненты массивов и записи файлов. При объявлении массива структур предварительно надо объявить саму структуру как новый тип данных.

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

anketa a[5];

a[0].tarif=15.75;

gets(a[0].fio);

scanf(“%d %f”, &a[0].work, &a[0].tarif);

Рассмотрим следующий пример.

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

#define LIM 30 // предельное число служащих

#include <string.h>

#include<conio.h>

#include<stdio.h>

#include <iostream>

using namespace std;

struct anketa //anketa - имя нового типа!

{ char fio[30];

int tabn;

float tarif;

int work;

float sum;

};

void main()

{ system("chcp 1251");

anketa vedom[LIM]; //массив структур типа anketa

int k=0,i;

cout<<"Введи до "<<LIM<<" фамилий"<<'\n';

cout<<"Для прекращения - Enter в начале строки"<<'\n';

cout<<"Фамилия "<<k+1<<" -го служащего";

while((gets(vedom[k].fio)!=NULL)&&

(vedom[k].fio[0])!='\0' && k<LIM )

{

cout<<"табельн номер - "<<vedom[k].fio; cin>>vedom[k].tabn;

cout<<"часовой тариф - "<<vedom[k].fio; cin>>vedom[k].tarif;

cout<<"отраб часов - "<<vedom[k].fio; cin>>vedom[k].work;

// начисление зарплаты

vedom[k].sum = vedom[k].tarif*vedom[k].work;

k++;

//ВНИМАНИЕ!!!

fflush(stdin); //очистить входной поток!

// Иначе 2-ю фамилию уже не введем, gets() определяет NULL

if(k<LIM)

cout<<"Фамилия "<<k+1<<" -го служащего ";

}

cout<<"\n\n\n\t\tВедомость на выплату зарплаты\n\n";

for(i=0; i<k; i++)

printf("\n%20s %10.2f %8d %10.2f",

vedom[i].fio,vedom[i].tarif,vedom[i].work, vedom[i].sum );

getch();

}