Arrays — Part 1st (Arrays and array processing)
Массив – это упорядоченная коллекция значений. Значения в массиве называются элементами, и каждый элемент характеризуется числовой позицией (или строкой если речь идет о ассоциативных массивах) в массиве, которая называется индексом (ключ для ассоциативных). Массивы в языке JavaScript являются нетипизированными: элементы массива могут иметь любой тип, причем разные элементы одного и того же массива могут иметь разные типы. Элементы массива могут даже быть объектами или другими массивами, что позволяет создавать сложные структуры данных, такие как массивы объектов и массивы массивов.
В JavaScript есть 2 типа массивов: ассоциативные массивы и массивы с числовыми индексами.
Ассоциативные массивы в JavaScript это не отдельный тип коллекции, а всего лишь объекты без методов. То есть если объект хранит данные и не делает с ними никаких действий это ассоциативный массив.
В отличии от ассоциативных массивов, массивы с числовыми индексами в JavaScript считаются отдельной кастой (говорят подкласом) обычных объектов. Но не образуют отдельного типа данных как в других языках програмирования.
2. Объекты как ассоциативные массивы
В этой главе мы рассмотрим использование объектов именно как массивов.
Ассоциативные массивы — структура данных, в которой можно хранить любые данные в формате ключ-значение.
Именно синтаксис доступа к полям объекта через квадратные скобки делает их похожими на ассоциативные массивы других языков програмирования.
Так как ассоциативные массивы это просто объекты, все методики работы с объектами справедливы и к ассоциативным массивам.
Могут закрасться сомнения нужно ли вводить такой термин как ассоциативные массивы, для JS колекций если это всего лишь объекты, но стоит знать что ассоциативные массивы имеют некие механизмы оптимизации, что приводит к отличиям реализаций таких структур на уровне памяти. А именно ассоциативные массивы поддерживают механизм компактного представления в памяти.
3. Массивы с числовыми индексами
В этой главе мы рассмотрим использование подкласса Array — что реализовывает массивы с числовыми индексами в JavaScript.
С этого момента и в будущем массивы с числовыми индексами мы будем называть просто массивами.
Массив – разновидность объекта, которая предназначена для хранения пронумерованных значений и предлагает дополнительные методы для удобного манипулирования такой коллекцией.
Отсчет индексов массивов в языке JavaScript начинается с нуля и для них используются 32-битные целые числа: первый элемент массива имеет индекс 0, а наибольший возможный индекс имеет значение 4294967295 элементов.
4. Создание массивов
Легче всего создать массив с помощью литерала, который представляет собой простой список разделенных запятыми элементов массива в квадратных скобках.
Значения в литерале массива не обязательно должны быть константами – это могут быть любые выражения:
Литералы массивов могут содержать литералы объектов или литералы других массивов:
Другой способ создания массива состоит в вызове конструктора Array(). Вызвать конструктор можно тремя разными способами:
В этом случае будет создан пустой массив, эквивалентный литералу [].
В этом случае будет создан пустой массив указанной длины. Такая форма вызова конструктора Array() может использоваться для предварительного распределения памяти под массив, если заранее известно количество его элементов. Обратите внимание, что при этом в массиве не сохраняется никаких значений и даже свойства-индексы массива с именами «0», «1» и т.д. в массиве не определены.
В этом случае аргументы конструктора становятся значениями элементов нового массива. Использование литералов массивов практически всегда проще, чем подобное применение конструктора Array().
5. Доступ к элементам массива
Доступ к элементам массива осуществляется с помощью оператора [ ]. Слева от скобок должна присутствовать ссылка на массив. Внутри скобок должно находиться произвольное выражение, возвращающее неотрицательное целое значение. Этот синтаксис пригоден как для чтения, так и для записи значения элемента массива. Следовательно, допустимы все приведенные далее JavaScript-инструкции:
Напомню, что массивы являются специализированной разновидностью объектов. Квадратные скобки, используемые для доступа к элементам массива, действуют точно так же, как квадратные скобки, используемые для доступа к свойствам объекта. Интерпретатор JavaScript преобразует указанные в скобках числовые индексы в строки – индекс 1 превращается в строку «1», – а затем использует строки как имена свойств. В преобразовании числовых индексов в строки нет ничего особенного: то же самое можно проделывать с обычными объектами.
6. Длина массива
Любой массив имеет свойство length, и это свойство отличает массивы от обычных объектов JavaScript. Для плотных (т. е. неразреженных) массивов свойство length определяет количество элементов в массиве. Его значение на единицу больше самого большого индекса в массиве:
Вторая особенность в поведении, обеспечивающем работу свойства length, заключается в том, что при присваивании свойству length неотрицательного целого числа n, меньшего, чем его текущее значение, все элементы массива с индексами, большими или равными значению n, удаляются из массива:
7. Добавление и удаление элементов массива
Мы уже видели, что самый простой способ добавить элементы в массив заключается в том, чтобы присвоить значения новым индексам:
8. Методы класса Array
Стандарты ECMAScript3-6 определяеют в составе Array.prototype множество удобных функций для работы с массивами, которые доступны как методы любого массива. Эти методы будут представлены в следующих подразделах. Более полную информацию можно найти в разделе Array в справочной части MDN по базовому языку JavaScript.
8.1 ES3
8.1.1 Метод join()
Метод Array.join() преобразует все элементы массива в строки, объединяет их и возвращает получившуюся строку. В необязательном аргументе методу можно передать строку, которая будет использоваться для отделения элементов в строке результата. Если строка-разделитель не указана, используется запятая.
8.1.2 Метод reverse()
Метод Array.reverse() меняет порядок следования элементов в массиве на обратный и возвращает переупорядоченный массив. Перестановка выполняется непосредственно в исходном массиве, т. е. этот метод не создает новый массив с переупорядоченными элементами, а переупорядочивает их в уже существующем массиве.
8.1.3 Метод split()
Метод split(s), который позволяет превратить строку в массив, разбив ее по разделителю s. В примере ниже таким разделителем является строка из запятой и пробела.
У метода split есть необязательный второй аргумент – ограничение на количество элементов в массиве. Если их больше, чем указано – остаток массива будет отброшен.
8.1.4 Метод slice()
Метод Array.slice() возвращает фрагмент, или подмассив, указанного массива. Два аргумента метода определяют начало и конец возвращаемого фрагмента. Возвращаемый массив содержит элемент, номер которого указан в первом аргументе, плюс все последующие элементы, вплоть до (но не включая) элемента, номер которого указан во втором аргументе. Если указан только один аргумент, возвращаемый массив содержит все элементы от начальной позиции до конца массива. Если какой-либо из аргументов имеет отрицательное значение, он определяет номер элемента относительно конца массива. Так, аргументу –1 соответствует последний элемент массива, а аргументу –3 – третий элемент массива с конца.
Если вообще не указать аргументов – скопируется весь массив.
8.1.5 Метод splice()
Метод Array.splice() – это универсальный метод, выполняющий вставку или удаление элементов массива. Метод splice() изменяет исходный массив, относительно которого он был вызван. Обратите внимание, что методы splice() и slice() имеют очень похожие имена, но выполняют совершенно разные операции.
Метод splice() может удалять элементы из массива, вставлять новые элементы или выполнять обе операции одновременно. Элементы массива при необходимости смещаются, чтобы после вставки или удаления образовывалась непрерывная последовательность. Первый аргумент метода splice() определяет позицию в массиве, начиная с которой будет выполняться вставка и/или удаление. Второй аргумент определяет количество элементов, которые должны быть удалены (вырезаны) из массива. Если второй аргумент опущен, удаляются все элементы массива от указанного до конца массива. Метод splice() возвращает массив удаленных элементов или (если ни один из элементов не был удален) пустой массив.
Первые два аргумента метода splice() определяют элементы массива, подлежащие удалению. За этими аргументами может следовать любое количество дополнительных аргументов, определяющих элементы, которые будут вставлены в массив, начиная с позиции, указанной в первом аргументе. Например:
8.1.6 Метод concat()
Метод Array.concat() создает и возвращает новый массив, содержащий элементы исходного массива, для которого был вызван метод concat(), и значения всех аргументов, переданных методу concat(). Если какой-либо из этих аргументов самявляется массивом, его элементы добавляются в возвращаемый массив. Следует, однако, отметить, что рекурсивного превращения массива из массивов в одно мерный массив не происходит. Метод concat() не изменяет исходный массив. Ниже приводится несколько примеров:
8.1.7 Метод sort()
Метод Array.sort() сортирует элементы в исходном массиве и возвращает отсортированный массив. Если метод sort() вызывается без аргументов, сортировка выполняется в алфавитном порядке (для сравнения элементы временно преобразуются в строки, если это необходимо).
Для сортировки в каком-либо ином порядке, отличном от алфавитного, методу sort() можно передать функцию сравнения в качестве аргумента. Эта функция устанавливает, какой из двух ее аргументов должен следовать раньше в отсортированном списке. Если первый аргумент должен предшествовать второму, функция сравнения должна возвращать отрицательное число. Если первый аргумент должен следовать за вторым в отсортированном массиве, то функция должна возвращать число больше нуля. А если два значения эквивалентны (т.е. порядок их следования не важен), функция сравнения должна возвращать 0. Поэтому, например, для сортировки элементов массива в числовом порядке можно сделать следующее:
Обратите внимание, насколько удобно использовать в этом фрагменте неименованную функцию. Функция сравнения используется только здесь, поэтому нет необходимости давать ей имя.
8.2 ES5
Стандарт ECMAScript 5 определяет девять новых методов массивов, позволяющих выполнять итерации, отображение, фильтрацию, проверку, свертку и поиск. Все эти методы описываются в следующих далее подразделах.
Однако, прежде чем перейти к изучению особенностей, следует сделать некоторые обобщения, касающиеся методов массивов в ECMAScript 5. Во-первых, большинство описываемых ниже методов принимают функцию в первом аргументе и вызывают ее для каждого элемента (или нескольких элементов) массива. В случае разреженных массивов указанная функция не будет вызываться для несуществующих элементов. В большинстве случаев указанной функции передаются три аргумента: значение элемента массива, индекс элемента и сам массив. Чаще всего вам необходим будет только первый аргумент, а второй и третий аргументы можно просто игнорировать. Большинство методов массивов, введенных стандартом ECMAScript 5, которые в первом аргументе принимают функцию, также принимают второй необязательный аргумент. Если он указан, функция будет вызываться, как если бы она была методом этого второго аргумента. То есть второй аргумент будет доступен функции, как значение ключевого слова this. Значение, возвращаемое функцией, играет важную роль, но разные методы обрабатывают его по-разному. Ни один из методов массивов, введенных стандартом ECMAScript 5, не изменяет исходный массив. Разумеется, функция, передаваемая этим методам, может модифицировать исходный массив.
8.2.1 Метод forEach()
Метод forEach() выполняет обход элементов массива и для каждого из них вызывает указанную функцию. Как уже говорилось выше, функция передается методу forEach() в первом аргументе. При вызове этой функции метод forEach() будет передавать ей три аргумента: значение элемента массива, индекс элемента и сам массив. Если вас интересует только значение элемента, можно написать функцию с одним параметром – дополнительные аргументы будут игнорироваться:
8.2.2 Метод map()
Метод map() создаёт новый массив с результатом вызова указанной функции для каждого элемента массива.
Функция map просто преобразует один массив в другой массив. Например, предположим, что у вас есть массив объектов person, но вам нужен массив name (строк):
8.2.3 Метод filter()
Метод filter() возвращает массив, содержащий подмножество элементов исходного массива. Передаваемая ему функция должна быть функцией-предикатом, т. е. должна возвращать значение true или false. Метод filter() вызывает функцию точно так же, как методы forEach() и map(). Если возвращается true или значение, которое может быть преобразовано в true, переданный функции элемент считается членом подмножества и добавляется в массив, возвращаемый методом. Например:
Обратите внимание, что метод filter() пропускает отсутствующие элементы в разреженных массивах и всегда возвращает плотные массивы. Чтобы уплотнить разреженный массив, можно выполнить следующие действия:
А чтобы уплотнить массив и удалить из него все элементы со значениями undefined и null, можно использовать метод filter(), как показано ниже:
8.2.3 Методы every() и some()
Метод some() проверяет, удовлетворяет ли хоть какой-нибудь элемент массива условию, заданному в передаваемой функции.
Метод some() вызывает переданную функцию callback один раз для каждого элемента, присутствующего в массиве до тех пор, пока не найдет такой, для которого callback вернет истинное значение (значение, становящееся равным true при приведении его к типу Boolean). Если такой элемент найден, метод some() немедленно вернёт true. В противном случае, если callback вернёт false для всех элементов массива, метод some() вернёт false. Функция callback вызывается только для индексов массива, имеющих присвоенные значения; она не вызывается для индексов, которые были удалены или которым значения никогда не присваивались.
Метод every() проверяет, удовлетворяют ли все элементы массива условию, заданному в передаваемой функции.
Метод every() вызывает переданную функцию callback один раз для каждого элемента, присутствующего в массиве до тех пор, пока не найдет такой, для которого callback вернет ложное значение (значение, становящееся равным false при приведении его к типу Boolean). Если такой элемент найден, метод every() немедленно вернёт false. В противном случае, если callback вернёт true для всех элементов массива, метод every() вернёт true. Функция callback вызывается только для индексов массива, имеющих присвоенные значения; она не вызывается для индексов, которые были удалены или которым значения никогда не присваивались.
8.2.4 Методы reduce() и reduceRight()
8.2.5 Методы indexOf() и lastIndexOf()
Методы indexOf() и lastIndexOf() отыскивают в массиве элемент с указанным значением и возвращают индекс первого найденного элемента или –1, если элемент с таким значением отсутствует. Метод indexOf() выполняет поиск от начала массива к концу, а метод lastIndexOf() – от конца к началу.
В отличие от других методов, описанных в этом разделе, методы indexOf() и lastIndexOf() не принимают функцию в виде аргумента. В первом аргументе им передается искомое значение. Второй аргумент является необязательным: он определяет индекс массива, с которого следует начинать поиск. Если опустить этот аргумент, метод indexOf() начнет поиск с начала массива, а метод lastIndexOf() – с конца. Во втором аргументе допускается передавать отрицательные значения, которые интерпретируются как смещение относительно конца массива, как в методе splice(): значение –1, например, соответствует последнему элементу массива.
Методы доступа к элементам массивов
В языке СИ между указателями и массивами существует тесная связь. Например, когда объявляется массив в виде int array[25], то этим определяется не только выделение памяти для двадцати пяти элементов массива, но и для указателя с именем array, значение которого равно адресу первого по счету (нулевого) элемента массива, т.е. сам массив остается безымянным, а доступ к элементам массива осуществляется через указатель с именем array. С точки зрения синтаксиса языка указатель arrey является константой, значение которой можно использовать в выражениях, но изменить это значение нельзя.
Поскольку имя массива является указателем допустимо, например, такое присваивание:
Здесь указатель ptr устанавливается на адрес первого элемента масcива, причем присваивание ptr=arrey можно записать в эквивалентной форме ptr=&arrey[0].
Для доступа к элементам массива существует два различных способа. Первый способ связан с использованием обычных индексных выражений в квадратных скобках, например, array[16]=3 или array[i+2]=7. При таком способе доступа записываются два выражения, причем второе выражение заключается в квадратные скобки. Одно из этих выражений должно быть указателем, а второе — выражением целого типа. Последовательность записи этих выражений может быть любой, но в квадратных скобках записывается выражение следующее вторым. Поэтому записи array[16] и 16[array] будут эквивалентными и обозначают элемент массива с номером шестнадцать. Указатель используемый в индексном выражении не обязательно должен быть константой, указывающей на какой-либо массив, это может быть и переменная. В частности после выполнения присваивания ptr=array доступ к шестнадцатому элементу массива можно получить с помощью указателя ptr в форме ptr[16] или 16[ptr].
Второй способ доступа к элементам массива связан с использованием адресных выражений и операции разадресации в форме *(array+16)=3 или *(array+i+2)=7. При таком способе доступа адресное выражение равное адресу шестнадцатого элемента массива тоже может быть записано разными способами *(array+16) или *(16+array).
При реализации на компьютере первый способ приводится ко второму, т.е. индексное выражение преобразуется к адресному. Для приведенных примеров array[16] и 16[array] преобразуются в *(array+16).
Для доступа к начальному элементу массива (т.е. к элементу с нулевым индексом) можно использовать просто значение указателя array или ptr. Любое из присваиваний
присваивает начальному элементу массива значение 2, но быстрее всего выполнятся присваивания *array=2 и *ptr=2, так как в них не требуется выполнять операции сложения.
1.7.2. Указатели на многомерные массивы
Указатели на многомерные массивы в языке СИ — это массивы массивов, т.е. такие массивы, элементами которых являются массивы. При объявлении таких массивов в памяти компьютера создается несколько различных объектов. Например при выполнении объявления двумерного массива int arr2[4][3] в памяти выделяется участок для хранения значения переменной arr, которая является указателем на массив из четырех указателей. Для этого массива из четырех указателей тоже выделяется память. Каждый из этих четырех указателей содержит адрес массива из трех элементов типа int, и, следовательно, в памяти компьютера выделяется четыре участка для хранения четырех массивов чисел типа int, каждый из которых состоит из трех элементов. Такое выделение памяти показано на схеме на рис.3.
| в | ||||
|---|---|---|---|---|
| а | ||||
| а | ||||
| а | ||||
| а | ||||
| Рис.3. Распределение памяти для двумерного массива. | ||||
Таким образом, объявление arr2[4][3] порождает в программе три разных объекта: указатель с идентификатором arr, безымянный массив из четырех указателей и безымянный массив из двенадцати чисел типа int. Для доступа к безымянным массивам используются адресные выражения с указателем arr. Доступ к элементам массива указателей осуществляется с указанием одного индексного выражения в форме arr2[2] или *(arr2+2). Для доступа к элементам двумерного массива чисел типа int должны быть использованы два индексных выражения в форме arr2[1][2] или эквивалентных ей *(*(arr2+1)+2) и (*(arr2+1))[2]. Следует учитывать, что с точки зрения синтаксиса языка СИ указатель arr и указатели arr[0], arr[1], arr[2], arr[3] являются константами и их значения нельзя изменять во время выполнения программы.
Размещение трехмерного массива происходит аналогично и объявление float arr3[3][4][5] порождает в программе кроме самого трехмерного массива из шестидесяти чисел типа float массив из четырех указателей на тип float, массив из трех указателей на массив указателей на float, и указатель на массив массивов указателей на float.
При размещении элементов многомерных массивов они располагаются в памяти подряд по строкам, т.е. быстрее всего изменяется последний индекс, а медленнее — первый. Такой порядок дает возможность обращаться к любому элементу многомерного массива, используя адрес его начального элемента и только одно индексное выражение.
Например, обращение к элементу arr2[1][2] можно осуществить с помощью указателя ptr2, объявленного в форме int *ptr2=arr2[0] как обращение ptr2[1*4+2] (здесь 1 и 2 это индексы используемого элемента, а 4 это число элементов в строке) или как ptr2[6]. Заметим, что внешне похожее обращение arr2[6] выполнить невозможно так как указателя с индексом 6 не существует.
Для обращения к элементу arr3[2][3][4] из трехмерного массива тоже можнo использовать указатель, описанный как float *ptr3=arr3[0][0] с одним индексным выражением в форме ptr3[3*2+4*3+4] или ptr3[22].
Далее приведена функция, позволяющая найти минимальный элемент в трехмерном массиве. В функцию передается адрес начального элемента и размеры массива, возвращаемое значение — указатель на структуру, содержащую индексы минимального элемента.
1.7.3. Операции с указателями
Над указателями можно выполнять унарные операции: инкремент и декремент. При выполнении операций ++ и — значение указателя увеличивается или уменьшается на длину типа, на который ссылается используемый указатель.
В бинарных операциях сложения и вычитания могут участвовать указатель и величина типа int. При этом результатом операции будет указатель на исходный тип, а его значение будет на указанное число элементов больше или меньше исходного.
В операции вычитания могут участвовать два указателя на один и тот же тип. Результат такой операции имеет тип int и равен числу элементов исходного типа между уменьшаемым и вычитаемым, причем если первый адрес младше, то результат имеет отрицательное значение.
Значения двух указателей на одинаковые типы можно сравнивать в операциях ==, !=, , >= при этом значения указателей рассматриваются просто как целые числа, а результат сравнения равен 0 (ложь) или 1 (истина).
В данном примере значение ptr1 меньше значения ptr2 и поэтому оператор a[3]=4 не будет выполнен.
1.7.4. Массивы указателей
В языке СИ элементы массивов могут иметь любой тип, и, в частности, могут быть указателями на любой тип. Рассмотрим несколько примеров с использованием указателей.
Следующие объявления переменных
порождают программные объекты, представленные на схеме на рис.4.
| в | ||||||
|---|---|---|---|---|---|---|
| а | . | . | . | . | . | |
| в | в | в | в | в | ||
| а | ||||||
| Рис.4. Схема размещения переменных при объявлении. | ||||||
При выполнении операции pp-p получим нулевое значение, так как ссылки pp и p равны и указывают на начальный элемент массива указателей, связанного с указателем p ( на элемент p[0]).
После выполнения операции pp+=2 схема изменится и примет вид, изображенный на рис.5.
| в | ||||||
|---|---|---|---|---|---|---|
| а | . | . | . | . | . | |
| в | в | в | в | в | ||
| а | ||||||
| Рис.5. Схема размещения переменных после выполнения операции pp+=2. | ||||||
Результатом выполнения вычитания pp-p будет 2, так как значение pp есть адрес третьего элемента массива p. Ссылка *pp-a тоже дает значение 2, так как обращение *pp есть адрес третьего элемента массива a, а обращение a есть адрес начального элемента массива a. При обращении с помощью ссылки **pp получим 12 — это значение третьего элемента массива a. Ссылка *pp++ даст значение четвертого элемента массива p т.е. адрес четвертого элемента массива a.
Если считать, что pp=p, то обращение *++pp это значение первого элемента массива a (т.е. значение 11), операция ++*pp изменит содержимое указателя p[0], таким образом, что он станет равным значению адреса элемента a[1].
Сложные обращения раскрываются изнутри. Например обращение *(++(*pp)) можно разбить на следующие действия: *pp дает значение начального элемента массива p[0], далее это значение инкременируется ++(*p) в результате чего указатель p[0] станет равен значению адреса элемента a[1], и последнее действие это выборка значения по полученному адресу, т.е. значение 11.
В предыдущих примерах был использован одномерный массив, рассмотрим теперь пример с многомерным массивом и указателями. Следующие объявления переменных
порождают в программе объекты представленные на схеме на рис.6.
Рис.6. Схема размещения указателей на двумерный массив.
Согласно этой схеме доступ к элементу a[0][0] получить по указателям a, p, pa при помощи следующих ссылок: a[0][0], *a, **a[0], *p, **pa, *p[0].
Рассмотрим теперь пример с использованием строк символов. Объявления переменных
можно изобразить схемой представленной на рис.7.
Рис.7. Схема размещения указателей на строки.
1.7.5. Динамическое размещение массивов
При динамическом распределении памяти для массивов следует описать соответствующий указатель и присваивать ему значение при помощи функции calloc. Одномерный массив a[10] из элементов типа float можно создать следующим образом
Для создания двумерного массива вначале нужно распределить память для массива указателей на одномерные массивы, а затем распределять память для одномерных массивов. Пусть, например, требуется создать массив a[n][m], это можно сделать при помощи следующего фрагмента программы:
Массивы
Массивы представляют собой ограниченное упорядоченное множество однотипных величин. Каждая отдельная величина называется элементом (компонентной) массива.
2. Какие типы данных могут быть элементами массива?
Тип элементов массива может быть любым, принятым в языке Паскаль, кроме файлового типа. Этот тип называется базовым типом.
3. Как описывается одномерный массив?
Согласно синтаксису языка Паскаль, массив можно описывать двумя способами. Первый способ – в разделе описания переменных var . Второй способ – с использованием описания собственного типа в разделе type .
Способ 1. Описание одномерного массива в разделе описания переменных var.
Способ 2. Описание одномерного массива с использованием раздела описания type .
4. Как осуществляется доступ к элементам одномерного массива?
Пусть имеем следующее описание:
Тогда чтобы присвоить значение конкретному элементу массива можно написать:
5. Пример фрагмента кода обнуления массива с именем M , содержащего 100 целых ( integer ) чисел.
6. Пример подсчета суммы элементов массива Mas , содержащего 50 вещественных ( real ) чисел.
7. Пример поиска максимального элемента в массиве из 100 целых чисел.
8. Пример определения наличия заданного элемента в массиве из 100 целых чисел.
В примере массив элементов содержится в переменной Mas , искомый элемент содержится в переменной num .
9. Пример сортировки одномерного массива Mas вещественных чисел методом вставки.
Фрагмент кода, который сортирует массив целых чисел, в котором максимальное количество элементов равно MaxItems . Элементы сортируются в порядке убывания.
10. Как в языке Паскаль осуществляется присвоение значения одного массива другому?
Фрагмент кода, в котором массиву M2 присваивается значение массива M1 . Массивы должны быть одного типа.
11. Как осуществляется инициализация одномерного массива?
Инициализация одномерного массива осуществляется в разделе описания констант const .
В следующем фрагменте кода инициализируются два массива:
- массив из 3 элементов, которые являются вещественными числами;
- массив из 5 элементов, которые являются целыми числами.
12. Пример описания и использования двумерного массива в программе?
Как и в случае с одномерными массивами существует два способа описания двумерных массивов.
Пример 1. Описание двумерного массива непосредственно в разделе var .
Пример 2. Описание с использованием раздела type .
Пример присвоения значений элементам двумерного массива
При обращении в квадратных дужках первым указывается номер строки, вторым – номер столбца.
13. Примеры описания многомерных массивов.
В данном примере описывается трехмерный и четырехмерный массивы чисел.
14. Пример инициализации двумерного массива.
В следующем примере инициализируются двумерные массивы целых чисел которые описываются разными способами. Согласно синтаксису языка Паскаль инициализация массивов должна осуществляться в разделе описания констант ( const ).
15. Пример инициализации многомерного массива.
Инициализация трехмерного массива целых чисел:
16. Пример обнуления двумерной матрицы целых чисел размером 10 * 10 .
В данном примере обнуляется матрица с именем Matr .
17. Пример поиска заданного элемента в матрице размером 20 * 20 целых чисел.
В данном примере num – искомый элемент, f_is – флажок, который определяет наличие элемента в матрице. Считается, что матрица Matr уже заполнена значениями.
18. Пример определения минимального значения в матрице вещественных чисел.
В данном примере искомое минимальное значение сохраняется в переменной min . Считается, что матрица Matr уже заполнена значениями.
19. Пример вычисления суммы элементов матрицы вещественных чисел.
В данном примере сумма элементов матрицы сохраняется в переменной sum . Считается, что матрица Matr уже заполнена значениями.
20. Пример описания и использования одномерного массива структур типа BOOK (КНИГА).
Пусть имеем следующее описание:
Пример доступа к элементам массива структур BOOKS . В данном примере в элемент с индексом 3 массива BOOKS заносятся данные.
21. Пример описания и использования массива строк (тип string ).
22. Пример описания и использования массива классов.
В данном примере описывается класс с именем TMyClass . В классе объявлены две переменные с именами x и y . Доступ к этим переменным есть общедоступным ( public ).
Name already in use
lectures / 6. массивы, перечисления.md
- Go to file T
- Go to line L
- Copy path
- Copy permalink
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents
Copy raw contents
Copy raw contents
6. массивы и перечисления
- массивы
- Описание
- Инициализация
- Доступ к элементам
- Строки символов
- Приёмы обработки
- Указатели и массивы
- Перечисления
- Описание
- Пример использования
- Объединения
Как и в большинстве других языков программирования, в Си под массивом понимается совокупность однородных данных, рассматриваемых как нечто единое. Математическими аналогами программистского понятия массив является, например, матрица, которая в программе задается в виде двухмерного массива, или вектор, задаваемый одномерным массивом. Массив это такой объект программы, который характеризуется именем, размерностью, количеством элементов по каждому измерению и типом значений его элементов.
<тип> определяет тип элементов массива;
<имя> – это <идентификатор>, задающийся по усмотрению программиста и являющийся именем массива. Имя массива используется для доступа к элементам массива;
<размер> определяет количество элементов массива по каждому измерению и записывается целой беззнаковой константой.
Доступ к элементу массива обеспечивается использованием имени массива, вслед за которым в квадратных скобках записываются координаты элемента (индексы) по соответствующим измерениям. Элементы многомерного массива отображаются в линейной памяти одномерным массивом, своеобразной построчной разверткой.
При описании массивов с инициализацией элементов не обязательно указывать размеры массива. Компилятор сам определит количество элементов и выделит для них память соответствующего размера. Недостающие при инициализации значения принимаются равными нулю
Инициализация многомерного массива похожа на сбор матрешки. Имеем как бы несколько массивов вложеных друг в друга. Но ничего не мешает развертывать многомерный массив построчно, как будто это линейный массив.
Доступ к элементам массива
Использование индексированной переменной. Это наиболее естественный, простой и понятный способ доступа к элементам массива любой размерности.
Использованный в исходной программе способ обращения к элементу массива на самом деле заменяется компилятором на обращение через указатель – имя массива. Отсюда становится понятным, почему в Си нумерация индексов массива начинается с нуля.
Использование имени одномерного массива. Этот способ доступа к элементам массива основан на том, что в Си имя одномерного массива трактуется как константа-указатель на данные, тип которых определен типом элементов массива, а значением этой константы является адрес нулевого элемента. Следовательно, применив к имени массива операции адресной арифметики, можно получить доступ к любому элементу массива.
Доступ к элементам многомерных массивов. Многомерный массив трактуется как одномерный массив массивов.
Доступ через переменную указатель. К элементам массива можно обратиться при помощи вспомогательного указателя. Для этого необходимо описать указатель с типом, соответствующим типу массива, и присвоить ему значение имени массива, которое является константой типа указатель. Теперь с указателем можно манипулировать как с переменной, ссылающейся на элементы массива, над ней можно выполнять любые действия, допустимые в адресной арифметике.
надо учитывать , что указатель «передвигается» по данным в той последовательности, в какой они расположены в памяти. Если, увеличивая указатель, мы выйдем за пределы данных массива, то он будет указывать на неопределенные данные.
Cимвольная строка в Си есть не что иное, как массив символов, последним символом которого является нуль-символ – признак конца строки. Для нуль-символа также надо зарезервировать место в массиве. Размер массива можно задавать и явно.
При обработке нескольких строк удобно организовать для их хранения массив символьных строк.
Двухмерный массив можно трактовать как одномерный массив, элементами которого являются другие одномерные массивы.
В отличие от массива символьных строк, здесь строки не дополняются нуль-символами для достижения одинаковой длины, а занимают столько места в памяти, сколько в них символов плюс нуль-символ.
Приёмы обработки массива
пример: Упорядочивание строк по алфавиту
Указатели и массивы
В Си существует связь между указателями и массивами. Любой доступ к элементу массива, осуществляемый операцией индексирования, может быть выполнен с помощью указателя.
Вычисляя а[i] , Си сразу преобразует его в *(a+i)
Между именем массива и указателем, выступающим в роли имени массива, существует одно различие. Указатель — это переменная, поэтому можно написать ра=а или ра++ . Но имя массива не является переменной, это скорее константа, и записи вроде а=ра или а++ не допускаются.
Если имя массива передается функции, то последняя получает в качестве аргумента адрес его начального элемента. Внутри вызываемой функции этот аргумент является локальной переменной, содержащей адрес.
переменная s — указатель, к ней применима операция ++ ; s++ не оказывает никакого влияния на строку символов функции, которая обратилась к strlen . Просто увеличивается на 1 некоторая копия указателя, находящаяся в личном пользовании функции strlen .
Перечисление – это конструируемый тип данных, во время описания которого задается имя типа данных и значения, которые могут принимать переменные этого типа.
<имя_типа> задается идентификатором Си по усмотрению программиста;
<список_значений> задается в виде: <элемент1>, <элемент2>. <элементN>, где любой из элементов есть либо <имя>, либо <имя> = <константное_выражение>.
<список_переменных> – это список имен переменных типа перечисление, отделенные друг от друга запятой.
по сути создаются именованные константы, значения которым присваивается автоматически и ничто не запрещает использовать их как обычные целочисленные константы
Предположим, нам необходимо написать фрагмент программы, который будет определять, образуют ли растворимую или нерастворимую в воде соль заданные кислота и металл.