русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Определить переменные этого типа для хранения соответствующих данных в памяти.


Дата добавления: 2014-04-05; просмотров: 1218; Нарушение авторских прав


Рассмотрим пример: сведения о студенте содержат следующие данные:

· фамилия - Fam;

· имя - Name;

· год рождения - Year;

· пол - Sex;

· средний балл - Grade.

Представим все эти данные в виде единой структуры. Введем новый тип данных (назовем его t_Student) для описания этой структуры:

 

struct t_Student {

char Fam [20],

Name [16];

short Year;

bool Sex;

float Grade;

};

 

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

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

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

 

t_Student St1, St2; // Определены две переменные типа t_Student

 

Определение переменных можно осуществить одновременно с описанием типа данных структуры:

 

struct t_Student {

char Fam [20],

Name [16];

short Year;

bool Sex;

float Grade;

} St1, St2;

 

Все поля структурных переменных располагаются в непрерывной области памяти одно за другим. Общий объем памяти, занимаемый структурой, равен сумме размеров всех полей структуры. Для определения размера структуры следует использовать инструкцию sizeof (): sizeof (t_Student) или sizeof (St2).

Доступ к полям структур

Для того чтобы записать данные в структурную переменную, необходимо каждому полю структуры присвоить определенное значение. Для этого необходимо научиться получать доступ к полям. Для этого используется оператор “точка”. Например:



 

strcpy ( St1.Fam, “Иванов” );

strcpy ( St1.Name, “Владимир” );

St1.Year = 1995;

St1.Sex = true; // Надо договориться какое значение соответствует значению пола

St1.Grade = 4.67;

 

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

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

 

St2 = St1;

 

Теперь переменная St2 содержит те же данные, что и переменная St1.

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

 

t_Student Gruppa [25];

 

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

 

St1 = Gruppa [10]; // Переменная St1 содержит сведения об 11-ом студенте

 

Доступ к некоторому полю студента внутри массива делается так:

 

double grade = Gruppa[10].Grade; // Переменная grade содержит среднюю оценку 11-ого студента

 

Если некоторое поле структуры представляет собой массив (например, поле Fam – это массив символов), доступ к отдельному элементу этого массива можно выполнить так:

 

St1.Fam[5] = ‘ш’;

 

Или так:

 

Gruppa[10].Fam[5] = ‘ш’;

 

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

Определяем новый тип данных и переменные для двух групп:

 

struct t_Gruppa {

short NumGr; // Номер группы

short Count; // Количество студентов в группе

t_Student Students[25]; // Массив студентов группы

} Gr1372, St1373;

 

Получим данные о некотором студенте из группы Gr1372:

 

St1 = Gr1372.Students[10]; // Переменная St1 содержит сведения об 11-ом студенте

 

А вот его средний балл:

 

grade = Gr1372.Students[10].Grade;

 

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

Указатели на структуры

Любая структурная переменная занимает в памяти определенное положение, характеризующееся конкретным адресом. Для работы с адресами структурных переменных (как и для простых переменных) можно использовать указатели. Указатели на структурные переменные определяются точно так же, как и для обычных переменных:

 

t_Student * p_Stud; // Переменная p_Stud указатель на тип данных t_Student

p_Stud = & St1; // Переменной p_Stud присвоен адрес переменной St1

 

Разыменование указателя (обращение к данным по адресу, хранящемуся в указателе) осуществляется обычным образом:

 

St2 = * p_Stud; // Данные по адресу p_Stud скопированы в переменную St2

 

Через указатели можно работать с отдельными полями структур. Для доступа к полю структуры через указатель используется оператор “стрелка”, а не “точка”:

 

grade = St1.Grade; // Доступ к полю Grade через обычную структурную переменную с помощью оператора “точка”

grade = p_Stud -> Grade; // Доступ к полю Grade через указатель на структурную переменную с помощью оператора “ стрелка”

p_Stud -> Grade = 3.75; // Полю Grade через указатель на структурную переменную присвоено новое значение

Структурные параметры функций

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

Напишем три варианта функции, выводящей на экран данные студента.

 

Вариант 1. Передача данных по значению:

 

void WriteStudent ( t_Student S )

