Как задается количество элементов массива
Массив – это поименованная совокупность однотипных элементов, упорядоченных по индексам, определяющим положение элемента в массиве.
Массив в языке Pascal – это набор однотипных данных, причём количество этих данных фиксировано и определяется при описании массива. Все переменные, входящие в массив, имеют одно и то же имя – имя массива, а различаются они по индексу – номеру (месту) в массиве.
Массив Result :
Массив Season :
Описание массива
Описание массива выглядит так:
array [<тип индекса>] of <тип компонент>
• array и of – служебные слова («массив» и «из»);
• <тип индекса> – описание индексации компонент (элементов) массива;
• <тип компонент> – тип величин, составляющих массив.
Запишите описание массива, ориентируясь на его назначение.
Массив для записи температуры (целое число) каждого дня года.
var Day: array [1..366] of integer;
Массив для ежечасной записи температуры больного в течении суток.
var T: array [1..24] of real;
Массив для подсчета частоты встречаемости прописных латинских букв в тексте.
var T: array [‘A’ .. ‘Z’] of longint;
Массив с фамилиями учащихся 11-го класса (всего 25 учащихся).
var Name: array [1 .. n] of string;
Типовые задачи обработки одномерных массивов
— Поиск элементов с заданными свойствами
— Поиск максимумов и минимумов
— Подсчёт элементов, удовлетворяющих условию
— Проверка массива на упорядоченность
— Удаление из массива элемента с индексом k
— Вставка в массив элемента на место с индексом k
— Перестановка элементов в обратном порядке
— Сортировка массива. Метод «пузырька»
Последовательный поиск в неупорядоченном массиве
Пример 3. Имеется массив A [1..n]. Найти элемент массива, равный p.
В алгоритмах поиска существует два возможных варианта окончания их работы: поиск может оказаться удачным – заданный элемент найден в массиве и определено его месторасположение, либо поиск может оказаться неудачным – необходимого элемента в данном объёме информации нет.
Возможный алгоритм решения:
1. Установить i = 1.
2. Если A [i] = p, алгоритм завершил работу успешно.
3. Увеличить i на 1.
4. Если i ≤ n, то перейти к шагу 2. В противном случае алгоритм завершил работу безуспешно.
var A: array [1..n] of integer;
i, p: integer;
begin
writeln (‘Ввод значений элементов массива:’);
for i := 1 to n do
read (A[i]);
write (‘ Ввод p: ‘);
readln (p);
while (i<=n) and (A[i]<>p) do
i:=i+1;
if i=n+1 then writeln (‘ Искомого элемента в массиве нет ‘)
else writeln (‘ Искомый элемент A[‘, i, ‘] = ‘, A[i])
end.
Поиск максимумов и минимумов
Пример 4. Имеется массив A [1..n]. Найти элемент массива с наименьшим значением.
Алгоритм поиска элемента с наименьшим значением в неупорядоченном массиве:
1. Установить значение текущего минимума равным первому исследуемому элементу.
2. Установить счетчик равным 2.
3. Если исследованы ещё не все элементы (i<=n), то перейти к шагу 4, иначе алгоритм окончен (минимальный элемент равен m in ).
4. Если рассматриваемый элемент меньше, чем текущий минимум, то минимуму присвоить значение текущего элемента.
5. Перейти к следующему элементу (увеличить i на единицу).
6. Перейти к шагу 3 .
Программа :
const n=5;
var A: array [1..n] of integer;
i, min: integer;
writeln (‘ Ввод значений элементов массива :’);
for i := 1 to n do
read (A[i]);
while (i<=n) do
begin
if A[i] < min then min := A[i];
end ;
writeln (‘ Минимум =’, min)
end.
Подсчёт элементов массива, удовлетворяющих некоторому условию
Зачастую бывает важно выяснить, сколько элементов, обладающих определённым свойством, содержится в массиве.
Пример 5. Имеется массив A [1..n]. Подсчитать количество элементов массива кратных некоторому числу p .
Алгоритм решения :
1. Присвоить нулевое значение переменной (счётчику), введённой для подсчёта количества элементов, удовлетворяющих заданному условию.
2. Организовать просмотр всех элементов массива: если просматриваемый элемент удовлетворяет заданному условию, значение счётчика увеличивать на 1.
Программа :
const n=5;
var A: array [1..n] of integer;
i, p, k: integer;
writeln (‘Ввод значений элементов массива:’);
for i := 1 to n do
read (A[i]);
writeln (‘ Ввод числа р :’);
readln (p);
for i := 1 to n do
if A[i] mod p = 0 then k := k + 1;
writeln (‘k=’, k)
end.
Проверка массива на упорядоченность
Пример 7. Имеется массив A [1..n]. Определить, упорядочены ли элементы массива по неубыванию, т. е. каждый элемент массива с 1-го по (n – 1)-й не больше последующего.
Алгоритм решения
Самый простой путь решения этой задачи – проверить, есть ли в массиве такие пары элементов, что A [i] > A [i + 1]. Если подобные пары элементов есть, то массив не упорядочен по неубыванию, а если таких пар нет, то – упорядочен.
В программе будем использовать логическую переменную flag:
• если flag = true, то массив упорядочен;
• если flag = false, то массив неупорядочен.
Программа :
const n=5;
var A: array [1..n] of integer;
i: integer; flag: boolean;
writeln (‘Ввод значений элементов массива:’);
for i := 1 to n do
read (A[i]);
for i := 1 to n-1 do
if a[i]>a[i+1] then flag:=false;
if flag then writeln (‘ упорядочен ‘)
else writeln (‘ неупорядочен ‘)
Удаление из массива элемента с индексом k
Пример 8. Имеется массив a[1..n]. Удалить элемент с индексом k .
При удалении из массива любого из элементов размерность массива уменьшается на 1.
Мы видим, что элементы с индексами от 1 до k – 1 не изменились.
На место элемента с индексом k (6) переместился элемент, имевший индекс k + 1 (7), на место элемента с индексом k + 1 (8) переместился элемент, имевший индекс k + 2 (8) и т. д.
Фрагмент программы удаления из массива элемента с индексом k и последующим сдвигом всех расположенных справа от него элементов на одну позицию влево имеет вид:
for i := k to n-1 do
A[i] := A[i+1];
Программа :
const n=10;
var A: array [1..n] of integer;
i, k: integer;
writeln (‘ Ввод значений элементов массива :’);
for i := 1 to n do
read (a[i]);
write (‘ Ввод индекса k: ‘);
readln (k);
for i := k to n-1
do A[i] := A[i+1];
writeln(‘ Массив после обработки :’);
for i := 1 to n -1 do
write (A[i], ‘ ‘)
end.
Вставка элемента на место с индексом k
Пример 9. Добавить в массив элемент Х на место с индексом k .
При вставке в массив ещё одного элемента размерность массива увеличивается на 1. Это надо учесть при описании массива.
Элементы с индексами от 1 до k – 1 не изменились.
На место элемента с индексом k (6) должен переместиться элемент, имевший индекс k + 1 (7), на место элемента с индексом k + 1 (8) –элемент, имевший индекс k + 2 (8) и т. д.
Поскольку при присваивании нового значения элементу старое пропадает, замену надо производить с конца. После чего заменить значение элемента с индексом k .
for i :=n downto k+1 do A[i] := A[i-1];
Программа :
const n=10;
var A: array [1..n] of integer;
i, k, X: integer;
begin
writeln (‘ Ввод значений элементов массива :’);
for i := 1 to n-1 do
read (A[i]);
write (‘ Ввод индекса k: ‘); readln (k);
write (‘Ввод числа Х: ‘); readln (X);
for i:=n downto k+1 do
A[i] := A[i-1];
A[k] := X;
writeln(‘Массив после обработки: ‘ );
for i:=1 to n do
write (A[i], ‘ ‘)
Перестановка всех элементов массива в обратном порядке
Пример 10. Имеется массив A [1..n].
Перевернуть его, т.е. что поменять местами 1-й и последний элементы, 2-й и предпоследний и т. д.
В общем случае, меняются местами элементы A [i] и A [ n – i + 1 ].
Вспомним. как можно произвести обмен значений между двумя переменными. Самый простой вариант – использование вспомогательной переменной:
Фрагмент программы по перестановке в обратном порядке всех элементов массива:
for i := 1 to n div 2 do
begin
R := A[i];
A[i] := A[n-i+1];
A[n-i+1] := R
Программа :
const n=7;
var A: array [1..n] of integer;
i, r: integer;
begin
writeln (‘ Ввод значений элементов массива :’);
for i := 1 to n do
read (A[i]);
for i := 1 to n div 2 do
begin
R := A[i];
A[i] := A[n-i+1];
A[n-i+1] := R
end;
writeln (‘ Массив после обработки :’);
for i := 1 to n do write (A[i], ‘ ‘)
end.
Сортировка массива
Сортировка – это распределение элементов массива в соответствии с определёнными правилами.
Существует 2 вида сортировки:
Сортировка методом «пузырька»
Своё название алгоритм получил благодаря следующей ассоциации: если сортировать этим алгоритмом массив по неубыванию, то максимальный элемент «тонет», а «лёгкие» элементы поднимаются на одну позицию к началу массива на каждом шаге алгоритма.
Пусть n– количество элементов в неупорядоченном массиве.
1. Поместим на место n-го элемента наибольший элемент массива. Для этого:
1) положим i = 1;
2) пока не обработана последняя пара элементов: сравниваем i-й и (i + 1)-й элементы массива; если A [i] > A [i + 1] (элементы расположены не по порядку), то меняем элементы местами; переходим к следующей паре элементов, сдвинувшись на один элемент вправо.
2. Повторяем пункт 1, каждый раз уменьшая размерность неупорядоченного массива на 1, до тех пор, пока не будет обработан массив из одной пары элементов (таким образом, на k-м просмотре будут сравниваться первые (n – k) элементов со своими соседями справа).
for k := n-1 downto 1 do
for i := 1 to k do
If A[i] > A[i+1] then
begin R := A[i]; A[i] := A[i+1]; A[i+1] := R end;
Сортировка выбором
Сортировка выбором (в порядке неубывания) осуществляется следующим образом:
1. В массиве выбирается минимальный элемент.
2. Минимальный и первый элементы меняются местами (первый элемент считается отсортированным).
3. В неотсортированной части массива снова выбирается минимальный элемент и меняется местами с первым неотсортированным элементом массива.
4. Действия, в пункте 3, повторяются с неотсортированными элементами массива до тех пор, пока не останется один неотсортированный элемент (его значение будет максимальным).
5. Программа :
Пример 10. Отсортировать массив A [1..n] по возрастанию.
Урок №75. Фиксированные массивы
Этот урок является продолжением предыдущего урока о массивах в языке C++.
Инициализация фиксированных массивов
Элементы массива обрабатываются так же, как и обычные переменные, поэтому они не инициализируются при создании. Одним из способов инициализации массива является присваивание значений каждому элементу поочерёдно:
Однако это не совсем удобно, особенно когда массив большой.
К счастью, язык C++ поддерживает более удобный способ инициализации массивов с помощью списка инициализаторов. Следующий пример эквивалентен примеру выше:
Если в этом списке инициализаторов больше, чем может содержать массив, то компилятор выдаст ошибку.
Однако, если в списке инициализаторов меньше, чем может содержать массив, то остальные элементы будут проинициализированы значением 0 . Например:
Результат выполнения программы:
Следовательно, чтобы инициализировать все элементы массива значением 0 , нужно:
В C++11 вместо этого мы можем воспользоваться синтаксисом uniform-инициализации:
Длина массива
Если вы инициализируете фиксированный массив с помощью списка инициализаторов, то компилятор может определить длину массива вместо вас, и вам уже не потребуется её объявлять.
Следующие две строки выполняют одно и то же:
Это не только сэкономит время, но также вам не придется обновлять длину массива, если вы захотите добавить или удалить элементы позже.
Массивы и перечисления
Одна из основных проблем при использовании массивов состоит в том, что целочисленные индексы не предоставляют никакой информации программисту об их значении. Рассмотрим класс из 5 учеников:
Кто представлен элементом testScores[3] ? Непонятно!
Это можно решить, используя перечисление, в котором перечислители сопоставляются каждому из возможных индексов массива:
Вот теперь понятно, что представляет собой каждый из элементов массива. Обратите внимание, добавлен дополнительный перечислитель с именем MAX_STUDENTS . Он используется во время объявления массива для гарантирования того, что массив имеет корректную длину (она должна быть на единицу больше самого большого индекса). Это полезно как для подсчета элементов, так и для возможности автоматического изменения длины массива, если добавить еще один перечислитель:
Обратите внимание, этот трюк работает только в том случае, если вы не изменяете значения перечислителей вручную!
Массивы и классы enum
Классы enum не имеют неявного преобразования в целочисленный тип, поэтому, если вы попробуете сделать следующее:
То получите ошибку от компилятора. Это можно решить, используя оператор static_cast для конвертации перечислителя в целое число:
Однако, это также не очень удобно, поэтому лучше использовать стандартное перечисление внутри пространства имен:
Передача массивов в функции
Хотя передача массива в функцию на первый взгляд выглядит так же, как передача обычной переменной, но «под капотом» C++ обрабатывает массивы несколько иначе.
Когда обычная переменная передается по значению, то C++ копирует значение аргумента в параметр функции. Поскольку параметр является копией, то изменение значения параметра не изменяет значение исходного аргумента.
Однако, поскольку копирование больших массивов — дело трудоёмкое, то C++ не копирует массив при его передаче в функцию. Вместо этого передается фактический массив. И здесь мы получаем побочный эффект, позволяющий функциям напрямую изменять значения элементов массива!
Следующий пример хорошо иллюстрирует эту концепцию:
Результат выполнения программы:
before passValue: 1
after passValue: 1
before passArray: 1 4 6 8 10
after passArray: 10 8 6 4 1
В примере, приведенном выше, значение переменной value не изменяется в функции main(), так как параметр value в функции passValue() был лишь копией фактической переменной value . Однако, поскольку массив в параметре функции passArray() является фактическим массивом, то passArray() напрямую изменяет значения его элементов!
Примечание: Если вы не хотите, чтобы функция изменяла значения элементов массива, переданного в нее в качестве параметра, то нужно сделать массив константным:
Оператор sizeof и массивы
Оператор sizeof можно использовать и с массивами: он возвращает общий размер массива (длина массива умножена на размер одного элемента) в байтах. Обратите внимание, из-за того, как C++ передает массивы в функции, следующая операция не будет корректно выполнена с массивами, переданными в функции:
Результат выполнения программы:
По этой причине будьте осторожны при использовании оператора sizeof с массивами!
Определение длины фиксированного массива
Чтобы определить длину фиксированного массива, поделите размер всего массива на размер одного элемента массива:
Результат выполнения программы:
The array has 8 elements
Как это работает? Во-первых, размер всего массива равен длине массива, умноженной на размер одного элемента. Формула: размер_массива = длина_массива * размер_одного_элемента .
Используя алгебру, мы можем изменить это уравнение: длина_массива = размер_массива / размер_одного_элемента . sizeof(array) — это размер массива, а sizeof(array [0]) — это размер одного элемента массива. Соответственно, длина_массива = sizeof(array) / sizeof(array[0]) . Обычно используется нулевой элемент в качестве элемента массива в уравнении, так как только он является единственным элементом, который гарантированно существует в массиве, независимо от его длины.
Это работает только если массив фиксированной длины, и вы выполняете эту операцию в той же функции, в которой объявлен массив.
Примечание: На следующих уроках мы будем использовать термин «длина» для обозначения общего количества элементов в массиве, и термин «размер», когда речь будет идти о байтах.
Индексирование массива вне диапазона
Помните, что массив длиной N содержит элементы от 0 до N-1 . Итак, что произойдет, если мы попытаемся получить доступ к индексу массива за пределами этого диапазона? Рассмотрим следующую программу:
Здесь наш массив имеет длину 5, но мы пытаемся записать значение в 6-й элемент (индекс 5).
Язык C++ не выполняет никаких проверок корректности вашего индекса. Таким образом, в вышеприведенном примере значение 14 будет помещено в ячейку памяти, где 6-й элемент существовал бы (если бы вообще был). Но, как вы уже догадались, это будет иметь свои последствия. Например, произойдет перезаписывание значения другой переменной или вообще сбой программы.
Хотя это происходит реже, но C++ также позволяет использовать отрицательный индекс, что тоже приведет к нежелательным результатам.
Правило: При использовании массивов убедитесь, что ваши индексы корректны и соответствуют диапазону вашего массива.
Задание №1
Объявите массив для хранения температуры (дробное число) каждого дня в году (всего 365 дней). Проинициализируйте массив значением 0.0 для каждого дня.
Ответ №1
Примечание: Если размер не является ограничением, то вместо типа float лучше использовать тип double.
Задание №2
Создайте перечисление со следующими перечислителями: chicken , lion , giraffe , elephant , duck и snake . Поместите перечисление в пространство имен. Объявите массив, где элементами будут эти перечислители и, используя список инициализаторов, инициализируйте каждый элемент соответствующим количеством лап определенного животного. В функции main() выведите количество ног у слона, используя перечислитель.
Ответ №2
Урок №74. Массивы
Комментариев: 19
2 задание действительно легче, чем в предыдущем итоговом тесте. Цикл for тут точно лишним не будет.
Задание 2, без перечисления
Лёгкие задания у меня получаются.
В первом задании написано: Объявите массив для хранения температуры (дробное число) каждого дня в году (всего 365 дней).
Но в ответе на первое задание указано 366 дней: double temperature[365]
Вед в уроке говорилось что массив начинается с нуля. Или я что-то не понял?
При объявлении массива в квадратных скобках указывается общее кол-во его ячеек, а вот уже сами ячейки нумеруются с нуля
По поводу выхода за границы массива:
1) В этом случае, как я понимаю, процесс может испортить только свою память? Порча (или чтение) памяти других процессов тут невозможно? Иначе это просто катастрофа.
2) Если (1) верно — это обеспечено самой операционкой (защищённая модель памяти и т. д.) или чем-то ещё? И будет ли безопасно на других ОС (не винда) и платформах?
В сети ясного ответа на это не нашёл.
Насколько я помню из видеокурсов по углубленному изучению языка С, то выделение памяти отдаётся на откуп ОС.
Любая программа (компилятор тоже программа) при запуске запрашивает у ОС память. Как правило, ОС выделяют не блок памяти под всю программу, а участками, поэтому ни о какой защищенной модели памяти здесь речи не идёт.
Если ваш выход за массив залез в вашу же программу — вам повезло.
Механизм защиты памяти (МЗП) используется операционной системой (ОС) и поддерживается процессорами серии i86 и старше.
В зависимости от размера программы, ОС выбирает способ работы с памятью: сегментный (обычно не более 64 кБ) или страничный (обычно по 4кБ). ОС выделяет память с выровненными границами, поэтому рекомендуется, чтобы данные вашей программы в памяти тоже были выровнены (немного касались этого вопроса Урок №61. Структуры -> Размер структур https://ravesli.com/urok-61-struktury/).
МЗП не позволит Вам "залесть" в чужую область памяти, т. е., если вам позволит уровень приоритетов (доступа ОС), можно прочитать данные другого процесса из другого доступного участка памяти, но не записать. Вы можете, что угодно делать только со своей выделенной областью памяти.
Но помните, что при вызове функций или передачи управления выполнения программы, результат записи за пределами индекса массива может привести к коллапсу, так как здесь могут находится данные вашей программы или, что хуже всего, сама Ваша исполняемая программа.
После всего — второе задание оказалось простым в исполнении, только текстом не приукрасил.
Немного не понял первое — почему double temp[365] = <0.0>.
Я использовал double temp[365] = < >.
В том и ином случаи "0".
Не подскажите, зачем нужно писать
= <0.0>, если все элементы по умолчанию, без присваивания значений равны 0.
нельзя ли просто написать
duoble god[365]; например?
или это будет неправильно?
"Трюк: Чтобы определить длину фиксированного массива — разделите размер всего массива на размер одного элемента массива:"
В русском языке принято употреблять слово "размер" массива, когда речь идет о количестве элементов в нем? Разве "длина" в этом случае не будет более уместным термином? Размер больше ассоциируется с количеством байт.
Вместо "трюка" — уравнения с sizeof, на мой взгляд, гораздо удобнее использовать более компактную встроенную функцию:
Она возвращает количество элементов в контейнере (массивы, vector, string)
Должна подключаться отдельным заголовком