Структуры Структура, также как и массив, не является типом данных – это лишь способ адресации данных в памяти, также, как и массивы. Структура может содержать.

Презентация:



Advertisements
Похожие презентации
ПРОГРАММИРОВАНИЕ/ ЯЗЫКИ ПРОГРАММИРОВАНИЯ Лекция 4 Работа с бинарными файлами (весенний семестр 2012 г.) Доцент Кафедры вычислительных систем, к.т.н. Поляков.
Advertisements

Лекция 9 Функции. Массивы-параметры функции Передача массива в функцию Пример: void array_enter(int a[], int size) { int i; for (i = 0; i < size; i++)
Лекция 14 Динамические данные. Виды памяти Существует три вида памяти: статическая, стековая и динамическая. Статическая память выделяется еще до начала.
Основы программирования на Бейсике Массивы. Задание: Найти все 3-хзначные числа, заканчивающихся на 2, 4, 8 и делящихся на 6. Ответ: CLS FOR I=100 TO.
Лабораторная работа 7. Работа с динамической памятью, строками и файлами.
Сложные структуры данных Связные списки. Структуры, ссылающиеся на себя struct node { int x; struct node *next; };
Занятие 4. Типы, определяемые пользователем, и указатели.
Основы информатики Массивы. Указатели. Заикин Олег Сергеевич
Информационные технологии Классы памяти auto static extern register Автоматические переменные создаются при входе в функцию и уничтожаются при.
Распределение памяти. Динамическое выделение памяти.
Записи Комбинированный тип. Запись – структура данных, состоящая из фиксированного числа компонентов, называемых полями записи. Поля записи могут быть.
УКАЗАТЕЛИ. Переменная - это именованная область памяти с заданным типом. [=значение]; int a; //Переменная типа integer с именем a int b=2;// Переменная.
Лекция 2 Функции библиотек языка C. stdio.h Заголовочный файл стандартной библиотеки языка C. Содержит определения констант, объявления функций и типов.
Лабораторная работа 4. Подпрограммы. Задание на лабораторную работу Написать программу, реализующую хранение информации, указанной в вариантах индивидуальных.
Основы информатики Лекция. Массивы. Указатели. Заикин Олег Сергеевич
Файловый тип данных Файл – это область памяти на внешнем носителе, в которой хранится некоторая информация. В языке Паскаль файл представляет собой последовательность.
Практическое занятие 6. Функции. Большинство языков программирования используют понятия функции и процедуры. C++ формально не поддерживает понятие процедуры,
Работа с файлами Сазонов Д.О. ПМиЭММ Часть 2. Тема занятия: Работа с файлами через потоки Для реализации файлового ввода/вывода, необходимо включить в.
Лекция 6 1. Обработка массивов. Объявление одномерного массива Синтаксис: [ ] Пример: int a[10]; Определяет массив a размера 10, т. е. блок из 10 последо-
Функции Функция – именованная последовательность описаний и операторов, выполняющая некоторое действие. Может иметь параметры и возвращать значение. Функция.
Транксрипт:

Структуры

Структура, также как и массив, не является типом данных – это лишь способ адресации данных в памяти, также, как и массивы. Структура может содержать в себе любые типы данных, а также структуры и массивы. Тип данных структуры – указатель на область памяти, которую покрывает структура. Но это особый указатель, и работа с ним производится по-другим правилам, чем если бы мы работали просто с указателем. Эти правила мы рассмотрим далее в этом разделе.

Дадим определение структуры struct { // элементы структуры – любые переменные // и любые типы данных }; Например: struct TPerson { char name[10], surname[20]; unsigned long telephone_nr; char address[30]; }; struct Circle{ int x, y; double radius; };

Давайте подсчитаем размер структур Tperson ( по логике, согласно элементам структуры, как мы ее определили ): 10 * sizeof( char ) + 20 * sizeof( char ) + sizeof( unsigned long ) + 30 * sizeof( char ) = 10*1+20*1+8+30*1 = 68 Но если запросить размер структуры, то заметим интересную вещь – размеры не совпадают. sizeof( struct TPerson ) = 72! Здесь нет никакого подвоха. Действительно, данные, которые мы определили в структуре, занимают 68 байт в памяти, но вся структура занимает 72 байта в памяти. Вывод: структура – это не только данные, которые она адресует! В структуре пристутствует еще один невидимый фактор, который рассмотрим в следующем слайде.

Выравнивание ( alignment ) в памяти В памяти, и, соответственно, в структурах также, данные расположены не сплошь непрерывным потоком байт. Для ускорения доступа к памяти и операций чтения / записи, реализован механизм выравнивания. Данные выравниваются по границе в 4 байта ( зависит от архитектуры ), проще говоря, по границе int. В архитектурах х86 и х86_64 sizeof(int) = 4. К примеру, мы создали структуру struct t{ char a; int b }; сhar занимает 1 байт в памяти, int – 4 байта. В памяти эта структура представлена таким образом байт под букву ( а ), 3 пустых байта ( выравнивание ), 4 байта под число ( b ). В сумме, структура займет 8 байт в памяти, а не 5, как может показаться. Данные займут 5 байт, но вся структура – 8, из-за эффекта выравнивания.

Вернемся к нашим структурам... Tperson: 10 байт выделено в памяти под имя, тоесть базовый адрес Далее записывается фамилия, данные должны быть записаны по 4-х байтной границе, тоесть ближайший адрес – базовый адрес образуются 2 пустых байта между именем и фамилией. Фамилия заканчивается по смещению 32, что есть 4-х байтная граница, и телефон пишется сразу следом за фамилией, без промежутков. Телефон в памяти заканчивается по смещению 40, от базового адреса, поскольку тип unsigned long занимает 8 байт в памяти ( на архитектурах x86(_64) ). Смещение +40 есть 4-х байтная граница, поле адрес пишется сразу следом, адрес заканчивается по смещению 70, но опять же, это не 4-х байтная граница, и в структуру в памяти добавляются 2 лишних байта в конец. Таким образом, мы получаем Sizeof( struct TPerson ) = 72, хотя под сами данные выделено 68 байт. В структуре Circle никаких промежутков между полями данных нет, поскольку мы использовали типы данных int и float, они занимают по 4 и 8 байт в памяти соответственно, все смещения соответствует границе int, потому sizeof( struct Circle ) = 2 * = 16 байт.

Статическое и динамическое выделение памяти под структуры. Статическое выделение памяти – структура создается в стэке. // определили структуру struct TPerson{ … }; // создали 2 структуры employee и manager struct TPerson employee, manager; Указатель на структуру ( объявление ): struct TPerson* employee_ptr; employee_ptr = &employee; // теперь указатель employee_ptr указывает на структуру employee. или одной строкой: struct TPerson* manager_ptr = &manager; // теперь указатель manager_ptr указывает на структуру manager.

Другой способ статического выделения памяти – определение и создание структуры одним выражением. struct TPerson {... } employee, manager, *employee_ptr = &employee, *manager_ptr = manager; Здесь мы определили структуру TPerson, и создали две структуры типа TPerson – employee и manager, а также объявили два указателя на структуру типа TPerson – employee_ptr и manager_ptr и присвоили им соответствующие значения, тоесть выставили указатель employee_ptr на структуру employee, а указатель manager_ptr указывает на структуру manager. Эти указатели имеют тип указатель на структуру TPerson - struct TPerson*.

Динамическое выделение памяти – структура создается в области памяти, называемой куча ( heap ). struct TPerson* employee = ( struct TPerson* ) malloc( sizeof( struct TPerson ) ); if( ! Employee ) { fprintf( stderr, Cannot allocate memory for structure.\n ); return (-1); }... // чтение / запись в структуру free( employee ); // возвращаем выделенную память системе Когда мы выделили память под структуру динамически, мы получаем указатель на эту область памяти. Работа со структурами в этом случае происходит через указатель. Об этом далее.

Работа со структурами ( чтение, запись ) В случае статически выделенной структуры обращение к элементу структуры происходит следующим образом: имя_переменной.элемент структуры Примеры: struct Tperson{ … } employee, manager; struct Circle; Circle circle; // создали эземпляр структуры employee.telephone_nr = 12345; manager.telephone_nr = 54321; printf( employee nr: %lu manager nr: %lu\n, employee.telephone_nr, manager.telephone_nr ); circle.x = 10; circle.y = 20; while( counter ){ circle.x++; circle.y--; }

Обращение к структуре по указателю. Разыменование указателя. Если мы выделили память под структуру динамичеси, то работа с элементами структуры происходит через указатели. Это справедливо и для статически выделенных структур, если создать указатель на такую структуру, то со структурой можно точно так же работать через этот указатель. Обращение к элементу структуры по указателю называется разыменованием указателя ( pointer dereference ).

Struct Circle { int x, y; double radius; } circle, *circle_ptr= &circle; struct Circle* some_pointer; some_pointer = &circle; circle.x = 5; (*circle_ptr).y = 10; circle_ptr->radius = 2; some_pointer->radius++; Оператор соответствует значению по указателю. Т.о circle_ptr->radius то же самое, что (*circle_ptr).radius Printf( Circle x: %d\nCircle y: %d\nCircle radius: %f\n, circle.x, circle_ptr->y, circle_ptr->radius );

В этом слайде будем делать из структуры тип данных Для этого в Си существует ключевое слово typedef ( type define, определить свой тип данных ). Применение простое typedef struct TCircle { int x,y; double radius } Circle, *PCircle; Мы только что создали свой тип данных Circle, и указатель на тип Circle c именем Pcircle. Если указатель не объявлять отдельно в typedef конструкции, то указатель будет выглядеть как обычный указатель на тип – Circle* name. В нашем же случае, мы объявили два типа данных: создали свой тип данных Circle, и еще один тип данных – указатель на Circle cо своим именем PCircle; Circle my_circle; // объявили переменную типа Circle с именем my_circle. Без typedef конструкции эта строка выглядела бы так: struct TCircle my_circle;

typedef struct TCircle{ int x,y; double radius; } Circle, *PCircle; Circle my_circle; PCircle my_circle_ptr = &my_circle; my_circle.x = 5; (*my_circle_ptr).y = 10; my_circle_ptr->radius = 2; Circle* pointer; pointer = &my_circle; pointer->radius += 8; printf( "Circle x: %d\n", my_circle.x ); // 5 printf( "Circle y: %d\n", pointer->y ); // 10 printf( "Circle radius: %.2f\n", my_circle_ptr->radius ); // 10

Создать таблицу базы данных, в которой присутствют поля: имя, фамилия, личный код ( Estonian ID code ), студенческий код. Записать в файл данные по 10 людям и считать их из файла. Произвести сортировку по созданной базе данных по личному коду ( м / ж ) Студентов и студенток в свою очередь отсортировать по возрасту, студентов в возрастающем порядке, студенток в убывающем порядке. Задание #1

Задание #2 Создать таблицу БД как минимум с 5 машинами. Поля: марка, модель, номерной знак, год выпуска, объем двигателя. Также создать таблицу БД владельцев машин. Поля: личный код, имя. Найти самую мощную, самую старую и самую новую машину в базе. У одного владельца может быть несколько машин, но машина может принадлежать только одному владельцу.

Задание #3 Создать 2 таблицы БД. В одной данные студентов ( имя, фамилия, студенческий код ), в другой соответствующие данные по предметам ( название предмета, код предмета, студенческие коды студентов, учащих этот предмет, результат ). Программа создает в результате экзаменационные листы по разным предметам в отдельных файлах, в которых: Название предмета в имени файла или в заголовке Имя и фамилия студента Его студенческий код Результат экзамена Сортировка студентов осуществляется по фамилиям.

Задание #4 Создать таблицу БД дат ( число, месяц, год ) и ввести в нее данные из файла Отсортировать данные по годам в отдельные массивы, и каждый массив отсортировать в возрастающем порядке по признаку ( месяц, число )

Задание #5 Создать таблицу БД певческого хора со следующими полями: имя. Фамилия, личный код, тембр голоса Внести данные по 10 людям, либо вручную, либо из текстового файла, который сделаете сами. Произвести поиск по тембру голоса на 4 категории ( сопрано, альт, тенор и бас ) В каждой из групп отсортировать людей по возрасту: женщин в возрастающем порядке, мужчин в убывающем порядке.

Задание на сортировку строк Создать текстовый файл, с 4-х значными последовательностями букв и цифр ( 23IO, 9010, … ) Считать файл программно и создать на его основе массив строк. Задача состоит в определении, является ли запись: а) bin-числом б) hex-числом вне зависимости от регистра символов. Результат вывести в файл в виде записей ( строка, база – 2 или 16 ) в возрастающем порядке найденные числа. В самом конце вывести строки, которые не принадлежат ни одной из вышеперечисленных категорий. В программе для представления каждой записи использовать структуры.