{

cout << setw(14) << "Фамилия: " << S.Fam << endl;

cout << setw(14) << "Имя: " << S.Name << endl;

cout << setw(14) << "Год рождения: " << S.Year << endl;

if ( S.Sex )

cout << setw(14) << "Пол: " << "М\n";

else

cout << setw(14) << "Пол: " << "Ж\n";

cout << setw(14) << "Средний балл: " << S.Grade << endl;

}

 

В этом варианте функции используется передача данных структуры по значению. Вызов этой функции WriteStudent ( St1 ); сопровождается дополнительным расходом памяти для создания локальной переменной S и дополнительными затратами времени на физическое копирование данных из аргумента St1 в параметр S. Учитывая то, что объем структур может быть очень большим, то эти дополнительные затраты вычислительных ресурсов могут быть чрезмерными. Поэтому передачу структур в функции по значению необходимо использовать аккуратно.

 

Вариант 2. Передача данных через указатель:

 

void WriteStudent ( t_Student *S )

{

cout << setw(14) << "Фамилия: " << S -> Fam << endl;

cout << setw(14) << "Имя: " << S -> Name << endl;

cout << setw(14) << "Год рождения: " << S -> Year << endl;

if ( S -> Sex )

cout << setw(14) << "Пол: " << "М\n";

else

cout << setw(14) << "Пол: " << "Ж\n";

cout << setw(14) << "Средний балл: " << S -> Grade << endl;

}

 

Вызов этой функции: WriteStudent ( &St1 );

В этом варианте фактической передачи данных студента в функцию не осуществляется. Дополнительные затраты памяти для создания локальной переменной небольшие – это адрес памяти (4 байта, независимо от размера самой структуры). Вызов такой функции будет осуществляться быстрее, а расход памяти существенно меньше, чем в первом варианте.

Здесь следует обратить внимание на то, что обращение к полям записи должно осуществляться с помощью оператора “стрелка”.

 

Вариант 3. Передача данных по ссылке:

 

void WriteStudent ( t_Student &S )

{

cout << setw(14) << "Фамилия: " << S.Fam << endl;

cout << setw(14) << "Имя: " << S.Name << endl;

cout << setw(14) << "Год рождения: " << S.Year << endl;

if ( S.Sex )

cout << setw(14) << "Пол: " << "М\n";

else

cout << setw(14) << "Пол: " << "Ж\n";

cout << setw(14) << "Средний балл: " << S.Grade << endl;

}

 

Вызов этой функции: WriteStudent ( St1 );

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

Важным здесь является то, что при использовании ссылочных параметров структурных типов доступ к членам структуры осуществляется обычным способом – с помощью оператора “точка”.

 

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

void WriteStudent ( const t_Student &S )

{

………..

}

 

Битовые поля структур

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

 

struct Date

{

unsigned WeekDay : 3; // 0..7 (3 бита)

unsigned MonthDay : 5; // 0..31 (5 бит)

unsigned Month : 4; // 0..12 (4 бита)

unsigned Year : 12; // 0..4048 (12 бит)

} D1;

 

Под переменную D1 в памяти будет отведено всего 4 байта:

 

0 … 2 3 … 7 8 … 11 12 … 23 24 … 31
WeekDay MonthDay Month Year Не используется
3 бита 5 бит 4 бита 12 бит 8 бит

 

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

Для хранения логического значения под битовое поле отводится 1 бит:

 

struct Flags

{

bool b1: 1;

bool b2: 1;

bool b3: 1;

bool b4: 1;

bool b5: 1;

bool b6: 1;

bool b7: 1;

bool b8: 1;

} Fl;

 

Под переменную Fl в памяти будет отведен 1 байт. Таким образом, в одном байте памяти можно разместить 8 логических значений.

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

 

D1.WeekDay = 4;

D1.MontthDay = 25;

D1.Month = 9;

D1.Year = 2004;

 

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

 

10.2. Объединения

Обычные объединения

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

 

union t_num{

int i;

double d;

};

 

Здесь описан новый тип данных с именем t_num, представляющий собой объединение двух членов (полей, элементов), каждый из которых задан типом данных и именем. Члены объединений могут быть любых типов, а их количество – любым.

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

 

t_num A, B; // Определены две переменные А и В

 

Создание переменных модно совместить с описанием объединения:

 

union t_num{

int i;

double d;

} A, B; // Описан тип данных t_num и определены две переменные А и В

 

Обращение к полям объединения осуществляется так же, как и к элементам структуры – с использованием оператора “точка”:

 

A.i = 13;

B.d = 3.14;

cout << A.i + B.d;

 

