Опубликован: 14.12.2010 | Доступ: свободный | Студентов: 3124 / 709 | Оценка: 4.53 / 4.12 | Длительность: 26:28:00
Лекция 14:

Структуры – производные типы данных языка С

< Лекция 13 || Лекция 14: 1234 || Лекция 15 >
Аннотация: В лекции рассматриваются вопросы создания и использования структур в языке программирования С.

Теоретическая часть

Структура – это совокупность нескольких переменных, часто различных типов [13.1]. В структурах совокупность переменных объединяют под одним именем. Переменные, из которых состоит структура, называются ее членами. Члены структуры еще называются элементами или полями [13.2].

С помощью структур удобно размещать в смежных полях связанные между собой элементы информации. В структуре могут быть собраны различные объекты – переменные, массивы, указатели, другие структуры и т.д., которые для удобства работы с ними сгруппированы под одним именем. Если в массиве собраны переменные одного типа (например, float ), то в структуре могут быть переменные различных типов. Объявление структуры создает шаблон, который можно использовать для создания ее объектов (то есть экземпляров этой структуры) [13.2]. При объявлении структуры определяется агрегатный тип данных, но не переменная

Определение структуры состоит из двух шагов:

  1. объявление шаблона структуры (задание нового типа данных, определенного пользователем);
  2. определение переменных типа объявленного шаблона [13.3].

Имена шаблонов должны быть уникальными в пределах их области определения, для того чтобы компилятор мог различать типы шаблонов. Задание шаблона осуществляется с помощью ключевого слова struct, за которым следует имя шаблона структуры и списка элементов, заключенных в фигурные скобки [13.3]. Имена элементов в одном шаблоне также должны быть уникальными. Задание только шаблона не влечет резервирования памяти компилятором. Шаблон предоставляет компилятору необходимую информацию об элементах структурной переменной для резервирования места в оперативной памяти и организации доступа к ней при определении структурной переменной и использовании ее отдельных элементов [13.3].

Рассмотрим шаблон структуры для определения имени и фамилии работника (служащего – employee), его возраста, почасовой оплаты:

struct employee {
char Name [20+1];     // Имя 
char Surname [20+1];  // Фамилия
int age;              // возраст
double hourlysalary;  // почасовой оклад
};

Как видно, шаблон структуры struct employee состоит из символьных массивов типа char, целого числа типа int и числа с плавающей точкой и двойной точности типа double. Описания элементов производится в фигурных скобках, после закрывающей скобки обязательно должна быть точка с запятой.

Определение структуры начинается с ключевого слова struct. Идентификатор employee является именем-этикеткой (tag name), дескриптором. Имя-этикетка employee именует структуру и используется совместно с ключевым словом struct для объявления переменных структурного типа [13.4].

Переменные структуры объявляются так же, как и переменные других типов. На основе вышеприведенного шаблона сделаем несколько объявлений новых структурных переменных:

struct employee new_ employee, * employeePtr, stack[120];

В приведенном объявлении new_employeeпеременная типа struct employee, *employeePtrуказатель на struct employee, emstack[120]массив из 120 элементов типа struct employee.

Объявленные структурные переменные new_employee, *employeePtr, stack[102] могут быть объединены с определением структуры, а именно:

struct employee {
char Name [20+1];       // Имя 
char Surname [20+1];    // Фамилия
int age;                // возраст
double hourlysalary;    // почасовой оклад
}  new_employee, *employeePtr, stack[120];

Имя-этикетка (tag name) не является для структуры обязательным. Если определение структуры не содержит имя-этикетку, то переменные для этой структуры могут быть объявлены только в определении структуры, но не отдельным объявлением [13.1].

При создании структур часто используется ключевое слово typedef (оператор). Оно предоставляет программисту средство для создания синонимов (или псевдонимов) для ранее определенных типов данных. Часто используют typedef для того, чтобы дать укороченное имя структурному типу [13.4]. Например, оператор вида

typedef struct card Card;

определяет новый тип с именем Card как синоним типа struct card.

Ключевое слово typedef может быть использовано в определении типа структуры без имени-этикетки. Например:

typedef  struct  {
char *Name;          // Имя 
char *Surname;       // Фамилия
int age;             // возраст
double hourlysalary; // почасовой оклад
}  Man;

