Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОАиП_курсовая_работа_2007.doc
Скачиваний:
5
Добавлен:
24.11.2018
Размер:
174.08 Кб
Скачать

Министерство образования Республики Беларусь

БЕЛОРУССКИЙ НАЦИОНАЛЬНЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ

МЕЖДУНАРОДНЫЙ ИНСТИТУТ ДИСТАНЦИОННОГО ОБРАЗОВАНИЯ

ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ

МЕТОДИЧЕСКИЕ УКАЗАНИЯ

ДЛЯ ВЫПОЛНЕНИЯ КУРСОВОЙ РАБОТЫ

для студентов заочной формы обучения специальности

1-40 01 01 – «Программное обеспечение информационных

технологий»

Минск 2006

УДК 681.3 (075.8)

В методические указания включены задания для выполнения курсовой работы, предназначенной для студентов I курса заочной формы обучения. Задания ориентированы на программную реализацию средствами языка программирования C/C++ любой версии.

Составители: Ю.Б. Попова, И.О. Лапанович

Цель работы

Закрепление практических навыков построения программ на языке C/C++ с использованием структур и объединений.

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

Курсовая работа состоит из программы, созданной на языке программирования Borland C++ под DOS или Microsoft Visual C++ консольное приложение (Win 32 Console Application), и расчетно-пояснительной записки. Структура расчетно-пояснительной записки и образец оформления приведены в Приложениях 1 - 2.

Теоретические сведения

В языке C/C++ реализован специальный тип данных, называемый структурой, который достаточно гибок для представления разнообразных данных и позволяет программисту создавать новые типы. Структуры – это наборы логически связанных переменных различных типов, объединенных под одним именем [10].

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

struct Имя-Этикетка

{

Тип_1 Имя_Переменной_1;

…………………………

Тип_N Имя_Переменной_N;

};

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

struct card {

char *face;

char *suit;

};

Идентификатор card является именем-этикеткой структуры. struct card – тип структуры, face и suit два элемента структуры типа указатель на char.

Элемент структуры не может быть структурой того же типа, в которой он содержится. Однако его можно объявить как указатель на тип структуры, в которую он входит. Структура, содержащая элемент-указатель на структуру того же типа, называется структурой, ссылающейся на себя.

struct card {

char *face;

char *suit;

struct card *cPtr; // элемент структуры, объявляется как указатель

}; // на тип структуры, в которую он входит

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

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

struct Имя-этикетка Имя_Переменной;

struct Имя-этикетка *Имя_Указателя;

Под каждую переменную структуры компилятор выделяет количество байт памяти для хранения всех ее элементов.

struct card a, deck[52]; // объявление переменной a типа struct card,

// и массива deck из 52 элементов типа struct card

struct card *cPtr; // объявление указателя cPtr на тип struct card

Разрешается объявление структурных переменных и указателей на структуру, объединенное с определением структуры:

struct card {

char *face;

char *suit;

} a, deck[52], *cPtr=&a; // указателю структуры cPtr присвоен адрес структуры а

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

Структуры можно инициализировать при объявлении, используя список инициализации:

struct Имя-этикетка Имя_Переменной = {Список_Инициализации};

struct card a={“Тройка”, “Черви”}; // объявление переменной а типа struct card

// и инициализация элемента face значением “Тройка”, а элемента suit значением “Черви”

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

Имя_Переменной_Структуры . Имя_Элемента_Структуры = Выражение;

Имя_Указателя_Структуры -> Имя_Элемента_Структуры = Выражение;

a.face = ”Туз”; // присвоение значения ”Туз” элементу face

cPtr->suit = ”Пики”; // присвоение значения ”Пики” элементу suit

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

Операция элемента структуры обращается к элементу структуры через имя переменной структуры и имеет общий вид:

Имя_Переменной_Структуры . Имя_Элемента_Структуры;

printf(“%s”, a.suit); // доступ к элементу структуры suit через имя