Если обращение к полям объединения осуществляется через указатель, то необходимо использовать оператор “стрелка”:

 

t_num *p = &A; // Указатель на объединение р инициализирован адресом переменной А

p -> d = 234.33; // Полю d переменной А присвоено новое значение

 

Передача объединений в качестве аргументов функций осуществляется точно так же, как и для структур.

В памяти члены объединения “накрывают” друг друга (располагаются по одному адресу):

d (double – 8 байт)
i (int – 4 байта)
А

 

Если вывести на экран адреса переменной А и полей i и d

 

cout << &A << " " << &A.i << " " << &A.d << endl;

 

то будут выведены три одинаковых адреса.

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

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

 

short Swap ( short I)

{

union t_U {

short i;

char c [2];

} u;

u.i = I;

char ch = u.c [0];

u.c [0] = u.c [1];

u.c [1] = ch;

return u.i;

}

 

cout << Swap (1234) << endl; // На экране -11772

 

Переменная u из этой функции интерпретируется в памяти так:

c[0] (char – 1 байт)
i (short – 2 байта)
u
c[1] (char – 1 байт)

 

Анонимные объединения

Имеется специальный вид объединений – анонимные объединения. Анонимные объединения объявляются без указания имени типа:

 

union {

short i;

char c [2];

};

 

Создавать переменные такого типа нельзя. Анонимные объединения позволяют обращаться к своим полям как к обычным переменным – без применения оператора “точка”. Они просто указывают на то, что переменные, соответствующие их полям, разделяют одну и ту же память.

Функция Swap с использованием анонимного объединения выглядит так:

 

short Swap ( short I)

{

union {

short i;

char c [2];

};

i = I;

char ch = c [0];

c [0] = c [1];

c [1] = ch;

return i;

}

10.3. Перечисления

Перечисления (enumeration) служат для определения пользовательских типов данных, значения которых принадлежат одному из элементов в некотором списке именованных целочисленных констант. Перечисление задается ключевым словом enum:

 

enum тип_Спектр {

красный, оранжевый, желтый, зеленый, голубой, синий, фиолетовый

} Цвет1, Цвет2;

 

Новый пользовательский тип данных тип_Спектр определяет список именованных целочисленных констант (этот список находится внутри фигурных скобок {}). Значениями переменных Цвет1 и Цвет2 могут быть только те значения, имена которых перечислены в определении этого типа данных. Переменной этого типа может быть присвоено любое из перечисленных имен:

 

Цвет1 = желтый;

Цвет2 = синий;

 

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

 

for ( Цвет1 = красный; Цвет1 <= фиолетовый; Цвет1 = тип_Спектр( Цвет1 + 1 ) )

cout << Цвет1 << endl;

 

Этот фрагмент программы выведет на экран целые значения от 0 до 6.

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

 

void WriteColor (тип_Спектр C )

{

switch (C)

{

case красный: cout << "красный"; break;

case оранжевый: cout << "оранжевый"; break;

case желтый: cout << "желтый"; break;

case зеленый: cout << "зеленый"; break;

case голубой: cout << "голубой"; break;

case синий: cout << "синий"; break;

case фиолетовый: cout << "фиолетовый"; break;

default: cout << "Неправильный цвет\n";

}

}

Числовые значения констант перечисления можно изменять, например, так:

 

enum тип_Спектр {

красный, оранжевый, желтый = 10, зеленый, голубой, синий, фиолетовый

};

 

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

 

красный оранжевый желтый зеленый голубой синий фиолетовый

 

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

11. Организация работы с файлами

11.1. Потоки для работы с файлами

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

Для работы с файлами в языке C++ используются потоки трех видов:

· поток ввода (класс ifstream);

· поток вывода (класс ofstream);

· поток ввода-вывода (класс fstream).

Класс ifstream используется для выполнения чтения данных из файлов. Поток ofstream – для записи данных в файлы. Поток fstream – для чтения и записи данных в файлы.

Для использования этих классов потоков необходимо в программу включить заголовочный файл <fstream>.

Для выполнения любых работ с файлом необходимо:

Создать поток одного из классов файловых потоков;

Связать созданный поток с конкретным файлом (открыть конкретный файл для работы);

3) выполнить необходимые действия с файлом (чтение / запись данных);



<== предыдущая лекция | следующая лекция ==>
Определение функции. | Закрыть файл.


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.232 сек.