9 / 9 / 2
Регистрация: 27.01.2010
Сообщений: 63

Динамические массивы в Delphi

27.01.2010, 19:41. Показов 97711. Ответов 3
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
объясните пожалуйста про массив массивов...задается он таким образом.


Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
program v5;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils;
var a:array of array [1..1] of integer; i,j,n,m:integer;
begin
{ TODO -oUser -cConsole Main : Insert code here }
writeln('vvedite razmer massiva NxM');
 
readln (n);
readln (m);
setlength(a,n);
randomize;
  for i:=1 to n do begin
    for J:=1 to m do begin
    a[i,j]:=random(21)-10;
    end;
  end;
 
 
 
  for i:=1 to n do begin
    for J:=1 to m do begin
    write(a[i,j]:3);
    end;
  writeln;
  writeln;
  end;
readln;
end.
вроде нормально создается массив,только с самим массивом чтото нето. вроде я его заполнял рандомом,а все элементы на побочных диагоналях одинаковые....некоторые действия с этими массивами выдают ложные результаты,(проверял тоже самое с обычным массивом-все нормально).

если кто знает подскажите плиз если есть способ другой способ задания двумерного массива с клавиатуры
(мне уже говорили про setlength,это функция только для одномерных массивов.)
заранее спасибо.
5
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
27.01.2010, 19:41
Ответы с готовыми решениями:

Динамические массивы в Delphi
Доброго времени суток! Можете написать простенький пример использования динамического массива Только не всяких там SetLength и т.д. Мне...

Динамические массивы в Delphi
Такая вот незадача, пишу программу, которая должна находить в текстовом файле, в котором программка из Delphi, все поля классов, и...

Статические массивы,Динамические массивы,строки
1)Создать двумерный массив A(N,M) целых положительных и отрицательных чисел с помощью функции Random. Найти произведение всех четных...

3
 Аватар для Mawrat
13113 / 5894 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
27.01.2010, 20:23
Delphi
1
a:array of array [1..1] of integer;
Здесь объявлен динамический массив каждым элементом которого должен являться статический массив, состоящий из одного элемента. Это не то что тебе надо. Т. к., судя по коду, вторая размерность массива тоже должна задаваться во время выполнения программы - через переменную "m".
Объявить надо так:
Delphi
1
2
var
  a : array of array of integer;
Далее так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var a:array of array of integer; i,j,n,m:integer;
begin
{ TODO -oUser -cConsole Main : Insert code here }
writeln('vvedite razmer massiva NxM');
 
readln (n);
readln (m);
setlength(a, n, m);
randomize;
  for i:=1 to n do begin
    for J:=1 to m do begin
    a[i,j]:=random(21)-10;
    end;
  end;
...
8
9 / 9 / 2
Регистрация: 27.01.2010
Сообщений: 63
27.01.2010, 22:50  [ТС]
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
program Project1;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils;
var a:array of array of integer; i,j,n,m:integer;
begin
{ TODO -oUser -cConsole Main : Insert code here }
writeln('vvedite razmer massiva NxM');
 
readln (n);
readln (m);
setlength(a, n, m);
randomize;
  for i:=1 to n do begin
    for J:=1 to m do begin
    a[i,j]:=random(21)-10;
    end;
  end;
 
   for i:=1 to n do begin
    for J:=1 to m do begin
    write(a[i,j]:5);
    end;
  end;
 
 
 
  readln;
  readln;
 
  end.

только что попытался его запустить ,он дальше рандома не проходит.


Delphi
1
2
3
readln (n);
readln (m);
setlength(a, n, m);
и насколько я знаю из инструкции к проге, что функция setlength для задавания одномерных массивов.
т.е. там должна быть только одна переменная....я попытался так:
Delphi
1
2
3
4
readln (n);
readln (m);
setlength(a, n);
setlength(a, m);
единственное что уешило,что когда я вместо [1..1] поставил [1..10] начали рандомится разные числа,но я ещё не проверял на выполнения задач)))
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
program Project1;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils;
var a:array of array [COLOR="Sienna"][1..10][/COLOR] of integer; i,j,n,m:integer;
begin
{ TODO -oUser -cConsole Main : Insert code here }
writeln('vvedite razmer massiva NxM');
readln (n);
readln (m);
setlength(a,n);
randomize;
  for i:=1 to n do begin
    for J:=1 to m do begin
    a[i,j]:=random(21)-10;
    end;
  end;
 
   for i:=1 to n do begin
    for J:=1 to m do begin
    write(a[i,j]:5);
    end;writeln;writeln;
  end;
  readln;
  end.
может есть какойто другой способ задания двумерного массива с клавиатуры.....?))

ещё раз,заранее спасибо за помощь)))
1
 Аватар для Mawrat
13113 / 5894 / 1708
Регистрация: 19.09.2009
Сообщений: 8,809
28.01.2010, 11:46
Да - там ещё границы изменения индексов неверно заданы.
Сейчас расскажу...
Вариант правильного кода выглядит так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
program Project1;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils, Windows;
 
var
  a : array of array of integer;
  i, j, n, m : integer;
begin
  {Переключение окна консоли на кодовую страницу CP1251 (Win-1251).
  Если после переключения русские буквы показываются неверно,
  следует открыть системное меню консольного окна - щелчком мыши в левом
  верхнем углу окна консоли и выбрать:
  Свойства - закладка "Шрифт" - выбрать шрифт: "Lucida Console".}
  SetConsoleCP(1251);
  SetConsoleOutputCP(1251);
  
  Writeln('Введите размер массива NxM:');
  Write('N = ');
  Readln(n);
  Write('M = ');
  Readln(m);
  SetLength(a, n, m);
 
  Randomize;
  for i := 0 to n - 1 do
    for J := 0 to m - 1 do
      a[i,j] := Random(21)-10;
 
  for i := 0 to n - 1 do begin
    for j := 0 to m - 1 do
      Write(a[i,j]:5);
    Writeln;
  end;
  
  Readln;
end.
В динамических массивах нижняя граница индекса всегда равна нулю. А верхняя граница равна длине массива в данном измерении минус единица.
Т. е., т. к. n и m задают длину массива по первому и второму измерениям, то цикл по всем элементам массива должен быть организован так:
Delphi
1
2
3
4
5
for i := 0 to n - 1 do begin
  for j := 0 to m - 1 do begin
    ...
  end;
end;
Т. е. индексы i и j меняются от нуля до (длина минус один). Есть специальные функции, которые определяют длину массива, нижнее и верхнее значения индекса. Это функции Length(), Low(), High().
Они применимы для любых массивов - для статических и динамических. Применяя функцию High(), код можно переписать так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
program Project1;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils, Windows;
 
var
  a : array of array of integer;
  i, j, n, m : integer;
begin
  {Переключение окна консоли на кодовую страницу CP1251 (Win-1251).
  Если после переключения русские буквы показываются неверно,
  следует открыть системное меню консольного окна - щелчком мыши в левом
  верхнем углу окна консоли и выбрать:
  Свойства - закладка "Шрифт" - выбрать шрифт: "Lucida Console".}
  SetConsoleCP(1251);
  SetConsoleOutputCP(1251);
  
  Writeln('Введите размер массива NxM:');
  Write('N = ');
  Readln(n);
  Write('M = ');
  Readln(m);
  SetLength(a, n, m);
 
  Randomize;
  for i := 0 to High(a) do
    for j := 0 to High(a[i]) do
      a[i,j] := Random(21)-10;
 
  for i := 0 to High(a) do begin
    for j := 0 to High(a[i]) do
      Write(a[i,j]:5);
    Writeln;
  end;
  
  Readln;
end.
Использовать функцию Low() можно было бы так:
Delphi
1
2
3
4
5
for i := Low(a) to High(a) do begin
  for j := Low(a[i]) to High(a[i]) do begin
    ...
  end;
end;
Для динамических массивов Low(a) всегда = 0. А High(a) = Length(a) - 1. Надо отметить, что таким образом, если Length(a) = 0, то High(a) = -1.
Теперь надо пояснить код: High(a) и High(a[i]). High(a) - возвращает верхнее значение индекса в первом измерении массива "a". А High(a[i]) - вернёт верхнее значение индекса во втором измерении для i-й строки. Дело в том, что динамический массив устроен не так как статический. И он может быть непрямоугольной формы. Т. е. например массив "a" может быть таким:
Code
1
2
3
4
1, 2, 3, 4, 5, 6, 7
1, 2, 3, 4, 5, 6, 7
1, 2, 3, 4, 5, 6, 7
1, 2, 3, 4, 5, 6, 7
Память под такой массив выделяется так: SetLength(a, 4, 7);
Но массив "a" может быть и непрямоугольным:
Code
1
2
3
4
1, 2, 3
1, 2, 3, 4, 5, 6, 7
1, 2
1, 2, 3, 4, 5
Память для такого массива выделяется так:
Delphi
1
2
3
4
5
SetLength(a, 4);
SetLength(a[0], 3);
SetLength(a[1], 7);
SetLength(a[2], 2);
SetLength(a[3], 5);
В данном случае:
Code
1
2
3
4
5
Length(a) = 4
Length(a[0]) = 3
Length(a[1]) = 7
Length(a[2]) = 2
Length(a[3]) = 5
Поэтому, грамотно цикл по элементам динамического массива строится так:
Delphi
1
2
3
4
5
for i := 0 to High(a) do begin
  for j := 0 to High(a[i]) do begin
    ...
  end;
end;
Если заведомо известно, что динамичский массив прямоугольный, то можно было бы написать так:
Delphi
1
2
3
4
5
for i := 0 to High(a) do begin
  for j := 0 to High(a[0]) do begin
    ...
  end;
end;
Т. к. длина всех строк одинакова и равна длине первой строки (первая строка массива имеет индекс равный нулю). Тем не менее лучше всё же использовать универсальную запись High(a[i]).
Для прямоугольного динамического массива память можно выделить двумя способами:
Delphi
1
2
3
4
5
6
7
//Первый способ. Он самый удобный.
SetLength(a, n, m);
 
//Второй способ.
SetLength(a, n);
for i := 0 to n - 1 do
  SetLength(a[i], m);
---
Таким образом каждый из элементов a[i] представляет собой самостоятельный одномерный динамический массив. Поэтому многомерный дин. массив "a" это на самом деле сборка из нескольких одномерных дин. массивов.
---
Одномерный дин. массив, упрощённо, представляет собой переменную типа указатель (занимает в памяти 4 байта), в которой записано целое число типа Integer - это число является адресом байта в памяти, начиная с которого расположены элементы массива.
---
Предположим память для массива "а" выделена так:
SetLength(a, 3, 5);
Физически такой массив будет из себя представлять следующее.
Это будет один одномерный динамический массив "а", который содержит указатель на область памяти в которой расположены три элемена. Каждый из этих трёх элементов в свою очередь представляет собой отдельный одномерный динамический массив - т. е. эти элементы тоже являются указателями на некие области в памяти, в каждой из которых располагаются по 5 элементов типа Integer, т. к. массив объявлен так:
a : array of array of Integer;
---
Если интересно, устройство динамического массива можно рассмотреть подробно. Следует рассмотреть случай одномерного динамического массива. Т. к. как уже говорилось, многомерные динамические массивы это сборки из одномерных дин. массивов.
И так, физически переменная типа динамический массив представляет собой переменную размером 4 байта, которая является указателем на область памяти, где расположены элементы массива.
Delphi
1
2
3
4
var
  Arr : array of Double;
begin
  SetLength(Arr, 5);
Здесь объявлен одномерный динамический массив. Когда выполняется команда SetLength(Arr, 5); происходит следующее:
1. Выделяется блок памяти размер которого равен:
3 * SizeOf(Integer) + Length(Arr) * SizeOf(Double) = 3 * 4 + 5 * 8 = 12 + 40 = 52 байта.
Кстати, я проверил - на самом деле памяти выделяется немного больше - больше на 2 байта, т. е. в этом примере будет не 52, а 54 байта. Для чего нужны дополнительные 2 байта - не знаю. Но это не суть важно.
2. В первые 4 байта выделенного блока (это байты со смещением 0, 1, 2, 3) записывается размер выделенного блока - это число = 54 = 52 + те самые 2 дополнительных байта.
3. В следующие 4 байта (смещение: 4, 5, 6, 7) записывается количество ссылок на данную структуру. В начале будем иметь здесь число = 1.
4. В следующие 4 байта (смещение: 8, 9, 10, 11) записывается длина массива измеряемая в количестве элементов типа Double - согласно объявлению массива. Т. е. здесь будет записано число = 5.
5. После этого адрес 13-го байта (его смещение = 12) будет записан в переменную Arr. Это адрес байта, начиная с которого расположен первый элемент массива - Arr[0].
Следующий код исследует физическое устройство одномерного дин. массива:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
procedure TForm1.Button1Click(Sender: TObject);
var
  Arr : array of Double;
  PBase, PInt : ^Integer;
  PDbl : ^Double;
  Size, RefCount, ArrLength : Integer;
  El_0, El_1, El_2, El_3, El_4 : Double;
