Форум программистов, компьютерный форум, киберфорум
Наши страницы

Delphi для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 542, средняя оценка - 4.75
krolex
9 / 9 / 1
Регистрация: 27.01.2010
Сообщений: 63
#1

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

27.01.2010, 19:41. Просмотров 73343. Ответов 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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.01.2010, 19:41
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Динамические массивы в Delphi (Delphi):

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

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

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

Динамические массивы - Delphi
Доброго времени, ищу помощи по данному вопросу, сам разобраться не в состоянии в виду полного отсутствия знания языка. Для матрицы А...

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

Динамические массивы? - Delphi
Составить код программы, которая выполняет следующие действия: 1. Формирование двумерного целочисленного массива (матрицы) размером N х...

3
Mawrat
12788 / 5695 / 672
Регистрация: 19.09.2009
Сообщений: 8,838
27.01.2010, 20:23 #2
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
krolex
9 / 9 / 1
Регистрация: 27.01.2010
Сообщений: 63
27.01.2010, 22:50  [ТС] #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
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
12788 / 5695 / 672
Регистрация: 19.09.2009
Сообщений: 8,838
28.01.2010, 11:46 #4
Да - там ещё границы изменения индексов неверно заданы.
Сейчас расскажу...
Вариант правильного кода выглядит так:
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" может быть таким:
Код
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" может быть и непрямоугольным:
Код
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);
В данном случае:
Код
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 статьи - это полный комплект знаний по дин. массивам и строкам.
60
28.01.2010, 11:46
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.01.2010, 11:46
Привет! Вот еще темы с ответами:

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

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

Динамические массивы - Delphi
Вчера на практике в колледже мы разбирали динамические массивы. Когда я узнала тему, то подумала: что тут сложного, A: array of...

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


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru