Скачать 496.92 Kb.
|
Пример 4.5. Допускается использовать перечисляемый тип в конструкции switch. int main(){ enum Colors {Red, Green, Blue}; Colors color=Green; switch (color){ case Red: cout<< "Красный цвет"; break; case Green: cout<< "Зеленый цвет"; break; case Blue: cout<< "Синий цвет"; break;} return 0;} Структуры Структуры поименованная совокупность компонентов, называемых полями, или элементами структуры. Поля структуры могут иметь различный тип: любой другой базовый или производный тип, не ссылающийся рекурсивно на объявляемый структурный тип, другой структурный тип, указатель на данный структурный тип. struct [ имятипа ] { тип_1 элемент_1; тип_2 элемент_2; … тип_N элемент_N; } [ список_описателей ]; Если отсутствует имя типа, должен быть указан список описателей переменных, указателей или массивов.
Для инициализации структуры значения ее элементов перечисляют в фигурных скобках в порядке их описания: struct{ char fio[30]; int date, code; double t;} man = {"Иванов И.И.", 2008, 215, 36.6}; Для переменных одного и того же структурного типа определена операция присваивания, при этом происходит поэлементное копирование. Houman clon, man={"Сидоров С.С.", 2010, 10, 36.3}; clon=man; Доступ к полям структуры выполняется с помощью операций выбора . (точка) при обращении к полю через имя структуры и -> при обращении через указатель Homan man, *ps; man.fio = "Иванов И.И"; ps->t = 36.6; Если элементом структуры является другая структура, то доступ к ее элементам выполняется через две операции выбора: struct A {int a; double x;}; struct B {A a; A* b; double x;} x; x.a.a=1;x.x=0.1; x.b=new A; x.b->x=0.2; Процессор, в зависимости от разрядности, за один раз может обработать фиксированный размер памяти. Поэтому компилятор выравнивает размеры структуры для более эффективной работы с ними процессора. Каждое поле выравнивается по адресу, кратному размеру данного поля (для 32 разрядных систем это 4 байта, для 64 разрядных – 8 байт). Размер структуры выравнивается до размера, кратному размеру его максимального элемента. Данное выравнивание может приводить к увеличению занятой, но не используемой памяти. Пример: struct myStruct{ int myint;//занимает 4 байта bool mybool;//занимает байт, выровнено до 4 size_t mysize;//занимает 4 байта short myshort;//занимает 2 байта, выровнено до 4 void *myptr;// занимает 4 байта char mychar;//занимает 1 байт, выровнено до 4 }; Видно, что структура занимает вместо 16 байт, 24 байта. Для 64 разрядных процессоров эта структура расположиться в 48 байтах памяти вместо предполагаемых 24-х. Используемый структурой размер можно сократить путем перестановки полей по правилу «достаточно расположить поля в порядке убывания их размера». При таком расположении процессор за один раз может захватить несколько полей с размером меньшим size_t. struct myStruct{ size_t mysize;//занимает 4 байта void *myptr;// занимает 4 байта int myint;//занимает 4 байта short myshort;//занимает 2 байта bool mybool;//занимает байт char mychar;//занимает байт }; //последние 4 поля объединяются в блок размером 4 байта При таком расположении структура будет занимать 16 байт для 32 разрядного процессора и 24 для 64 разрядных.
Объединение - частный случай структуры, все поля которой располагаются по одному и тому же адресу. Формат объявления объединения такой же, как у структуры, только вместо ключевого слова struct используется слово union. Длина объединения равна наибольшей из длин его полей. В каждый момент времени в переменной типа объединение хранится только одно значение. Размер объединения тоже подвержен выравниванию. enum identification {FIO, INN}; identification type; /* объединение займет 28 байт. Данная область памяти может быть проинтерпретирована либо как набор из 25 символов либо как целое число типа long int */ union ident{ char fio[25]; long inn;} info; /* присваивание значений info и type */ switch (type){ case FIO: cout « “по фамилии: “ « info.fio; break; case INN: cout « “по инн: “ « info.inn; break;} Объединение удобно «обертывать» в структуру, включая туда дополнительное поле, определяющее, какой именно элемент объединения используется в каждый момент. Пример 4.6. enum identification {FIO, INN}; struct ident{ identification type; union { char fio[25]; long inn; } data; } info; info.type=INN; info.data.inn=12345; switch (info.type){ case FIO: cout << "FIO: " << info.data.fio; break; case INN: cout << "INN: " << info.data.inn; break;} Статические и динамические массивы Массив конечная, именованная, упорядоченная по индексам последовательность однотипных величин. Количество индексов, которые необходимо задать одновременно для доступа к элементу массива называется размерностью массива. Массивы с одним индексом называют одномерными, с несколькими – многомерными (в частности двумерными, трехмерными и т.д.). Различают массивы:
Описание статического одномерного массива: тип_элементов имя_массива [количество элементов]; Например, float а [10]; // описание массива из 10 вещественных чисел Элементы массива нумеруются с нуля. При описании могут быть использованы спецификаторы памяти и модификатор const. Количество элементов массива задается только целой положительной константой или константным выражением. Для доступа к элементу массива после его имени указывается индекс элемента в квадратных скобках. Например, запись a[1]=3.14; означает присвоить второму элементу вещественного одномерного массива значение 3.14.
Допускается не указывать явным образом количество элементов в массиве. Однако такой массив обязан быть проинициализирован при объявлении. Значения записываются в фигурных скобках, после операции присваивания. При инициализации массива с указанием количества элементов, если элементов в массиве больше, чем инициализаторов, элементы, для которых значения не указаны, обнуляются: int b[5] = {}; // инициализировать все пять элементов массива нулями int c[]={1,2,3,4,5,6,7}; /* определяем массив из семи элементов и инициализируем значениями от 1 до 7 */ Данная запись будет эквивалентной записи int c[7]={1,2,3,4,5,6,7}; либо int c[7]; c[0]=1;. c[l]=2; c[2]=3; c[3]=4; c[4]=5; c[5]=6; c[6]=7; Пример 4.7. Найти сумму элементов массива. int main(){ const int n = 10; int i, sum; int array[n] = {3, 4, 5, 4, 4}; for (i =0, sum = 0; i cout << "Сумма элементов: " << sum; return 0;} Идентификатор массива является константным указателем на его нулевой элемент. Идентификатор array из предыдущего примера эквивалентен &array[0]. К i-тому элементу данного массива можно обратиться как *(array+i). Пример 4.8. Копирование элементов одного массива в другой через указатели. int а[100], b[100]; // описываем два массива int *ра = а; // или int *рa = &а[0]; int *pb = b; for(int i = 0; i<100; i++) *pb++ = *pa++; // или pb[i] = pa[i]; тут происходит копирование. Статические многомерные массивы. Многомерные массивы в C++ рассматриваются как массивы, элементами которых являются массивы. Определение многомерного массива должно содержать информацию о типе, размерности (количество парных квадратных скобок) и количестве элементов каждой размерности. Пример. int matrix [6][8]; /* описание двумерной матрицы из 6 строк и 8 столбцов.*/ float cube[3][3][3]; // описание трехмерного массива вещественных чисел Доступ к элементу многомерного массива осуществляется через указание всех его индексов, например, matrix[i][j]=-20;
При инициализации многомерных массивов инициализаторы каждого подмассива заключаются в свои фигурные скобки. int mass2 [][]={ {1, 1}, {0, 2}, {1, 0} }; /* объявляем массив размерности 3 на 2 и инициализируем его значениями */ При явном указании количества элементов в каждой из размерностей допускается не отделять инициализаторы подмассивов скобками. int mass2 [3][2]={1, 1, 0, 2, 1, 0}; // компилятору ясно как инициализировать Динамические одномерные и многомерные массивы Память для динамических массивов выделяется так же динамически. Для создания одномерных динамических массивов используется операция new, при этом необходимо указать тип элементов и количество элементов в размерности. Например, int n = 100; float *p = new float [n]; В примере определен динамический массив вещественных чисел. Количество элементов уже не является константой, а определяется переменной, значение которой определяется логикой программы в ходе ее выполнения. Доступ к элементам динамического массива осуществляется так же, как и к статическим, через указание индекса либо через указатель: p[5]=3.14; *(р+6)=6.28.
Память, зарезервированная под динамический массив с помощью new [], должна освобождаться оператором delete []. Наличие квадратных скобок указывает компилятору на необходимость освободить память, занятую не одним элементом, а несколькими. Пример 4.9. Создание динамического массива на основе выборочных элементов статического массива. int main(){ const int num=20; // количество элементов статического массива int a[num]; // определяем статический массив int n=0; /* переменная для хранения количества элементов динамического массива */ for (int i=0;i a[i]=rand() % 100; if (a[i]<100/2) n++;} /* считаем количество элементов, меньше некоторого числа */ int *b; b=new int[n]; // создаем массив b, количество элементов теперь известно for(int i = 0,j=0; i if (a[i] < 100/2) {*(b+j)=a[i]; j++;}// в массив b помещаем нужные элементы for (int i=0; i< n;i++) cout<< b[i]<<" "; // элементы b на экран delete[] b ; // освобождаем память занятую массивом cout<< b; /* указатель указывает на некоторую ячейку, но эта память не принадлежит программе, и всякое изменение значения ячейки по этому адресу приведет к непредсказуемым последствиям */ return 0;} При создании многомерных динамических массивов придерживаются двух подходов:
Первый подход позволяет использовать динамическое выделение памяти только один раз поскольку подмассивы являются статическими. Пример 4.10. int dim1 = rand() % 10; /* количество элементов в первой размерности определяем как случайное число, т.е. это число будет известно только во время запуска программы */ const int dim2=10; /* количество элементов в оставшейся размерности считаем известным заранее */ /* ниже определяем матрицу со случайным количеством строк, у которой гарантированно 10 столбцов */ int ** matrix = (int **) new int [dim1][dim2]; matrix[0][1]=10; // далее работаем как с обычным массивом Запись int ** matrix определяет указатель на массив, элементами которого являются указателями на массив. Приведение типа необходимо, поскольку операция new возвращает указатель на одномерный массив. Второй подход заключается в том, что мы динамически создаем массив ссылок, а потом в цикле каждую из ссылок вновь связываем с динамическим массивом. Уничтожение массива необходимо проводить поэлементно. Пример 4.11. Организация двумерного «треугольного» динамического массива. int dim; int chgdim; // переменная для количества строк и столбцов cin>>dim; // вводим количество строк с клавиатуры chgdim=1; /* количество столбцов будет последовательно увеличиваться начиная с единицы */ int* *Matrix = new int*[dim]; // создаем массив указателей /* далее, в цикле каждый элемент массива связывает с динамическим массивом в котором chgdim элементов */ for (int i = 0; i < dim; i++, chgdim++) Matrix[i] = new int[chgdim]; /* в цикле заполняем массив случайными числами */ chgdim=1; for (int i=0; i< dim;i++,chgdim++) for (int j=0;j /* Выводим матрицу на экран в виде треугольника*/ chgdim=1; for (int i=0; i< dim;i++,chgdim++){ for (int j=0;j cout << endl; } /* в цикле освобождаем память занятую массивами - элементами одномерного массива */ for (int i = 0; i < dim; i++) delete[] Matrix[i]; delete[] Matrix; // освобождаем память из под одномерного массива Пример 4.12. Создание и уничтожение трехмерного массива. /* случайным образом задаем количества элементов в размерностях*/ int dim1=rand() % 10; int dim2=rand() % 10; int dim3=rand() % 10; int ***Cube; /* указатель, указывающий на указатель, указывающий на указатель, указывающий на int */ Cube = new int**[dim1]; // создаем одномерный массив for (int i = 0; i < dim1; i++) Cube[i] = new int*[dim2]; /* создаем двухмерный массив*/ /* в циклах проходим по всем элементам двухмерного массива и связываем элемент с динамическим массивом */ for (int i = 0; i < dim1; i++) for (int j = 0; j < dim2; j++) Cube[i][j] = new int[dim3]; //----------------------- /* работаем с массивом */ //--------------------- /* в циклах проходим по всем элементам двухмерного массива и освобождаем память, связанную с элементами */ for (int i = 0; i < dim1; i++) for (int j = 0; j < dim2; j++) delete[] Cube[i][j]; // проходим по элементам одномерного массива и освобождаем память for (int i = 0; i < dim1; i++) delete[] Cube[i]; delete[] Cube; // освобождаем память, занятую одномерным массивом |
Применение многопроцессорных вычислительных систем (мвс) ставит две задачи построения параллельных алгоритмов: распараллеливание... | Основы программирования и конфигурирования в корпоративных информационных системах | ||
Описать основные элементы структуры программы ( Раздел интерфейса, раздел реализации, раздел инициализации) | Цель контрольной работы – закрепление и проверка знаний, полученных студентами заочной формы обучения в процессе самостоятельного... | ||
Виртом в 1971 г., играет особую роль и в практическом программировании, и в его изучении. С непревзойденной четкостью в нем реализованы... | Методические указания предназначены для выполнения курсовой работы по дисциплине «Объектно-ориентированное программирование» для... | ||
Хотя набор стандартных функций электронных таблиц достаточно широк, для некоторых задач он либо недостаточен, либо выполнение таких... | Интерфейс среды matlab (окно команд, окно рабочего пространства, окно истории команд, окно «текущая папка», окно Details, меню Start,... | ||
Назовите основные разделы науки о языке и единицы языка, изучаемые в этих разделах | Представительством Европейского Союза в России для облегчения понимания правил конкурса для потенциальных российских участников.... |
Поиск Главная страница   Заполнение бланков   Бланки   Договоры   Документы    |