begin
  SetLength(Arr, 5);
  Arr[0] := 0;
  Arr[1] := 1;
  Arr[2] := 2;
  Arr[3] := 3;
  Arr[4] := 4;
 
  PInt := Pointer(Arr);
  PBase := Pointer( Integer(PInt) - 12 );
 
  PInt := Pointer( Integer(PBase) + 0 );
  Size := PInt^;
 
  PInt := Pointer( Integer(PBase) + 4 );
  RefCount := PInt^;
 
  PInt := Pointer( Integer(PBase) + 8 );
  ArrLength := PInt^;
 
  PDbl := Pointer( Integer(PBase) + 12 + SizeOf(Double) * 0 );
  El_0 := PDbl^;
  PDbl := Pointer( Integer(PBase) + 12 + SizeOf(Double) * 1 );
  El_1 := PDbl^;
  PDbl := Pointer( Integer(PBase) + 12 + SizeOf(Double) * 2 );
  El_2 := PDbl^;
  PDbl := Pointer( Integer(PBase) + 12 + SizeOf(Double) * 3 );
  El_3 := PDbl^;
  PDbl := Pointer( Integer(PBase) + 12 + SizeOf(Double) * 4 );
  El_4 := PDbl^;
 
  ShowMessage(
    'Размер выделенного блока памяти = ' + IntToStr(Size) + ' байт.' + Char(10)
    + 'Количество ссылок = ' + IntToStr(RefCount) + Char(10)
    + 'Длина массива, т. е. Length(Arr) = ' + IntToStr(ArrLength) + ' элементов.' + Char(10)
    + 'Arr[0] = ' + FloatToStr(El_0) + Char(10)
    + 'Arr[1] = ' + FloatToStr(El_1) + Char(10)
    + 'Arr[2] = ' + FloatToStr(El_2) + Char(10)
    + 'Arr[3] = ' + FloatToStr(El_3) + Char(10)
    + 'Arr[4] = ' + FloatToStr(El_4)
  );
end;
---
В байтах со смещением 4, 5, 6, 7 относительно PBase расположено целое число равное количеству ссылок на данную структуру. В приведённом примере RefCount = 1. Если, например, дополнительно объявить ещё одну переменную типа дин массив:
Arr2 : array of array of Double;
А затем в выше представленном коде выполнить:
Arr2 := Arr;
То новый массив не будет создан, а лишь увеличится количество ссылок RefCount = 2.
Если затем сделать так:
Arr2 := nil;
Тогда вновь окажется RefCount = 1.
Если выполнить:
Arr := nil;
Тогда окажется, что RefCount = 0 при этом произойдёт автоматическое освобождение памяти из под массива, на который ранее ссылалась переменная Arr.
Поэтому динамические массивы (как и строки типа String, AnsiString, WideString) называются ссылочными (или динамическими) типами. Для освобождения памяти из под этих типов данных в Delphi применяется технология "уборки мусора" - т. е. память освобождается автоматически, как только окажется, что RefCount = 0.
Строки String, AnsiString, WideString устроены точно так же как и одномерные динамические массивы. Т. е. по сути они представляют собой одмерные динамические массивы, содержащие символы. Хотя есть всё же некоторые отличия в том как компилятор Delphi обрабатывает строки и дин. массивы.
---
Ещё добавлю про то, как можно вводить двумерные массивы с клавиатуры в консоли.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
program Project2;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils, Windows;
 
var
  Arr : array of array of Integer;
  N, M, i, j : Integer;
