Скачать презентацию
Идет загрузка презентации. Пожалуйста, подождите
Презентация была опубликована 10 лет назад пользователемТимур Свирин
1 Структуры
2 Структура, также как и массив, не является типом данных – это лишь способ адресации данных в памяти, также, как и массивы. Структура может содержать в себе любые типы данных, а также структуры и массивы. Тип данных структуры – указатель на область памяти, которую покрывает структура. Но это особый указатель, и работа с ним производится по-другим правилам, чем если бы мы работали просто с указателем. Эти правила мы рассмотрим далее в этом разделе.
3 Дадим определение структуры struct { // элементы структуры – любые переменные // и любые типы данных }; Например: struct TPerson { char name[10], surname[20]; unsigned long telephone_nr; char address[30]; }; struct Circle{ int x, y; double radius; };
4 Давайте подсчитаем размер структур 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 байта в памяти. Вывод: структура – это не только данные, которые она адресует! В структуре пристутствует еще один невидимый фактор, который рассмотрим в следующем слайде.
5 Выравнивание ( 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, из-за эффекта выравнивания.
6 Вернемся к нашим структурам... 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 байт.
7 Статическое и динамическое выделение памяти под структуры. Статическое выделение памяти – структура создается в стэке. // определили структуру 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.
8 Другой способ статического выделения памяти – определение и создание структуры одним выражением. 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*.
9 Динамическое выделение памяти – структура создается в области памяти, называемой куча ( heap ). struct TPerson* employee = ( struct TPerson* ) malloc( sizeof( struct TPerson ) ); if( ! Employee ) { fprintf( stderr, Cannot allocate memory for structure.\n ); return (-1); }... // чтение / запись в структуру free( employee ); // возвращаем выделенную память системе Когда мы выделили память под структуру динамически, мы получаем указатель на эту область памяти. Работа со структурами в этом случае происходит через указатель. Об этом далее.
10 Работа со структурами ( чтение, запись ) В случае статически выделенной структуры обращение к элементу структуры происходит следующим образом: имя_переменной.элемент структуры Примеры: 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--; }
11 Обращение к структуре по указателю. Разыменование указателя. Если мы выделили память под структуру динамичеси, то работа с элементами структуры происходит через указатели. Это справедливо и для статически выделенных структур, если создать указатель на такую структуру, то со структурой можно точно так же работать через этот указатель. Обращение к элементу структуры по указателю называется разыменованием указателя ( pointer dereference ).
12 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 );
13 В этом слайде будем делать из структуры тип данных Для этого в Си существует ключевое слово 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;
14 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 y ); // 10 printf( "Circle radius: %.2f\n", my_circle_ptr->radius ); // 10">
15 Создать таблицу базы данных, в которой присутствют поля: имя, фамилия, личный код ( Estonian ID code ), студенческий код. Записать в файл данные по 10 людям и считать их из файла. Произвести сортировку по созданной базе данных по личному коду ( м / ж ) Студентов и студенток в свою очередь отсортировать по возрасту, студентов в возрастающем порядке, студенток в убывающем порядке. Задание #1
16 Задание #2 Создать таблицу БД как минимум с 5 машинами. Поля: марка, модель, номерной знак, год выпуска, объем двигателя. Также создать таблицу БД владельцев машин. Поля: личный код, имя. Найти самую мощную, самую старую и самую новую машину в базе. У одного владельца может быть несколько машин, но машина может принадлежать только одному владельцу.
17 Задание #3 Создать 2 таблицы БД. В одной данные студентов ( имя, фамилия, студенческий код ), в другой соответствующие данные по предметам ( название предмета, код предмета, студенческие коды студентов, учащих этот предмет, результат ). Программа создает в результате экзаменационные листы по разным предметам в отдельных файлах, в которых: Название предмета в имени файла или в заголовке Имя и фамилия студента Его студенческий код Результат экзамена Сортировка студентов осуществляется по фамилиям.
18 Задание #4 Создать таблицу БД дат ( число, месяц, год ) и ввести в нее данные из файла Отсортировать данные по годам в отдельные массивы, и каждый массив отсортировать в возрастающем порядке по признаку ( месяц, число )
19 Задание #5 Создать таблицу БД певческого хора со следующими полями: имя. Фамилия, личный код, тембр голоса Внести данные по 10 людям, либо вручную, либо из текстового файла, который сделаете сами. Произвести поиск по тембру голоса на 4 категории ( сопрано, альт, тенор и бас ) В каждой из групп отсортировать людей по возрасту: женщин в возрастающем порядке, мужчин в убывающем порядке.
20 Задание на сортировку строк Создать текстовый файл, с 4-х значными последовательностями букв и цифр ( 23IO, 9010, … ) Считать файл программно и создать на его основе массив строк. Задача состоит в определении, является ли запись: а) bin-числом б) hex-числом вне зависимости от регистра символов. Результат вывести в файл в виде записей ( строка, база – 2 или 16 ) в возрастающем порядке найденные числа. В самом конце вывести строки, которые не принадлежат ни одной из вышеперечисленных категорий. В программе для представления каждой записи использовать структуры.
Еще похожие презентации в нашем архиве:
© 2024 MyShared Inc.
All rights reserved.