Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

учебное пособие. Часть1. Информатика

.pdf
Скачиваний:
42
Добавлен:
04.06.2015
Размер:
2.87 Mб
Скачать

7. СТРУКТУРЫ

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

марка и тип кузова автомобиля (символьные строки); год выпуска автомобиля (целый тип); объем цилиндра (целый тип).

Объявление структуры: struct < имя типа >{

< сп. полей > };

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

struct automobile {

char mark [10]; type [10];

int date; float ob;

};

Как элементы массива, так и поля структуры можно использовать в качестве отдельных переменных. Чтобы можно было ссылаться на то или иное поле структуры, поля именуются. К каждому полю можно об- ратиться, если указать имя переменной типа struct, затем точку и имя поля.

Используя, описанный выше тип, напишем фрагмент программы: automobile maсhine, a1, *a2 ;

strcpy (machine.mark, "volvo"); maсhine.date = 1996;

strcpy (maсhine.type, "car"); maсhine.ob = 5000;

puts (maсhine.mark);

printf ( "%d\n", maсhine.date); puts ( maсhine.type );

printf ( "%7.2f\n", maсhine.ob ); a1 = machine;

a2 = &a1;

241

a2->ob = 3000;

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

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

Структуры могут быть элементами массива. Приведем описание такого массива:

automobile maсhine[100];

Принимая во внимание предыдущее описание automobile, можно сделать вывод, что описана табл. 6, в которой могут содержаться данные на 100 автомобилей, т. е. каждый элемент массива содержит поля mark, type, date, ob.

 

 

 

Таблица 6

 

лрлорлорлорлорлорлр

 

 

 

 

 

Марка

Дата выпуска

Тип кузова

Объем цилиндров

 

 

 

 

VOLVO S70

1999

Седан

2300

Cadillac STS

1998

Седан

4565

 

 

 

 

......

......

......

......

......

......

......

......

 

 

 

 

BMW320i

2000

Седан

1991

 

 

 

 

Можно записать следующие операторы: strcpy(maсhine [1].mark, ”Cadillac STS”); puts( maсhine[1].mark ); machine[1]=machine[2];

Поле структуры само может быть структурой. В примере структуры automobile введем поле, отвечающее за дату приобретения автомобиля.

struct dat { int den;

char mes[10]; int god;

};

struct automobile {

char mark[15], type[15];

dat date1 ; int date; float ob;

242

};

automobile machine;

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

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

//Пример pr34

#define n 25 // Максимальное количество студентов в группе #define stp "" // Признак завершения ввода исходных данных ввод

// пустой строки struct w {char fam[15];

int oc[3]; float sr; };

int 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 ("Введите оценки \n"); for ( j = 0; j<3; j++ )

{

scanf ( "%d", &wed[i].oc[j] ); 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++;

}

243

int k = i; //Реальное количество студентов в группе; puts ( "Исходная таблица");

puts (" Фамилия Оценки Средний балл"); 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(" Максимальный средний балл у студента %s\n", wed[imax].fam);

return 0;

}

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

//Пример pr35 struct w {

char fam[15]; int oc[3];

float sr; };

int main()

{

w *wed, *ptr, *ptrmax; int i=0, j, n;

float max = 0, s;

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

wed = new w[n]; ptr = wed;

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

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

{

s=0;

cout << "Введите оценки\n"; for( j = 0; j<3; j++ )

{

cin >> ptr->oc[j]; s+ = ptr->oc[j];

}

ptr->sr = s/3.0;

if ( max <ptr->sr )

244

{

max = ptr->sr; ptrmax = ptr;

}

i++;

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

}

int k = i;

puts ( "Исходная таблица");

puts ( " Фамилия Оценки Средний балл"); 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 ( "Максимальный средний балл у студента %s\n", ptrmax->fam);

return 0;

}

245

8. ОБЪЕДИНЕНИЯ

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

union < имя типа >{

< сп. полей >

};

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

union u {

int digit; double big; char letter;

};

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

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

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

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

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

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

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

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

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

246

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

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

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

тах;

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

……

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

}

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

struct w{

int a:9;

int

:7;

int

b:9;

};

 

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

//Пример pr36 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;

247

} u;

void decode ( union bits); int main ()

{

do

{

u.chgetche (); printf (":"); decode ( u );

}

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

}

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" );

}

В приведенном примере в объединении структура, содержащая битовые поля, и символ размещаются в одном и том же месте памяти,

поэтому к одним и тем же ячейкам памяти можно обращаться так, как это требу-

ется в ходе решения задачи.

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

248

1.Какие переменные описываются с помощью ключевого слова char?

2.Чем отличается строка символов от массива символов?

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

4.Как описываются переменные типа структура?

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

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

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

8.Можно ли создать массив структур?

9.Когда можно использовать следующую запись ptr->oc[j] ?

10.Как обратиться к полю структуры?

249

9.ФАЙЛЫ

9.1.Текстовые файлы

Под файлом понимается именованная область внешней памяти или ло- гическое устройство потенциальный источник или приемник информации

[10]. Основное отличие внешней памяти ЭВМ от оперативной памяти воз- можность сохранения информации при отключении ЭВМ. Информация со- храняется в виде файлов, доступ к которым поддерживает операционная сис- тема ЭВМ. Поддержка операционной системы состоит в том, что в ней име- ются средства:

создания файлов; уничтожения файлов;

поиска файлов на внешнем носителе; чтения и записи из файлов и в файлы; открытия файлов; закрытия файлов; позиционирования файлов.

Любой сколько-нибудь развитый язык программирования должен со- держать средства для организации хранения информации на внешних запо- минающих устройствах и доступа к этой информации. Язык С++ не лишен таких возможностей.

Любой файл в С++ имеет три характерные особенности:

у файла есть имя, это дает возможность работать с несколькими фай- лами одновременно;

содержит компоненты одного типа (типом может быть любой тип, кроме файлового);

длина вновь создаваемого файла никак не ограничена при объявле- нии и ограничивается лишь емкостью внешних устройств памяти.

Обращение к файлу производится через указатель на файл, который необходимо описать следующим образом:

FILE *< имя >;

Здесь < имя >идентификатор указателя на файл; FILE имя типа, определенного в файле stdio.h, являющегося структурой, описывающей характеристики файла, суть которых в данном пособии не рассматривается.

Например, можно привести такие описания:

FILE * in, *out, *cur;

Взависимости от способа описания можно выделить текстовые файлы

идвоичные (типизированные). Вид файла определяет способ хранения ин- формации в файле.

250