С.Б. Липпман, Ж. Лажойе - Язык программирования С++ Вводный курс (1114944), страница 21
Текст из файла (страница 21)
Если мы напишем операторвывода:cout << input << " " << om << endl;то все равно получим:109С++ для начинающих1101 3Эта проблема решается, если определить строковый массив, в котором элемент синдексом, равным значению элемента перечисления, будет содержать его имя. Имеяcout << open_modes_table[ input ] << " "такой массив, мы сможем написать:<< open_modes_table[ om ]<< endlБудет выведено:input append// не поддерживаетсяfor ( open_modes iter = input; iter != append; ++inter )Кроме того, нельзя перебрать все значения перечисления:// ...Для определения перечисления служит ключевое слово enum, а имена элементов задаютсяв фигурных скобках, через запятую.
По умолчанию первый из них равен 0, следующий –1 и так далее. С помощью оператора присваивания это правило можно изменить. Приэтом каждый следующий элемент без явно указанного значения будет на 1 больше, чемэлемент, идущий перед ним в списке. В нашем примере мы явно указали значение 1 для// shape == 0, sphere == 1, cylinder == 2, polygon == 3input, при этом output и append будут равны 2 и 3.
Вот еще один пример:enum Forms{ share, spere, cylinder, polygon };Целые значения, соответствующие разным элементам одного перечисления, не обязаны// point2d == 2, point2w == 3, point3d == 3, point3w == 4отличаться. Например:enum Points { point2d=2, point2w, point3d=3, point3w=4 };Объект, тип которого – перечисление, можно определять, использовать в выражениях ипередавать в функцию как аргумент.
Подобный объект инициализируется толькозначением одного из элементов перечисления, и только такое значение емуприсваивается – явно или как значение другого объекта того же типа. Дажесоответствующие допустимым элементам перечисления целые значения не могут бытьему присвоены:С++ для начинающихvoid mumble() {Points pt3d = point3d; // правильно: pt2d == 3// ошибка: pt3w инициализируется типом intPoints pt3w = 3;// ошибка: polygon не входит в перечисление Pointspt3w = polygon;// правильно: оба объекта типа Pointspt3w = pt3d;}Однако в арифметических выражениях перечисление может быть автоматическиconst int array_size = 1024;// правильно: pt2w преобразуется intпреобразовано в тип int.
Например:int chunk_size = array_size * pt2w;3.9. Тип “массив”Мы уже касались массивов в разделе 2.1. Массив – это набор элементов одного типа,доступ к которым производится по индексу – порядковому номеру элемента в массиве.Например:int ival;определяет ival как переменную типа int, а инструкцияint ia[ 10 ];задает массив из десяти объектов типа int. К каждому из этих объектов, или элементовмассива, можно обратиться с помощью операции взятия индекса:ival = ia[ 2 ];присваивает переменной ival значение элемента массива ia с индексом 2.
Аналогичноia[ 7 ] = ival;присваивает элементу с индексом 7 значение ival.Определение массива состоит из спецификатора типа, имени массива и размера. Размерзадает количество элементов массива (не менее 1) и заключается в квадратные скобки.Размер массива нужно знать уже на этапе компиляции, а следовательно, он должен бытьконстантным выражением, хотя не обязательно задается литералом. Вот примерыправильных и неправильных определений массивов:111С++ для начинающихextern int get_size();// buf_size и max_files константыconst int buf_size = 512, max_files = 20;int staff_size = 27;// правильно: константаchar input_buffer[ buf_size ];// правильно: константное выражение: 20 - 3char *fileTable[ max_files-3 ];// ошибка: не константаdouble salaries[ staff_size ];// ошибка: не константное выражениеint test_scores[ get_size() ];Объекты buf_size и max_files являются константами, поэтому определения массивовinput_buffer и fileTable правильны.
А вот staff_size – переменная (хотя иинициализированная константой 27), значит, salaries[staff_size] недопустимо.(Компилятор не в состоянии найти значение переменной staff_size в моментопределения массива salaries.)Выражение max_files-3 может быть вычислено на этапе компиляции, следовательно,определение массива fileTable[max_files-3] синтаксически правильно.Нумерация элементов начинается с 0, поэтому для массива из 10 элементов правильнымдиапазоном индексов является не 1 – 10, а 0 – 9. Вот пример перебора всех элементовint main(){const int array_size = 10;int ia[ array_size ];for ( int ix = 0; ix < array_size; ++ ix )ia[ ix ] = ix;массива:}При определении массив можно явно инициализировать, перечислив значения егоconst int array_size = 3;элементов в фигурных скобках, через запятую:int ia[ array_size ] = { 0, 1, 2 };Если мы явно указываем список значений, то можем не указывать размер массива:// массив размера 3компилятор сам подсчитает количество элементов:int ia[] = { 0, 1, 2 };112С++ для начинающихКогда явно указаны и размер, и список значений, возможны три варианта.
Присовпадении размера и количества значений все очевидно. Если список значений короче,чем заданный размер, оставшиеся элементы массива инициализируются нулями. Если же// ia ==> { 0, 1, 2, 0, 0 }const int array_size = 5;в списке больше значений, компилятор выводит сообщение об ошибке:int ia[ array_size ] = { 0, 1, 2 };Символьный массив может быть инициализирован не только списком символьныхзначений в фигурных скобках, но и строковым литералом.
Однако между этимиconst char cal[] = {'C', '+', '+' };способами есть некоторая разница. Допустим,const char cal2[] = "C++";Размерность массива ca1 равна 3, массива ca2 – 4 (в строковых литералах учитывается// ошибка: строка "Daniel" состоит из 7 элементовзавершающий нулевой символ). Следующее определение вызовет ошибку компиляции:const char ch3[ 6 ] = "Daniel";Массиву не может быть присвоено значение другого массива, недопустима иинициализация одного массива другим. Кроме того, не разрешается использовать массивconst int array_size = 3;int ix, jx, kx;// правильно: массив указателей типа int*int *iar [] = { &ix, &jx, &kx };// error: массивы ссылок недопустимыint &iar[] = { ix, jx, kx };int main(){int ia3{ array_size ]; // правильно// ошибка: встроенные массивы нельзя копироватьia3 = ia;return 0;ссылок. Вот примеры правильного и неправильного употребления массивов:}Чтобы скопировать один массив в другой, придется проделать это для каждого элементапо отдельности:113С++ для начинающих114const int array_size = 7;int ia1[] = { 0, 1, 2, 3, 4, 5, 6 };int main(){int ia3[ array_size ];for ( int ix = 0; ix < array_size; ++ix )ia2[ ix ] = ia1[ ix ];return 0;}В качестве индекса массива может выступать любое выражение, дающее результат целогоint someVal, get_index();типа.
Например:ia2[ get_index() ] = someVal;Подчеркнем, что язык С++ не обеспечивает контроля индексов массива – ни на этапекомпиляции, ни на этапе выполнения. Программист сам должен следить за тем, чтобыиндекс не вышел за границы массива. Ошибки при работе с индексом достаточнораспространены. К сожалению, не так уж трудно встретить примеры программ, которыекомпилируются и даже работают, но тем не менее содержат фатальные ошибки, рано илипоздно приводящие к краху.Упражнение 3.22(a) int ia[ buf_size ];(b) int ia[ get_size() ];(d) int ia[ 2 * 7 - 14 ](e) char st[ 11 ] = "fundamental";Какие из приведенных определений массивов содержат ошибки? Поясните.(c) int ia[ 4 * 7 - 14 ];Упражнение 3.23Следующий фрагмент кода должен инициализировать каждый элемент массиваint main() {const int array_size = 10;int ia[ array_size ];for ( int ix = 1; ix <= array_size; ++ix )ia[ ia ] = ix;// ...значением индекса.
Найдите допущенные ошибки:}С++ для начинающих3.9.1. Многомерные массивыВ С++ есть возможность использовать многомерные массивы, при объявлении которыхнеобходимо указать правую границу каждого измерения в отдельных квадратныхскобках. Вот определение двумерного массива:int ia[ 4 ][ 3 ];Первая величина (4) задает количество строк, вторая (3) – количество столбцов. Объектia определен как массив из четырех строк по три элемента в каждой. Многомерныеint ia[ 4 ][ 3 ] = {{ 0, 1, 2 },{ 3, 4, 5 },{ 6, 7, 8 },{ 9, 10, 11 }массивы тоже могут быть инициализированы:};Внутренние фигурные скобки, разбивающие список значений на строки, необязательны ииспользуются, как правило, для удобства чтения кода.
Приведенная ниже инициализацияв точности соответствует предыдущему примеру, хотя менее понятна:int ia[4][3] = { 0,1,2,3,4,5,6,7,8,9,10,11 };Следующее определение инициализирует только первые элементы каждой строки.Оставшиеся элементы будут равны нулю:int ia[ 4 ][ 3 ] = { {0}, {3}, {6}, {9} };Если же опустить внутренние фигурные скобки, результат окажется совершенно иным.Все три элемента первой строки и первый элемент второй получат указанное значение, аостальные будут неявно инициализированы 0.int ia[ 4 ][ 3 ] = { 0, 3, 6, 9 };При обращении к элементам многомерного массива необходимо использовать индексыдля каждого измерения (они заключаются в квадратные скобки).