создает тип Man без использования отдельного оператора typedef.

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

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

Man stack[120];

Примечание. Использование typedef помогает сделать программу более переносимой.

Синтаксис инициализации структур аналогичен инициализации массивов. Например, выполним инициализацию структуры:

struct employee {
char Name [20+1];      // Имя 
char Surname [20+1];   // Фамилия
int age;               // возраст
double hourlysalary;   // почасовой оклад
}   new_employee;

Возможный вариант инициализации:

struct employee {
char Name [20];       // Имя 
char Surname [20];    // Фамилия
int age;              // возраст
double hourlysalary;  // почасовой оклад
}   new_employee =  { "Peter", "Smith", 25, 6.78 };

При инициализации структуры структурные элементы (инициализаторы) должны соответствовать заданному типу и отделяться друг от друга запятыми.

Доступ к элементам (компонентам, полям) структуры осуществляется двумя способами:

  1. с помощью оператора связывающей точки (оператора точки) "." при непосредственной работе со структурой;
  2. при использовании указателей на структуры с помощью стрелки "–>".

Общий формат доступа к элементам структуры имеет следующий вид:

имя_переменной_структуры.имя_поля;
имя_указателя_на_структуру–>имя_поля;
(*имя_указателя_на_структуру).имя_поля;

Например, для вышеприведенной инициализации можно изменить почасовой оклад с помощью оператора точки и указателя на структуру:

new_employee.hourlysalary = 21.0;
employeePtr –> hourlysalary = 21.0;

Следует обратить внимание, что new_employee – это имя всего объекта-структуры, а hourlysalary – имя элемента этой структуры. Аналогично и в случае указателя *employeePtr на структуру.

В случае изменения полей структуры следует выделить случай со строками, например:

strcpy(new_employee.name, "Stephen");

При этом должен быть предусмотрен заголовочный файл <string.h>. для функции strcpy().

Когда объявлен массив структур, например, stack[120], то это означает, что создано 120 наборов переменных, каждый из которых организован также, как определено в структуре с дескриптором employee.

Чтобы получить доступ к определенной структуре stack[120], следует указать имя массива с индексом, который пробегает значения от 0 до 119. Например, для пятой структуры можно сделать изменения в почасовом окладе:

stack[4].hourlysalary = 121.5;

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

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

struct X = {
int A[7][8]; 
float b;
char ch;
struct employee Emp2;
} Y;

Тогда инициализация элементов двухмерного массива А может быть такой:

Y.A[2][5] = 99;

Инициализация вложенной структуры может быть такой:

Y.Emp2.hourlysalary = 12.75;

В соответствии со стандартом С89 структуры могут быть вложенными вплоть до 15-го уровня. Стандарт С99 допускает уровень вложенности до 63-го включительно [13.2].

Практическая часть

Пример 1. Напишите программу структурного описания каталога одной книги.

Программный код решения примера:

#include <stdio.h>
#include <conio.h>
#include <string.h>
#define N 40
struct  book  { // Определение структуры
	char title[N+1];    // Название книги
	char author[N+1];   // Автор
	int year;           // Год издания
	int page;           // Количество страниц
	float price;        // Цена в у.е.
} Library;

int main (void)
 {
// Инициализация полей структуры
Library.year = 2007;
Library.page = 496;
Library.price = 12.78F;
strcpy_s(Library.title, N, "Programming in C");
strcpy_s(Library.author, N, "Stephen G. Kochan");

// Вывод на консоль
printf("\n\t Title: %s\n", Library.title);
printf("\t Author: %s\n", Library.author);
printf("\t Year: %d\n", Library.year );
printf("\t Number of pages: %d p.\n", Library.page );
printf("\t Price: %1.2f y.e.\n", Library.price);

	printf("\n\n Press any key: ");
	_getch();
	return 0; 
}

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

strcpy(Library.title, "Programming in C");
strcpy(Library.author, "Stephen G. Kochan");

Результат выполнения программы показан на рис. 13.1.

Пример инициализированных полей структуры

Рис. 13.1. Пример инициализированных полей структуры
< Лекция 13 || Лекция 14: 1234 || Лекция 15 >
Мухаммадюсуф Курбонов
Мухаммадюсуф Курбонов