begin
  {Переключение окна консоли на кодовую страницу CP1251 (Win-1251).
  Если после переключения русские буквы показываются неверно,
  следует открыть системное меню консольного окна - щелчком мыши в левом
  верхнем углу окна консоли и выбрать:
  Свойства - закладка "Шрифт" - выбрать шрифт: "Lucida Console".}
  SetConsoleCP(1251);
  SetConsoleOutputCP(1251);
  
  Writeln('Задайте размер массива:');
  Writeln('Количество строк: N = ');
  Readln(N);
  Writeln('Количество столбцов: M = ');
  Readln(M);
 
  SetLength(Arr, N, M);
 
  Writeln('Задайте значения элементов массива.');
  Writeln('Вводите значений построчно через пробел в каждой строке. В конце строки - ENTER.');
  for i := 0 to High(Arr) do begin //for i := 0 to N - 1 do begin
    Writeln('Строка ', i, ' :');
    for j := 0 to High(Arr[i]) do //for j := 0 to M - 1 do
      Read(Arr[i, j]);
    Readln;
  end;
 
  Writeln('Сформированный массив:');
  for i := 0 to High(Arr) do begin
    for j := 0 to High(Arr[i]) do
      Write(Arr[i, j], ' ');
    Writeln;
  end;
 
  Readln;
end.
Есть несколько очень хороших статей по дин. массивам и строкам. Вот:
---
1. Длинные строки и динамические массивы в Delphi.
2. Тонкости работы со строками в Delphi.
3. Строковые типы в Delphi. Особенности реализации и использования.
4. Параметры типа открытый массив и "array of const".
---
Эти 4 статьи - это полный комплект знаний по дин. массивам и строкам.
61
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
28.01.2010, 11:46
Помогаю со студенческими работами здесь

Динамические массивы
С помощью двух динамических массивов (одномерный - для названия стран, двумерный - для количества медалей по странам) нужно сделать...

Динамические массивы
Дан одномерный массив Xn. Найти количество элементов массива, значение которых больше 5. Напечатать номера всех элементов массива, значение...

динамические массивы
помогите пожалуйста с заданием по динамическим массивам: Разработать программу, которая создает список L, элементами которого является...

Динамические массивы
1. Заданы два одномерных массива случайных целых чисел(размеры определяет пользователь). Сформировать Новый массив по правилу:если сумма...

Динамические массивы
Здравствуйте! Недавно решил попробовать покодить на Delphi Prism... и возникла проблема... В дельфи win32 есть замечательная вещь:...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Закрытая тема Создать тему
Опции темы

Новые блоги и статьи
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
PowerShell Snippets
iNNOKENTIY21 11.11.2025
Модуль PowerShell 5. 1+ : Snippets. psm1 У меня модуль расположен в пользовательской папке модулей, по умолчанию: \Documents\WindowsPowerShell\Modules\Snippets\ А в самом низу файла-профиля. . .
PowerShell и онлайн сервисы. Валюта (floatrates.com руб.)
iNNOKENTIY21 11.11.2025
PowerShell функция floatrates-rub Примеры вызова: # Указанная валюта 'EUR' floatrates-rub -Code 'EUR' # Список имеющихся кодов валют floatrates-rub -Available function floatrates-rub {
PowerShell и онлайн сервисы. Погода (RP5.ru)
iNNOKENTIY21 11.11.2025
PowerShell функция Get-WeatherRP5rss для получения погоды с сервиса RP5 Примеры вызова Get-WeatherRP5rss с указанием id 5484 — Москва (восток, Измайлово) и переносом строки:. . .
PowerShell и онлайн сервисы. Погода (wttr)
iNNOKENTIY21 11.11.2025
PowerShell Функция для получения погоды с сервиса wttr Примеры вызова: Погода в городе Омск с прогнозом на день, можно изменить прогноз на более дней, для этого надо поменять запрос:. . .
PowerShell и онлайн сервисы. Валюта (ЦБР)
iNNOKENTIY21 11.11.2025
# Получение курса валют function cbr (] $Valutes = @('USD', 'EUR', 'CNY')) { $url = 'https:/ / www. cbr-xml-daily. ru/ daily_json. js' $data = Invoke-RestMethod -Uri $url $esc = 27 . . .
И решил я переделать этот ноут в машину для распределенных вычислений
Programma_Boinc 09.11.2025
И решил я переделать этот ноут в машину для распределенных вычислений Всем привет. А вот мой компьютер, переделанный из ноутбука. Был у меня ноут асус 2011 года. Со временем корпус превратился. . .
Мысли в слух
kumehtar 07.11.2025
Заметил среди людей, что по-настоящему верная дружба бывает между теми, с кем нечего делить.
Новая зверюга
volvo 07.11.2025
Подарок на Хеллоуин, и теперь у нас кроме Tuxedo Cat есть еще и щенок далматинца: Хочу еще Симбу взять, очень нравится. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru