Создание новых типов
Тип переменной определяет: её размер в памяти, тип данных, которые она может хранить и операции, которые можно производить с этой переменной.
Тип данных является категорией. В языке С++ программист может создать любой тип данных на основе базовых типов. Новые типы данных необходимо создавать для решения конкретных практических задач. Например: реализация работы деканата.
Успех программы часто зависит от удачного выбора способа представления данных. С помощью структур возможно моделировать сложные объекты, возникающие при решении задач. Структуры представляют средство для доступа к записям, которые содержат поля одного или нескольких типов.
Для использования структуры необходимо:
1. установить шаблон для структуры
2. объявить переменную, соответствующую этому шаблону
3. осуществить доступ к компонентам структуры.
Шаблон структуры
Шаблон - это схема, описывающая содержание структуры. Установка структурного шаблона телефонный справочник:
struct sprav {
char fio[20];
long num;
};
Данный шаблон описывает структуру с именем типа структуры sprav, состоящую из двух компонентов: строки fio и целой переменной num типа long. Имя типа структуры sprav необязательно и используется для ссылки на эту структуру. Компоненты структуры - данные любого типа, включая и другие структуры. Имя внутри структуры может быть таким же, как имя объекта вне структуры. Если шаблон описан внутри функции - он доступен только этой функции, если шаблон описан вне функции - он доступен любой функции программы. Установка шаблона не вызывает никаких действий в программе.
Структурные переменные
Объявление структурных переменных приводит к выделению памяти для компонент структуры, куда можно записать данные или откуда можно прочитать их. Для объявления структурных переменных имеются несколько способов.
1. Установить структурный шаблон:
struct sprav {
char fio[20];
long num;
};
Объявить простую переменную, массив структур, указатель на структуру: struct sprav tel1, tel2[5], *tel3;
2. Установить структурный шаблон с помощью макроопределения:
#define SPRAV struct sprav
SPRAV {
char fio[20];
long num;
};
Объявить переменные:
SPRAV sp1, sp2[6], *sp3;
3. Объявить переменные одновременно с установкой шаблона (если на данную структуру вы больше не ссылаетесь):
struct {
char fio[20];
long num;
} tel1, tel2[3], *tel3;
4. Ввести новый тип данных (TEL)-структура определенного вида:
typedef struct {
char fio[20];
long num;
} TEL;
Объявить переменные нового типа:
TEL tel1, tel2[6], *tel3;
Если программа достаточно объемна, представляется более удобным четвертый способ.
Инициализация структуры
Инициализировать можно только внешние или статические структуры.
static struct {
char fio[20];
long num;
} tel[2]={
"Иванов Ф.А.", 456756,
"Петров В.П.", 632345
};
Доступ к компонентам структуры
Доступ к компонентам структуры продемонстрируем с помощью примеров.
Пример 1.
/* Обращение к элементам структуры через имя переменной */
#include <stdio.h>
#include <conio.h>
void main(void)
{
struct{
char fio[20]; /* фамилия */
long num; /* телефон */
} tel1, tel2;
clrscr();
puts("введите фио абонента-");
gets(tel1.fio);
puts("введите его номер-");
scanf("%ld",&tel1.num);
tel2=tel1; /* нельзя так же сравнивать структуры */
puts("Введено:");
printf("Фамилия :%s номер: %ld\n",tel2.fio,tel2.num);
}
Пример 2.
/* Динамическое выделение памяти для структуры */
/* Обращение к элементам структуры через указатель */
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
struct sprav {
char fio[20];
long num;
};
void main(void)
{
struct sprav *tel1, *tel2;
clrscr();
/* Выделение памяти для структуры */
tel1=(struct sprav *)malloc(sizeof(struct sprav));
tel2=(struct sprav *)malloc(sizeof(struct sprav));
puts("введите фио абонента-");
gets(tel1->fio);
puts("введите его номер-");
scanf("%ld",&tel1->num);
*tel2= *tel1;
puts("Введено:");
printf("Фамилия :%s номер: %ld\n",(*tel2).fio,(*tel2).num);
}
Массив структур
Пример 3.
/* Массив структур. Обращение к элементам структуры через */
/* имя элемента массива */
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define SPRAV struct sprav
void main(void)
{
SPRAV{
char fio[20];
long num;
};
SPRAV tel[5]; /* массив структур - 5 элементов */
char fio_tek[20];
int i;
clrscr();
/* ввод данных в массив структур */
for(i=0; i<5; i++)
{
puts("введите фио абонента-");
gets(tel[i].fio);
puts("введите его номер-");
scanf("%ld",&tel[i].num);
getchar();
}
puts("Выбор телефона по фамилии");
gets(fio_tek);
/* поиск структуры по фамилии абонента */
for(i=0; i<5; i++)
if(!strcmp(fio_tek,tel[i].fio)) break;
if(i!=5) /* цикл закончен по break */
printf("номер абонента %s равен %ld\n",fio_tek, \
tel[i].num);
else /* цикл выполнился полностью */
puts("Абонент не найден");
}
Пример 4.
/* Массив структур. Память выделяется динамически. */
/* Обращение к элементам структуры через указатель */
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <alloc.h>
typedef struct{
char fio[20];
long num;
} TEL;
void main(void)
{
TEL *tel;
char fio_tek[20];
int i;
clrscr();
/* Выделение памяти для массива - 3 элемента */
tel=(TEL *)malloc(sizeof(TEL)*3);
for(i=0; i<3; i++)
{
puts("введите фио абонента-");
gets((tel+i)->fio);
puts("введите его номер-");
scanf("%ld",&(tel+i)->num);
getchar();
}
puts("Выбор телефона по фамилии");
gets(fio_tek);
for(i=0; i<5; i++,tel++)
if(!strcmp(fio_tek,tel->fio)) break;
if(i!=5)
printf("номер абонента %s равен %ld\n",fio_tek, \
tel->num);
else
puts("Абонент не найден");
}
Передача структуры в функцию
Непосредственный доступ к компонентам структуры - плохой стиль программирования. Все операции, которые разрешены применительно к структуре, должны быть при этом реализованы в виде отдельных функций. Не все компиляторы языка Си позволяют передавать структуры в функцию по значению, поэтому в примерах передача структуры идет через указатель.
Пример 5.
/* Передача структуры в функцию через указатель на структуру */
/* Определение комплексного числа через структуру и действия */
/* над комплексными числами ( ввод, вывод, вычисление суммы) */
#include <stdio.h>
typedef struct { float a; /* действительная часть */
float b; /* мнимая часть */
} COMPLEX;
void vvod(COMPLEX *,float,float);
void sum(COMPLEX *,COMPLEX *,COMPLEX *);
void out(COMPLEX *);
void main(void)
{
COMPLEX x,y,z;
vvod(&x,2.5,6.7);
vvod(&y,6.89,8.45);
puts("Введены числа:");
out(&x);
out(&y);
sum(&x,&y,&z);
puts("Сумма комплексных чисел равна:");
out(&z);
}
/* Вывод комплексного числа */
void out( COMPLEX *p)
{
printf("(%.2f,%.2f)\n", (*p).a,(*p).b);
return;
}
/* Вычисление суммы двух комплексных чисел */
void sum(COMPLEX *p1,COMPLEX *p2,COMPLEX *p3)
{
(*p3).a=(*p1).a+(*p2).a;
(*p3).b=(*p1).b+(*p2).b;
return;
}
/* Ввод значений для элементов структуры */
void vvod(COMPLEX *p,float a, float b)
{
p->a=a;
p->b=b;
return;
}
Вложенные структуры
Структура, являющаяся компонентом другой структуры, называется вложенной.
Пример 6.
/* Даны четыре точки - центры четырех окружностей. Заполнить структуру окружность, если все окружности проходят через начало координат. */
#include<conio.h>
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
struct POINT {
float x;
float y;
};
struct CIRCLE {
struct POINT point; /* вложенная структура */
double r;
} circle[2], *p;
void main (void)
{
int i,j;
float a,b,c,d;
clrscr();
gotoxy(17,1);
cputs("ВВЕДИТЕ КООРДИНАТЫ ТОЧЕК :\r\n");
for(i=0;i<2;i++)
{
cprintf ("\n\n ВВЕДИТЕ X: ");
cprintf ("X[%d]= ",i+1);
cscanf("%f",&circle[i].point.x);
cprintf ("\n ВВЕДИТЕ Y: ");
cprintf ("Y[%d]= ",i+1);
cscanf ("%f",&circle[i].point.y);
}
p=circle;
gotoxy(17,12);
cputs("РЕЗУЛЬТАТ:\r\n\n");
for(i=0;i<2;i++)
{
a=p->point.x;
b=p->point.y;
c=sqrt(a*a+b*b);
p->r=c;
cprintf("\nРАДИУС : %lf ЦЕНТР (%f,%f)\r\n",p->r,a,b);
p++;
}