// переменной структуры a

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

Имя_Указателя_Структуры -> Имя_Элемента_Структуры;

printf(“%s”, cPtr->suit); // доступ к элементу структуры suit через указатель

// структуры cPtr, которому присвоен адрес структуры a

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

(*Имя_Указателя_Структуры) . Имя_Элемента_Структуры;

printf(“%s”, (*cPtr).suit); // доступ к элементу структуры suit через указатель

// структуры cPtr, к которому применена операция косвенной

// адресации

Пример. Программа демонстрирует использование операции элемента структуры и операции указателя структуры. Необходимо определить структуру, объявить переменную структуры и указатель структуры, инициализировать элементы структуры и осуществить доступ к элементам структуры [10].

#include<iostream.h>

struct card { // определение структуры типа struct card

char *face;

char *suit;

};

main()

{

struct card a, *cPtr; // объявление переменной структуры a и

// указателя структуры cPtr типа struct card

a.face=”Туз”; // инициализация элемента структуры face

a.suit=”Пики”; // инициализация элемента структуры suit

cPtr=&a; // присвоение указателю структуры cPtr адреса структуры a

cout<<a.face<<a.suit<<endl; // доступ к элементам структуры face и suit

// при помощи операции элемента структуры

cout<<cPtr->face<<cPtr->suit<<endl; // доступ к элементам структуры face и suit

// при помощи операции указателя структуры

cout<<(*cPtr).face<<(*cPtr).suit<<endl; // доступ к элементам структуры face и suit

//при помощи операции элемента структуры

return 0;

}

Результаты работы программы:

Туз Пики

Туз Пики

Туз Пики

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

Массивы структур, как и все прочие массивы, вызываются по ссылке автоматически. Однако, используя структуру, можно осуществить вызов массива по значению. Для вызова массива по значению создается структура, содержащая массив как элемент. Вызывая структуру по значению, мы и массив вызываем по значению.

Пример. Программа демонстрирует использование структуры как параметра функции. Структура передается функции по значению и по ссылке. Необходимо реализовать функции, в которых производится ввод значений элементов структуры [7]:

#include<iostream.h>

#include<stdio.h>

struct person f1(struct person);

void f2(struct person*);

struct person { // определение структуры типа struct person

char name[20];

int tel;

} Student; // объявление переменной структуры Student типа struct person

void main()

{

switch(getchar())

{

case ‘1’: Student=f1(Student); break; // вызов функции f1() по значению

case ‘2’: f2(&Student); break; // вызов функции f2() по ссылке

}

cout<<”Студент:”<<Student.name<<”Телефон:”<<Student.tel<<endl;

}

struct person f1(struct person Student) // определение функции f1(), в

{ // которую передается переменная структуры

cout<<”Введите данные:”;

cin>>Student.name;

cin>>Student.tel;

return Student;

}

void f2(struct person *Student) // определение функции f2(), в

{ // которую передается указатель структуры

cout<<”Введите данные:”;

cin>>(*Student).name;

cin>>(*Student).tel;

}

Результаты работы программы:

1

Введите данные: Петров 221133

Студент: Петров Телефон: 221133

2

Введите данные: Иванов 998877

Студент: Иванов Телефон: 998877

Оператор typedef предоставляет программисту механизм для создания синонимов (или псевдонимов) для ранее определенных типов данных. Создание нового имени с помощью typedef не создает нового типа. typedef просто определяет новое имя для уже существующего типа, которое может использоваться как псевдоним последнего [10].

Общий вид оператора typedef:

typedef Описание_Типа Новое_Имя_Типа;

typedef struct card Card; // определение нового типа с именем Card,

// как синонима типа struct card

Теперь Card можно использовать для объявления переменных типа struct card.

Card deck[52]; // объявление массива deck, состоящего из 52 структур

// Card

// т.е. элементов типа struct card

При использовании оператора typedef для определения типа структуры отпадает необходимость в имени-этикетке:

typedef struct {

char *face;

char *suit;

} Card; // создание типа Card без использования отдельного оператора typedef

Объединение – это составной тип данных, подобный структуре, элементы которого разделяют одну и ту же область памяти. Все элементы, включенные в объединение, в памяти располагаются с одного и того же адреса, перекрывая друг друга. Следовательно, ссылаться в данный момент времени можно только на один элемент и, соответственно, только на один тип данных. Число байтов, используемое для хранения объединения, должно быть достаточным для хранения наибольшего из элементов [10].

Общий вид описания объединения:

union Имя-Этикетка

{

Тип_1 Имя_Переменной_1;

…………………………

Тип_N Имя_Переменной_N;

};

Ключевое слово union определяет объединение. Имя-этикетка именует объединение и используется совместно с ключевым словом union для объявления переменных типа объединения. Переменные, объявленные внутри скобок объединения, являются элементами объединения. Элементы объединения могут быть переменными основных типов данных или составными типами, как массивы или же другие объединения.

union number {

int x;

float y;

};

Идентификатор number является именем-этикеткой объединения, union number – тип объединения, x и y – элементы объединения.

Элемент объединения не может быть объединением того же типа, в котором он содержится. Однако его можно объявить как указатель на тип объединения, в которое он входит. С определением объединения можно использовать оператор typedef.

Объявления переменной объединения и указателя объединения:

union number value; // объявление переменной value типа union number

union number *uPtr; // объявление указателя uPtr на тип union number

Разрешается совместное определение объединения и объявления переменной объединения и указателя объединения:

union number {

int x;

float y;

} value, *uPtr=&value; // присвоение указателю объединения uPtr адреса

// переменной объединения value

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

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

union number value={10}; // допустимая инициализация переменной value, т.к.

// объединение инициализировано целым числом

union number value={1.43}; // ошибочная инициализация переменной объединения

// value

Объединение можно инициализировать и с помощью оператора присваивания:

value.x=100; // присвоение элементу объединения x целого значения 100

Доступ к элементам объединения осуществляется аналогично, как и к элементам структур, при помощи операции элемента структуры и операции указателя структуры.

printf("%d", value.x); // доступ к значению элемента объединения x

// через имя переменной объединения value

printf("%d", uPtr->x); // доступ к значению элемента объединения x

// через указатель объединения uPtr

printf("%f", (*uPtr).y); // доступ к значению элемента объединения y

// через указатель объединения uPtr, к которому

// применена операция косвенной адресации

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

#include<stdio.h>

union number { // определение объединения типа union number

int x;

float y;

};

main()

{ union number value, *uPtr=&value; // объявление переменной объединения value

// и присвоение указателю объединения uPtr адреса переменной объединения value

value.x=100; // инициализация элемента объединения x

printf("Вывод значений int:%d\n float:%f\n", value.x, value.y); // доступ

// к элементам объединения x и y при помощи операции элемента структуры

printf("Вывод значений int:%d\n float:%f\n", (*uPtr).x, (*uPtr).y); // доступ

// к элементам объединения x и y при помощи операции указателя

// структуры, к которому применена операция косвенной адресации

value.y=100.0; // инициализация элемента объединения y

// значение элемента объединения x теряется

printf("Вывод значений int:%d\n float:%f\n", value.x, value.y);

printf("Вывод значений int:%d\n float:%f\n", uPtr->x, uPtr->y); // доступ

// к элементам объединения x и y при помощи операции указателя структуры

return 0;

}

Результаты работы программы:

Вывод значений int: 100

float: 0.000000

Вывод значений int: 100

float: 0.000000

Вывод значений int: 11204

float: 100.000000

Вывод значений int: 11204

float: 100.000000

Вывод программы свидетельствует, что внутреннее представление значения float может значительно отличаться от представления int.

