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

Общие сведения

Структуры - это тип данных, состоящий из фиксированного числа ком­понентов, называемых полями. Очень часто возникает необходимость опи­сать характеристики некоторого объекта, представляемого и обрабатываемо­го в программе: Таким объектом может быть человек, автомобиль, журнал и т.д. В отличие от массива компоненты (поля) структуры могут быть различ­ного типа. Для описания объекта "автомобиль" могут потребоваться, напри­мер, следующие характеристики:

марка и тип кузова автомобиля (символьные строки);

год выпуска автомобиля (целый тип);

объем цилиндра (целый тип).

Чтобы можно было ссылаться на то или иное поле структуры, поля именуются.

Объявление структуры:

struct <имя типа>

{

<cn. nолей>

};

здеcь <имя типа> - правильный идентификатор;

<cn. nолей> - список полей, представляющий собой последова­тельность разделов, между которыми ставится точка с запятой. Например: struct autom {

char mark[10], type [10];

int date;

float ob;

}

Как элементы массива, так и поля структуры можно использовать в ка­честве отдельных переменных. К каждому компоненту можно обратиться, если указатель имя переменной типа struct, затем точку и имя поля. Используя, описанный выше тип, напишем фрагмент программы:

a

98

utom machine, a1, *a2;

strcpy(machine.mark, "volvo");

machine.date = 1996;

strcpy(machine.type, "car");

machine.ob = 5000;

puts(machine. mark);

printf("%d\n",machine.date);

puts(machine.type);

printf("%7.2f\n",machine.ob);

a1=machine; a2=&a1;

a2>ob=3000;

}

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

autom mach1, mach2;

Это означает, что переменная mach1 содержит поля mark, typе, date, ob, точно такие же поля содержит и переменная mach2. Возможен оператор присваивания:

mach1 =mach2;

Для переменных одного типа можно проверить выполнение отношения равенства или неравенства. Как и в случае массивов, допустимы операции сравнения == и !=.

Так как на тип элементов массива не накладывается ограничений, то можно создавать массив, компонентами которого являются структуры, объ­являть указатели на структуры.

Приведем описание такого массива:

autom machine[100]

Принимая во внимание предыдущее описание autom, можно сделать вывод, что описана таблица 6, в которой могут содержаться данные на 100 автомобилей.

Табл.7

Далее можно записать следующие операторы: для обращения к первому элементу массива

99

machine [1].mark:=’Cadillac STS’;

для чтения первого элемента:

read (machine [1].mark);

Как и в массиве, значения переменных и констант типа struct можно присваивать другим переменным такого же типа:

machine[1] = machine[2];

Поле структуры само может быть структурой. В примере структуры autom введем дату приобретения автомобиля.

struct dat { int den;

char mes[10];

int god;

} ;

struct autom {

char mark[15], type[15];

dat date1;

int date;

float ob;

} ;

autom machine;

При обращении к полю god необходимо продолжать уточнения:

machine.date1.god: = 1949;

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

// Пример pr31

#include <stdio.h>

#include <string.h>

#define n 25

#define stp ""

struct w { char fam[15];

int os[3];

float sr;

} ;

void main()

{ w wed[n];

int i=0, j, imax;

float max = 0, s;

printf ("Введите фамилию \n");

while(strcmp(gets(wed[i].fam),stp)!=0 && i<n)

{ s=0;

printf("Введите ocenki \n");

for(j=0; j<3; j++)

{ scanf("%d",&wed[i].oc[j]);

100

s+=wed[i].oc[j];

}

wed[i].sr=s/3.0;

if(max<wed[i].sr)

{max=wed[i].sr;

imax=i;

}

while(getchar()!=’\n’);

if(i<n) printf("Введите следующую фамилию"); printf("\n");

i++;

}

int k=i; // Реальное количество студентов в группе

puts("icxod tabl");

puts(" fam ocenki sred bal ");

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

{printf("%15s",wed[i].fam);

for(j=0; j<3; j++)

printf("%5d",wed[i].oc[j]);

printf("%5.2f\n",wed[i].sr);

}

printf("max=%s\n",wed[imax].fam);

}

Эту же программу составим с использованием указателей на структуру // Пример рr32

#include <stdio.h>

#include<string.h> #include <iostream.h>

struct w {char fam[15];

int oc[3];

float sr;

} ;

void main()

