Г. Шилдт - Полный справочник по C++ (1109478), страница 22
Текст из файла (страница 22)
Например, если ма~сна щ объявлен оператором ]( зпс т(4] [Э] [б] [5] з, то функция вмпо1(), получающая его в качестве аргумента, может выглядеть гак: еозг] Гппс1(зпг. г][][3][5][5]) ( Разумеется, при желании можно указать и первый размер, но это не обязательно. Индексация указателей В языке С/С++ указатели и массивы тесно связаны друг с другом. Как извесгно, нмя массива без изаекса — это указатель на его первый элемент. Рассмотрим, например, следующий массив. [( с]зал р[10]з Следующие два выражения абсолютно идентичны. ар[0] С другой стороны, выражение $ р == ар[0] является истиззным, поскольку адрес первого элемента массива совпадает с адресом всего массива. Как указывачось ранее, имя массива представляет собой указатель.
И, наоборот, указатель можно индсксироватзн как массив. Рассмотрим следующий фрагмент программы. з с ь а зпе *р, з.[10); Р р[5] -- 100з Г* Прнспаннанне с помощью индекса *7 *(р+5) = 100з з'* Присааиаание с помощью адресной арифметики */ Оба оператора присваивания заносят число 100 в шестой элемент массива 1 Первый из них индексирует указатель р, а второй использует адресную арифметику. В обоих случаях результат одинаков. (Указатели и адресная арифметика изучаются в главе 5.) Глава 4, Массивы и строки Этот способ можно применять и к многомерным массивам.
Например, если переменная а — это указатель на целочис,тонный массив, состоящий из 1О строк и 10 столбцов, то следующие два оператора будут эквивалентными. а аа(0](01 Более того, доступ к элементу, стоящему на пересечении первой строки и пятого столбца, можно получить двумя способами: либо инлсксируя массив — а[0] [4], либо используя указатель — *((хпе а)а+4). Аналогично элемент, стоящий во второй строке и третьем столбце, является значением выражений а[1] [2] и *((1пс *)а+12). ДЛЯ двухмерного массива справедлива следующая формула: а[з] []г] = ((базовый тил )а + (1 * длина строки) + ]с) Правила адресной арифметики требуют приведения типа указателя на массив к его базовому типу.
Обращение к элементам массива с помощью указателей используется довольно широко, поскольку операции алресной арифметики выполняются быстрее, чем индексация. Двухмерный массив можно представить с помощью указателя на массив одномерных массивов. Следовательно, используя отдельный указатель, можно обращаться к элементам, стоящим в строках двухмерного массива.
Этот способ иллюстрируемся следующей функцией. Она выводит на печать содержимое заланной строки глобального целочисленного массива пшп. хпс пып(101(10!; чей рг гоы(1пс ]) ( хпс *р, р = (хпс *) согда(]](01 /* Подучить адрес первого элементе в строке с индексом ] */ бог(е=о; Е(10; +те) ргхпсу("Ы ", *(р+С))3 ) Эту функцию можно обобщить, включив в список аргументов индекс строки, ее длину и указатель на первый элемент массива.
чоЫ рг гон(хпс б, хпс гон Ивепахоп, хпс *р) ( хг1с р = р + (5 * гон с]хгаепахоп); хог(с=о; с<дом г]хмаепвхоп; т+с) ргхпсх("Ъс ", *(р+с)); чоха г(чохе]) ( хпс пои [ 101 (1 01; рг гои(0, 10, (хпе *) пои)," /* Вывод первой строки */ ) ИО Часть 1. Основы языка С++: тц(множество С Этот способ можно применять и к массивам более высокой размерности. Например, трехмерный массив можно свести к указателю на двухмерный массив, который, вовою очередь, можно представить с гвмощью указателя на одномерный массив.
В общем случае п-мерный массив можно свес~и к указателю на (и-1)-мерный массив и т.д. Процесс завершается получением указателей на одномерный массив. Инициализация массива В языке С/С++ допускается инициализация массивов при их объявлении. Общий вид инициализации массива не отличается от инициализации обычных переменных. гния массива имя массино)размер)) ...(размгрЖ) = (список значений) Список значений представляет собой список констант, разделенных запятымн. Тип констант должен быть совмссзнмым с типом массива.
Первая константа присваивается первому элементу массива, вторая — второму и т.д. Обратите внимание на то, что после закрывающейся фигурной скобки ) обязательно должна стоять точка с запятой. Рассмотрим пример, в котором целочисленный массив, состоящий из 10 элементов, инициализируется числами от 1 до 10. (В )пе 1(10) =- (1, 2, 3, 4, 5, б, 7, 8, 9, 10); Здесь элементу 1(О) присваивается значение 1, а элементу 1(9) — число 10. Символьные массивы можно инициализировать строковыми константами: с)зат имя массива(размер) ="сгпрока"; Например, следующий фрагмент инициализирует массив вет строкой "Я люблю С++". й с)зат втт(12) = "Я люблю О+~"; То же самое можно переписать иначе. с)зат втт(12) = ('Я', ' ', 'л', 'ю', 'б', 'л', 'ю', ' ', 'С', '10'); Поскольку строки завершаются нулевым байтом, необходимо следитгч чтобы размер массива был достаточным.
Вот почему размер массива вет равен 12, хотя строка "Я люблю С++" состоит из 11 символов. Если массив инициализируется строковой консинтой, компилятор автоматически добавляет нулевой байт Многомерные массивы инициализируются аналогично. Рассмотрим пример инициализации массива вцтв числами от 1 до 1О и их квадратами. гпе вцтв 110! (2) 1, 1, 2, 4, 3, 9, 4, 16, 5, 25, б, Зб, 7, 49, 9, 81, 10, 100 )Р Инициализируя многомерный массив, можно заключать элементы списка в фигурные скобки.
Этот способ называется субагрггагпной группировкой (зцЬаййгейа(е йгоцрщй). Например, предыдущую инициализацию можно переписать следующим образом. Глава 4. Массивы и строки зп) вс)тв)18] [2) (1, 1), (2, 4), (3, 9), (4, 16), (5, 25; (б, 36], (3, 49). (8, 64), (9, 81). [18, ).88) Если при группировке данных указаны не все начальные значения, оставшиеся элементы группы автоматически заполняются нулями. Инициализация безразмерного массива Представьтс себе инициализацию таблицы сообщений об ошибках, каждое из которых хранится в одномерном массиве.
т ) снес е1';12) = "Отибка при чтениихп"; сЬат е2[13] = "Описка при записи1п"; айат е3[18] — "Невозможно открыть файлхп"; Чтобы задать правильный размер массивов, пришлось бы подсчитывать точное количество символов в каждом сообщении. К счастью, компилятор может сам определить размер массива.
Если в операторе инициализации нс указан размер массива, компилятор автоматически создаст массив, вмещающий все начальные значения. Такой массив называется безрсзиеряым (ш)в[лег[ апау). Используя этот подход, можно переписать предыдущий фрагмент программы иначе. ) онат е1[] =- "Ожибка при чтениихп"г с]тат е2[] = 'Огаибка при записи1п'; снах е3[] : — 'Невозможно открыть файл1п") В этом случае оператор ГВ ртзптб("длина строки 1"Ъзх" равна ))бтп". е2, збзеоб е2); выведет на экран сообщение ГВ длина строки "Оыибка при записи" равна 18 Инициализация безразмерных массивов не ~олько облегчает программирование, но и позволяет изменять сообщения, не заботясь о размере массивов.
Этот способ применим и к многомерным массивам. Для этого требуется указать все размеры, кроме первого. (Остальные размеры нужны для того, чтобы компилятор правильно выполнял индексацию массива.) Это позволяет создавать таблицы переменной длины, носковы~ компилятор автоматически размещает нх в памяти. Например, объявление массива есте как безразмерного выглядит ~агс )пе в((те [] [2) = ( (1, 1), (2, 4), (3, 9), (4, 16), (5, 25), (б, 36), (7, 49), Часть). Основы языка С++: подмножество С Преимушестно ~акого объявления состоит в том.
что размер таблицы можно изменять, не меняя размеры массива. ~ Игра в крестики-нолики Приведенный ниже пример иллюстрирует способы манипулирования массивами в языке С/С++. В этом разлеле описана простая программа лля игры в крестики((олики. В качестве игральной доски используется двухмерный массив. Компьютер играет очень просто. Когда наступает его очередь ходить, он просматривает матрицу с помошью функции нее сощряеет вече(> н поисках свободной ячейки. Найдя такую ячейку, заполняет ес символом о.
Если нее ячейки заняты, фиксируется ничья, и программа прекрашает свою работу. Функция (гее р1ауее вочеО предлагает игроку сделать очередной ход и занести символ х в указанную им ячейку. Координаты левого нерхнего угла равны (1, 1), а правого нижнего — (3, 3). Массив вает1х инициализируется пробелами. Каждый хол, сделанный игроком или компьютером, заменяет пробел в соответстнуюшей ячейке символами о или х. Это позволяет легко вывести матрицу на экран.
После каждою хода вызывается функция снес)<О. Если победитель еше не определен, она возврашает пробел, если выиграл и~рок — символ к, а если компьютер— символ о. Эза функция просматривает матрицу в поисках строк, столбцов и диагоналей, заполненных одинаковыми символами. Текущее состояние игры отображается функцией айер вает1х(). Обратите внимание, насколько инициализация матрицы пробелами упрогцает эту функцию. Все функции получают доступ к массиву ваеезх по-разному. Изучите эти способы внимательно, чтобы лучше понять их механизм. /* Игра а крестики-нолики. */ Евпс1ибе <аЫ1о.ц> Вупс1ибе <эсб11Ь.Ь> спаг ваегвх[3)[3); /* игральная доска */ сцаг сйеск(чо1б)( чс1б 1пвс ваег1х(чей); чо)б пес р1ауег аюче(чо1с)); чово сес соврпсег вече(чо16); чо1д б1вр васг1х(чо1б): ьге ваап(чо1б) спаг с)опе; ркьпсг("это — игра в крестики нолики.