В C/C++ существует возможность задавать число битов для хранения элемента структуры или объединения посредством определения битовых полей. Битовые поля позволяют лучше использовать память, храня данные в минимально требуемом количестве бит. Элементы – битовые поля должны быть объявлены как int или unsigned [10].

Общий вид объявления структуры, содержащей битовые поля:

struct Имя_Этикетка

{

Тип Имя1: Ширина;

……………………..

Тип ИмяN: Ширина;

};

Ширина поля задается целой константой. Ширина поля - это число бит, выделяемых для хранения элемента.

struct bit { // определение структуры, содержащей битовые поля

int a : 4;

int b : 2;

int c : 1;

} bt, *btPtr=&bt;

Данное определение структуры содержит три битовых поля типа int – a, b и c и показывает, что элемент a хранится в четырех битах, элемент b в двух битах, а элемент c в одном бите.

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

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

bt.a; // доступ к битовому полю a с помощью операции элемента

// структуры

btPtr->b; // доступ к битовому полю b с помощью операции указателя

// структуры

(*btPtr).c; // доступ к битовому полю c с помощью операции указателя

// структуры, к которому применена операция косвенной адресации

Битовое поле может быть инициализировано только непосредственной операцией присваивания.

bt.a=1; // инициализация битового поля a значением 1

btPtr->b=125; // инициализация битового поля b значением 125

(*btPtr).c=-100; // инициализация битового поля c значением -100

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

#include<stdio.h>

struct bits{ // определение структуры, содержащей битовые поля

int a:1;

int b:11;

int :15;

int c:10;

} bt,*btPtr=&bt; // объявление переменной структуры bt и присвоение

// указателю структуры btPtr адреса переменной структуры bt

void main()

{

bt.a=1; // инициализация битовых полей

btPtr->b=125;

(*btPtr).c=-100;

printf("a=%d\nb=%d\nc=%d\n", bt.a, btPtr->b, (*btPtr).c); // доступ к битовым полям

}

Результаты работы программы:

a=1

b=125

c=-100

Язык C/C++ имеет еще один определяемый пользователем тип переменных, называемый перечислением. Перечисление объявляется при помощи ключевого слова enum, при этом задается имя переменной и определяется список именованных целых констант, называемый списком перечисления. Эти перечисляемые константы фактически являются символическими константами, значение которых может устанавливаться автоматически. Начальное значение в enum задается равным 0, если не задано иначе, и увеличивается с шагом 1 [10].

Общий вид задания перечисляемого типа:

enum Имя_Переменной {Список_Перечисления};

enum months {JUN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC};

// создание нового типа enum months, в котором идентификаторам

// автоматически присваиваются значения от 0 до 11

Идентификаторы в перечислении должны иметь уникальное имя. Значения каждой перечисляемой константы можно задавать явно путем присвоения значения идентификатору непосредственно в определении. Несколько элементов в списке перечисления могут иметь одно и тоже целое значение:

enum months {JUN=1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC};

// значение первого идентификатора явно устанавливается равным 1,

// значения остальных увеличатся, начиная с 1

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

enum months month; // объявление переменной month типа enum months

month=JUN; // переменной month присваивается

// перечисляемая константа данного типа

Пример. Программа демонстрирует применение перечисляемого типа [10].

#include<stdio.h>

enum months { JUN=1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC};

// задание перечисляемого типа enum months, в котором явно

// задается значение первой перечисляемой константы

main()

{ enum months month; // объявление переменной month типа enum months

char *monthName[]={“”, “January”, ”February”, ”March”, ”April”, ”May”, ”June”, ”July”, ”August”, ”September”, ”October”, ”November”, ”December”};

for(month=JUN; month<=DEC; month++)

printf(“%d%s”, month, monthName[month]);

return 0;}

Результаты работы программы:

1 January

2 February

3 March

4 April

5 May

6 June

7 July

8 August

9 September

10 October

11 November

12 December