Как создать N размер массива задаваемый пользователем PASCAL
Это можно сделать с помощью динамических массивов. Например:
program p1; var a: array of integer; n: integer; begin readln(n); // вводим длину массива SetLength(a, n); // устанавливаем новую длину массива writeln(length(a)); // показываем длину массива end.
P.S. Для написания кода использовался PascalABC
Отслеживать
ответ дан 22 окт 2020 в 15:19
SurfaceStack SurfaceStack
865 6 6 серебряных знаков 23 23 бронзовых знака
-
Важное на Мете
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
lang-pascal
Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.9.3159
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
3. Массивы в Pascal
Массив — это множество величин, имеющих одно и то же имя и номер по порядку.
В математике подобное называется последовательностью, можно сказать, что последовательность — это одномерный массив. В математической последовательности каждый следующий элемент записывается по определённому правилу (формуле), в одномерном массиве могут быть произвольные числа (либо символы, либо слова).
Размер массива — это количество элементов в массиве.
Размерность массива определяется количеством входящих в него индексов.
Массивы бывают: одномерные, двумерные, многомерные.
Индекс определяет положение элемента в массиве (нумерация начинается с \(1\)).

Рис. \(1\). Индекс и значение массива
Примеры массивов
Массивы в PascalABC.NET
В PascalABC.NET рекомендуется использовать динамические массивы. В отличие от статических, они имеют огромное количество методов и операций, просты в создании, заполнении и выводе.
Описание и выделение памяти
Динамический массив описывается так:
begin var a: array of integer; end.
Память под динамический массив a выделяется в момент работы программы:
begin var a: array of integer; var n := ReadInteger; a := new integer[n]; end.
Здесь — первое преимущество динамических массивов — в переменной a может храниться массив любого размера, память выделяется в процессе работы программы. Кроме того, выделенная память гарантированно автоматически заполняется нулевыми значениями.
Можно совместить описание и выделение памяти — тип динамического массива выводится автоматически:
begin var n := ReadInteger; var a := new integer[n]; end.
Обычно в PascalABC.NET совмещают описание динамического массива, выделение памяти и заполнение значениями. Самый простой способ — заполнить n нулями:
begin var n := ReadInteger; var a := |0| * n; end.
Индексация в динамических массивах и использование статических массивов
Динамические массивы индексируются с нуля — это эффективно. В качестве индексов в динамических массивах могут выступать только целые.
Статические массивы тем не менее иногда удобно использовать — в задачах, где индексы либо символьные, либо по-существу начинаются не с нуля. Например, для подсчёта количества слов на каждую букву может использоваться стаический массив
var a := array ['a'..'z'] of integer;
Заполнение статических массивов — увы — производится в цикле. Кроме того, они не помнят свою длину и передача таких массивов в качестве параметров подпрограмм связана с техническими сложностями 40-летней давности, не нужными начинающим.
Простейшее заполнение
Важную роль играют функции заполнения динамических массивов. Перед заполнением они выделяют для массива память, поэтому в одной строке можно совмещать описание, выделение памяти и заполнение.
Простейшее заполнение — набором значений:
var a := |1,3,3,7,9|;
Заполнение диапазоном целых или символьных значений делается с использованием функции Arr:
var a := Arr(1..9); var b := Arr('a'..'z');
Заполнение определённым значением осуществляется с помощью операции умножения массива на число:
begin var n := ReadInteger; var a := |0| * n; // массив из n нулей end.
Для заполнения можно также использовать функцию ArrFill:
begin var n := ReadInteger; var a := ArrFill(n,0); // массив из n нулей end.
Для заполнения массива случайными значениями следует использовать
begin var n := ReadInteger; var a := ArrRandomInteger(n); // по умолчанию значения от 0 до 100 var a1 := ArrRandomInteger(n,1,10); // случайные от 1 до 10 var r := ArrRandomReal(n); // по умолчанию значения от 0 до 10 var r1 := ArrRandomReal(n,2,5); // случайные вещественные от 2 до 5 end.
Не рекомендуется использовать алгоритм для заполнения массива случайными в каждой задаче:
begin var n := ReadInteger; var a := new integer[n]; for var i:=0 to n-1 do a[i] := Random(0,100); end.
Повторять этот текст в каждой задаче — странно. Для этого есть стандартные функции.
Ввод и вывод элементов массива
Для ввода элементов массива базовых типов используются функции
begin var n := ReadInteger; var a := ReadArrInteger(n); var r := ReadArrReal(n); var s := ReadArrString(n); // . end.
Стандартная процедура вывода Write или Print выводит значения в массиве в квадратных скобках черезх запятую:
begin var a := Arr(1..9); Print(a); // [1,2,3,4,5,6,7,8,9] end.
Однако лучше всего для вывода воспользоваться методом Print, выводящим все значения в массиве через пробел:
begin var a := Arr(1..9); a.Print; // 1 2 3 4 5 6 7 8 9 end.
Не рекомендуется вводить и выводить элементы массива в цикле
begin var n := ReadInteger; var a := new integer[n]; for var i:=0 to n-1 do a[i] := ReadInteger; end.
Повторять этот текст в каждой задаче — странно. Для этого есть стандартные функции.
Циклы по массиву
Для обработки элементов массива используются следующие циклы:
-
Цикл for по индексам (если требуется менять элементв или нужна информация об индексах)
for var i:=0 to a.Length-1 do a[i] *= 2;
var sum := 0; foreach var x in a do sum += x;
foreach var i in a.Indices do a[i] += 2;
var (K,L) := ReadInteger2; foreach var i in K..L do a[i] := 777;
Пример. Найти количество чётных элементов, стоящих на чётных местах
begin var a := ArrRandomInteger(10); a.Println; var count := 0; foreach var i in a.Indices do if i.IsEven and a[i].IsEven then count += 1; Print(count); end.
Методы массива
Массивы содержат большое количество стандартных методов:
a.Length - длина массива a.Min - минимальный элемент в массиве a.Max - максимальный элемент в массиве a.IndexMin - индекс первого минимального элемента в массиве a.IndexMax - индекс первого максимального элемента в массиве a.Sum - сумма элементов в числовом массиве a.Product - произведение элементов в числовом массиве a.Average - среднее элементов в числовом массиве a.First - первый элемент в массиве a.Last - последний элемент в массиве a.IndexOf(x) - индекс первого значения x или -1 если не найдено a.Replace(x,y) - заменить в массиве все значения x на y
Кроме того, доступны процедуры
Sort(a) - сортировка элементов по возрастанию SortDescending(a) - сортировка элементов по убыванию Reverse(a) - инвертирование элементов массива
Методика. Обращаем внимание, что в методических целях естественно рассказывать, как эти алгоритмы устроены “внутри”. Но потом следует пользоваться стандартными алгоритмами, а не заставлять учеников во всех задачах использовать рукописные сортировки или рукописный поиск минимума. Например, рекомендуется показать, как накопить сумму элементов массива:
begin var a := ArrRandomInteger(10); a.Println; var sum := 0; foreach var x in a do sum += x; Print(sum); end.
Здесь следует обратить внимание, что этот алгоритм может быть легко модифицирован в алгоритм нахождения суммы элементов по условию: например, всех чётных элементов:
begin var a := ArrRandomInteger(10); a.Println; var sum := 0; foreach var x in a do if x.IsEven then sum += x; Print(sum); end.
Отметим, что заполнение случайными и вывод — это технические части программы, которые делаются в PascalABC.NET в одну строку, позволяя концентрироваться на алгоритме.
Если условие надо накладывать на индексы, то в этом случае (и только в этом случае) следует использовать цикл for по индексам:
begin var a := ArrRandomInteger(10); a.Println; var sum := 0; for var i:=0 to a.Length-1 do if i.IsEven then sum += a[i]; Print(sum); end.
Для нахождения суммы без условия необходимо использовать стандартный метод a.Sum:
begin var a := ArrRandomInteger(10); a.Println; Print(a.Sum); end.
Отметим также, что для поиска суммы по условию также имеется короткая однострочная запись. Она требует использование стандартного метода Where с параметром, являющимся лямбда-выражением. Лямбда-выражения мы будем рассматривать далее:
begin var a := ArrRandomInteger(10); a.Println; Print(a.Where(x -> x.IsEven).Sum); end.
Методика. Поскольку данная запись использована здесь впервые, обращаем внимание на её высокую универсальность: алгоритмы фильтрации и поиска суммы не слиты в один алгоритм, а используются порознь один за другим, что позволяет:
- Лучше читать код (потому что он записан компактно и методами с понятными и очевидными названиями)
- Лучше модифицировать код
- Решать более сложные и более прикладные задачи за одно и то же время урока
Далее лямбда-выражения объясняются подробно и тщательно и используются повсеместно.
Операции с массивами
x in a - возвращает true если значение x содержится в a a1 + a2 - возвращает массив, образованный слиянием массивов a1 и a2 a1 * n - возвращает массив, состоящий из n раз повторенных значений массива a
Изменение размера динамического массива
Если в процессе работы программы требуется чтобы динамический массив менял свой размер, то следует … пользоваться типом List ! Это — динамический массив с возможностью эффективного измненения размера и рядом дополнительных методов. Основным является методы Add — добавить в конец:
begin var l := new Listinteger>; l.Add(1); l.Add(3); l.Add(5); l.Print end.
Для первоначального заполнения списков List используется короткая фунеция Lst:
begin var l := Lst(1,3,5); l.Print end.
При необходимости список List можно преобразовать к динамическому массиву, вызвав метод .ToArray:
begin var l := Lst(1,3,5); var a := l.ToArray; end.
Большинство методов, которые имеются в массивах, есть и в списках List. Поэтому выбор типа List или array of для контейнера при решении задач определяется тем, будет ли данный контейнер расширяться по ходу работы программы.
©2023 PascalABCNET Team. All rights reserved.
Page last updated: 19.12.2020
Site last generated: Dec 20, 2023
Динамические массивы
Тип динамического массива конструируется следующим образом:
array of тип элементов (одномерный массив)
array [,] of тип элементов (двумерный массив)
и т.д.
Переменная типа динамический массив представляет собой ссылку. Поэтому динамический массив нуждается в инициализации (выделении памяти под элементы).
Выделение памяти под динамический массив
Для выделения памяти под динамический массив используется два способа. Первый способ использует операцию new в стиле вызова конструктора класса:
var
a: array of integer;
b: array [,] of real;
begin
a := new integer[5];
b := new real[4,3];
end.
Данный способ хорош тем, что позволяет совместить описание массива и выделение под него памяти:
var
a: array of integer := new integer[5];
b: array [,] of real := new real[4,3];
Описание типа можно при этом опускать — тип автовыводится:
Второй способ выделения памяти под динамический массив использует стандартную процедуру SetLength :
Элементы массива при этом заполняются значениями по умолчанию.
Процедура SetLength обладает тем преимуществом, что при ее повторном вызове старое содержимое массива сохраняется.
Инициализация динамического массива
Можно инициализировать динамический массив при выделении под него память операцией new:
Инициализацию динамического массива в момент описания можно проводить в сокращенной форме:
var
a: array of integer := (1,2,3);
b: array [,] of real := ((1,2,3),(4,5,6),(7,8,9),(0,1,2));
c: array of array of integer := ((1,2,3),(4,5),(6,7,8));
При этом происходит выделение памяти под указанное справа количество элементов.
Инициализация одномерного массива проще всего осуществляется стандартными функциями Seq. которые выделяют память нужного размера и заполняют массив указанными значениями:
var a := Arr(1,3,5,7,8); // array of integer
var s := Arr(‘Иванов’,’Петров’,’Сидоров’); // array of string
var b := ArrFill(777,5); // b = [777,777,777,777,777]
var r := ArrRandom(10); // заполнение 10 случайными целыми в диапазоне от 0 до 99
В таком же стиле можно инициализировать массивы массивов:
var a := Arr(Arr(1,3,5),Arr(7,8),Arr(5,6)); // array of array of integer
Длина динамического массива
Динамический массив помнит свою длину (n-мерный динамический массив помнит длину по каждой размерности). Длина массива (количество элементов в нем) возвращается стандартной функцией Length или свойством Length :
Для многомерных массивов длина по каждой размерности возвращается стандартной функцией Length с двумя параметрами или методом GetLength(i) :
Ввод динамического массива
После выделения памяти ввод динамического массива можно осуществлять традиционно в цикле:
for var i:=0 to a.Length-1 do
read(a[i]);
Ввод динамического массива можно осуществлять с помощью стандартной функции ReadSeqInteger:
var a := ReadSeqInteger(10);
При этом под динамический массив выделяется память нужного размера.
Вывод динамического массива
Процедура write выводит динамический массив, заключая элементы в квадратные скобки и разделяя их запятыми:
var a := Arr(1,3,5,7,9);
writeln(a); // [1,3,5,7,9]
n-мерный динамический массив выводится так, что каждая размерность заключается в квадратные скобки:.
var m := new integer[3,3] ((1,2,3),(4,5,6),(7,8,9));
writeln(m); // [[1,2,3],[4,5,6],[7,8,9]]
Динамический массив можно выводить также методом расширения Print или Println:
При этом элементы по умолчанию разделяются пробелами, но можно это изменить, задав параметр Print, являющийся разделителем элементов. Например:
выводит каждый элемент на отдельной строке.
Массивы массивов
Если объявлен массив массивов
var с: array of array of integer;
то его инициализацию можно провести только с помощью SetLength :
SetLength(с,5);
for i := 0 to 4 do
SetLength(c[i],3);
Для инициализации такого массива с помощью new следует ввести имя типа для array of integer :
type IntArray = array of integer;
var с: array of IntArray;
.
c := new IntArray[5];
for i := 0 to 4 do
c[i] := new integer[3];
Инициализацию массива массивов можно также проводить в сокращенной форме:
var
c: array of array of integer := ((1,2,3),(4,5),(6,7,8));
Присваивание динамических массивов
Динамические массивы одного типа можно присваивать друг другу, при этом обе переменные-ссылки будут указывать на одну память:
var a1: array of integer;
var a2: array of integer;
a1 := a2;
Следует обратить внимание, что для динамических массивов принята структурная эквивалентность типов: можно присваивать друг другу и передавать в качестве параметров подпрограмм динамические массивы, совпадающие по структуре.
Чтобы одному динамическому массиву присвоить копию другого массива, следует воспользоваться стандартной функцией Copy :
Передача динамического массива в подпрограмму
Динамический массив обычно передается в подпрограмму по значению, т.к. сама переменная уже является ссылкой:
procedure Squares(a: array of integer);
begin
for var i:=0 to a.Length-1 do
a[i] := Sqr(a[i]);
end;
begin
var a := Arr(1,3,5,7,9);
Squares(a);
end.
Динамический массив передается по ссылке только в одном случае: если он создается или пересоздается внутри подпрограммы. В частности, это необходимо делать если для динамического масива внутри подпрограммы вызывается SetLength:
procedure Add(var a: array of integer; x: integer);
begin
SetLength(a,a.Length+1);
a[a.Length-1] := x;
end;
begin
var a := Arr(1,3,5,7,9);
Add(a,666);
writeln(a);
end.