{ w *wed,*ptr,*ptrmax;

int i=0,j,n;

float max=0,s;

cout<<"Введите число студентов\n";

cin>>n;

wed=new w[n];

ptr=wed;

cout<<"Введите фамилию \n";

while(gets(ptr->fam)!=NULL && i<n)

{

s=0;

101

cout<<"Введите ocenki \n";

for(j=0; j<3; j++)

{ cin>>ptr->oc[j];

s+=ptr->oc[j];

}

ptr->sr=s/3.0;

if(max<ptr->sr)

{max=ptr->sr

ptrmax=ptr;

}

i++;

if(i<n) cout<<"Введите следующую фамилию \n";

ptr++;

}

int k=i;

puts("icxod tabl");

puts("fam ocenki sred bal");

for(i=0, ptr=wed; i<k; i++,ptr++)

{

printf("%15s",ptr->fam);

for(j=0; j<3; j++)

printf("%5d",ptr->oc[j]);

printf("%9.2f\n",ptr->sr);

}

printf("max=%s\n", ptrmax->fam);

}

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

#include <string.h>

#define n5

#define stp""

struct w {char fam[15];

char gor[15];

char ul[15]; ; , int dom,kw;} ;

void main() Tv' '

{ int k; ' '

struct w wed[n]; *'

int proc (int a,struct w wed[], int& , int k);

int i=0,j,f;

p

102

rintf("введите фамилию \n");

while(strcmp(gets(wed[i].fam),stp)!=0 && i<n)

{printf("введите город \n");

gets(wed[i].gor);

printf("введите улицу \n");

gets(wed[i].ul);

printf("введите номер дома и квартиры \n");

scanf("%d%d", &wed[i].dom, &wed[i].kw);

while(getchar()!=’\n’);

if(i<n) printf("введите следующую фамилию"); printf("\n");

i++;

}

k=i;

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

printf("%s%s%s%d%d

\n",wed[j].fam,wed[j].gor,wed[j].ul,wed[j].dom,wed[j].kw);

for(j=0; j<k-1; j++)

{ f=pros(j,wed,i,k);

if(f)

{

puts("По одинаковому адресу проживают:");

printf("%s",wed[j].fam);

printf(" u %s",wed[i].fam); break;

}

}

if(!f) puts("Таких нет!");

}

int pros (int a,struct w wed[],int &i,int k)

{

for (i=a+1; i<k; i++)

if (strcmp(wed[a].gor,wed[i].gor)!=0)

if (strcmp(wed[a].ul,wed[i].ul)==0)

if (wed[a].dom==wed[i].dom)

if (wed[a].kw==wed[i].kw)

{return 1; break;

}

return 0;

}

Объединения

Со структурами в "близком родстве" находятся объединения, которые описываются с помощью ключевого слова union [8]. Синтаксис описания объединения отличается от описания структур только ключевым словом:

u

103

nion <имя типа>

{

<сп. полей>

} ;

здесь <имя типа> - правильный идентификатор;

<сп. полей> - список полей, представляющий собой последова­тельность разделов, между которыми ставится точка с запятой. Например:

u {

int digit;

double big;

char letter;

} ;

Как и в случае со структурами, это описание не задает какую-либо пере­менную, а задает только шаблон объединения. Можно объявить переменную:

union и f1, *ptr, m[10];

В отличие от структуры для переменной типа union места в памяти вы­деляется ровно столько, сколько надо элементу объединения, имеющему наибольший размер в байтах. В приведенном выше примере под переменную f1 будет выделено 8 байтов памяти. Bсе поля объединения будут иметь один и тот же начальный адрес. Таким образом, объединения позволяют запоми­нать данные различных типов в одном и том же месте памяти:

f1.digit=43; // 43 записывается в f1; используется 2 байта;

f1.big=7.0; // 43 стирается, 7.0 записывается; используется 8байт;

f1.letter='w'; // 7.0 стирается, 'w' записывается; используется 1 байт;

В каждый момент времени запоминается только одно значение; нельзя записать два значения одновременно, даже если для этого достаточно памя­ти.

Битовые поля структур и объединений

В отличие от других языков программирования язык Си обеспечивает доступ к одному или нескольким битам в байте или слове. Внутри структур и объединений могут в качестве их компонентов использоваться битовые по­ля. Каждое битовое поле представляет целое или беззнаковое целое значение, занимающее в памяти фиксированное число битов (от 1 до 16). Битовые поля могут быть только элементами структур, объединений классов, т. е. они не могут быть самостоятельными объектами программ. Битовые поля не имеют адресов, нет указателей и ссылок на битовые поля. Они не могут объединяться в массивы. Назначение битовых полей - обеспечить удобный доступ к от­дельным битам данных. Чаще всего битовые поля используют при работе с флажками, которые могут принимать только два значения, что позволяет экономить память.

С

104

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

struct <имя_структуры>

{

<тип поля> имя поля1: длина в битах;

<тип поля> имя поля2: длина в битах;

……..

<тип поля> имя поляN: длина в битах;

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

struct w {

int a:9;

int :7;

int b:9;

} ;

Программа, приведенная ниже, выдает на экран двоичный код ASCII

символа, вводимого с клавиатуры.

#include <stdio.h>

#include <conio.h>

struct byte {

int b1:1;

int b2:1;

int b3:1;

int b4:1;

int b5:1;

int b6:1;

int b7:1;

int b8:1;

} ;

union bits {

char ch;

struct byte b;

} u;

void decode(union bits);

main()

{do

{ u.ch=getche();

printf(":");

decode(u);

}

while (u.ch!= 'q');

return 0;

}

105

void decode(union bits x)

{

if (x.b.b8) printf("1");

else printf("0");

if (x.b.b7) printf("1");

else printf("0");

if (x.b.b6) printf("1");

else printf("0");

if (x.b.b5) printf("1");

else printf("0");

if (x.b.b4) printf("1");

else printf("0");

if (x.b.b3) printf("1");

else printf("0");

if (x.b.b2) printf("1");

else printf("0");

if (x.b.b1) printf("1");

else printf("0");

printf("\n");

}

Контрольные вопросы

1. Как описываются структуры?

2. Чем структуры отличаются от объединения?

3. Для чего используются битовые поля?

4. Как обратиться к структуре по указателю?

Варианты заданий

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

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

2. Ведомость, упорядоченную в алфавитном порядке.

3. Напечатать название предмета, по которому получено наибольшее ко­личество "двоек", и фамилии студентов, получивших по этому предмету "двойку".

4

106

. Напечатать название предмета, по которому получено наибольшее ко­личество "пятерок", и фамилии студентов, получивших по этому предмету "двойку".

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

5. Напечатать по алфавиту фамилии лиц, живущих в Хабаровске.

6. Напечатать фамилии и адреса лиц, живущих в Хабаровске по улице Тихоокеанской, и расположить список в алфавитном порядке.

7. Напечатать список лиц, работающих (учащихся) в ХГТУ по алфавиту.

На основе таблицы, содержащей следующую информацию о каждом из 20 студентов некоторого вуза: <фамилия>, <имя>, <отчество>, <пол>, <возраст>, <курс> причем в фамилии, имени и отчестве - не более 12 букв, пол указывается буквами М и Ж, возраст - целое от 16 до 35, курс - целое от 1 до 5. Написать программу, которая вводит эту информацию и печатает следующие данные:

8. Номер курса, на котором наибольший процент мужчин.

9. Список студенток в алфавитном порядке.

10. Самое распространенное женское имя.

11. Список студенток первого курса в алфавитном порядке.

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

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

13. Напечатать результаты команды, набравшей наибольшее количество пропущенных мячей.

14. Напечатать таблицу, расположив команды в порядке убывания пропущенных мячей.

15. Напечатать результаты команд, набравших одинаковое количество очков.

16. Вывести таблицу в порядке убывания числа поражений.

На основе таблицы, включающей названия 10 моделей автомобиля, их технические характеристики (мощность, наибольшая скорость, масса, вид ку­зова, рабочий объем цилиндра), цену:

17. Напечатать таблицу, расположение модели в порядке убывания

мощности.

18. Напечатать таблицу в порядке убывания стоимости моделей.

19. Вывести на печать технические характеристики автомобиля с наи­большей скоростью.

20. Напечатать таблицу, расположив модели в порядке возрастания рабочего объема цилиндра.

Н

107

а основе таблицы, содержащей данные об услугах, оказываемых ком­пьютерной фирмой: название услуги, её стоимость, налог на добавленную стоимость, срок выполнения:

21. Составить итоговую таблицу, подсчитав общую стоимость для каж­дой услуги и расположив их в порядке возрастания общей стоимости.

22. Напечатать название самой дорогой услуги;

23. Напечатать таблицу, расположив названия услуг, в порядке­ убывания их стоимости.

24. Напечатать названия услуг, имеющих одинаковую стоимость.

25. Вывести таблицу в порядке убывания сроков выполнения услуг.

108

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]