Форум: "Начинающим";
Поиск по всему сайту: www.delphimaster.net;
Текущий архив: 2010.10.03;
Скачать: [xml.tar.bz2];




Вниз

Как скопировать один массив массивов в другой? 


AKE   (2010-07-02 19:12) [0]

сабж.



Amoeba_   (2010-07-02 19:22) [1]

Какой? Статический или динамический?



AKE   (2010-07-02 19:36) [2]

статический массив статических массивов...



Германн ©   (2010-07-02 20:02) [3]

Move



AKE   (2010-07-02 20:29) [4]

Германн ©   (02.07.10 20:02) [3]
Спасибо...



Jeer ©   (2010-07-02 21:51) [5]

Вообще-то, для статических массивов одинаковой размерности

A := B;

означает копирование содержимого А в B.

Для динамических же - копирование адреса.



AKE   (2010-07-02 21:57) [6]

Jeer ©   (02.07.10 21:51) [5]
А если это массив массивов то всё перекопируется нормально...



Jeer ©   (2010-07-02 22:09) [7]


> AKE   (02.07.10 21:57) [6]
>
> Jeer ©   (02.07.10 21:51) [5]
> А если это массив массивов то всё перекопируется нормально.
> ..


Непонятно, это вопрос или утверждение ?



AKE   (2010-07-02 22:44) [8]

Jeer ©   (02.07.10 22:09) [7]
Знак вопроса забыл поставить...



Германн ©   (2010-07-03 01:43) [9]


> А если это массив массивов

Для статических массивов это не имеет ни малейшего значения. Во всяком случае, если оба массива одного типа (соломку всё-таки решил подстелить :).



Anatoly Podgoretsky ©   (2010-07-03 13:42) [10]

> Германн  (03.07.2010 01:43:09)  [9]

Не обязательно, но копируемый массив должен быть такого же или меньшего
объема.



Демо ©   (2010-07-03 16:53) [11]

Как для динамических, так и для статических массивов, достаточно выполнить:

B := A;

для динамического массива, кроме этого, нужно ещё выполнить

SetLength(B,Length(B));



Jeer ©   (2010-07-03 17:16) [12]


> Демо ©   (03.07.10 16:53) [11]


Иди покури "травку", прежде чем советовать.



Jeer ©   (2010-07-03 17:18) [13]

arsA,arsB: array[0..4] of double;
 ardA, ardB: array of double;

 SetLength(ardA, 5);
 SetLength(ardB, 5);

 arsA[0] := 1;
 arsB := arsA;
 arsB[0] := 2;
 ShowMessage(Format("%f %f",[arsA[0], arsB[0]]));

 ardA[0] := 1;
 ardB := ardA;
 ardB[0] := 2;
 ShowMessage(Format("%f %f",[ardA[0], ardB[0]]));

Как говорится -"Почувствуй разницу"



Amoeba_   (2010-07-03 17:18) [14]


> Демо ©   (03.07.10 16:53) [11]


> для динамического массива, кроме этого, нужно ещё выполнить
>
> SetLength(B,Length(B));

Не надо.
Читаем справку:
If X and Y are variables of the same dynamic-array type, X :=Y points X to the same array as Y. (There is no need to allocate memory for X before performing this operation.)



Anatoly Podgoretsky ©   (2010-07-03 17:25) [15]

> Amoeba_  (03.07.2010 17:18:14)  [14]

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



Jeer ©   (2010-07-03 17:25) [16]

Вкупе, вот такие операции породят утечку, т.к. будет утеряна ссылка на В и ее инициализация (аллокация).

SetLength(ardB, 5);
arsB := arsA;



Jeer ©   (2010-07-03 17:27) [17]

P.S.
Возможно, что средства управления динамическими массивами действительно "подчистят" B, но я не уверен.
Потому это не небрежность, а ошибка.



Демо ©   (2010-07-03 17:47) [18]


> Jeer ©   (03.07.10 17:16) [12]
> > Демо ©   (03.07.10 16:53) [11]Иди покури "травку", прежде
> чем советовать.


Бредить не надо? Ок?


> Amoeba_   (03.07.10 17:18) [14]
> > Демо ©   (03.07.10 16:53) [11]> для динамического массива,
>  кроме этого, нужно ещё выполнить> > SetLength(B,Length(B));
> Не надо.Читаем справку:If X and Y are variables of the same
> dynamic-array type, X :=Y points X to the same array as
> Y. (There is no need to allocate memory for X before performing
> this operation.)


При присвоении переменных динамических массивов происходит копирование ссылки на массив.
+ Рекомендую перечитать справку по SetLength.

procedure TForm1.btnCopyDinArraysClick(Sender: TObject);
type
 TTestArr = array of byte;
var
 vB1: TTestArr;
 vB2: TTestArr;
begin
 SetLength(vB1, 3);
 vB1[0] := 1;
 vB1[1] := 2;
 vB1[2] := 3;

 vB2 := vB1;
 SetLength(vB2, Length(vB2)); //Здесь память будет перераспределена и все элементы скопированы.

 vB1[0] := 10;
end;



Демо ©   (2010-07-03 17:50) [19]


> Anatoly Podgoretsky ©   (03.07.10 17:25) [15]


Анатолий,Ю я бы советовал всё же внимательнее читать, то, что пишут.
У меня написано в [11], что SetLength должен выполняться после присвоения.



Anatoly Podgoretsky ©   (2010-07-03 18:07) [20]

А ты тоже повнимательнее читай, особенно про A:=B; Если после то это особо жестоко, это тянет на пожизненый эцик с гвоздями



Демо ©   (2010-07-03 18:12) [21]


>  особенно про A:=B;


Э-э... У меня написано B := A;



Anatoly Podgoretsky ©   (2010-07-03 19:47) [22]

> Демо  (03.07.2010 18:12:21)  [21]

Ну тогда другое дело.



Германн ©   (2010-07-04 01:44) [23]


> Anatoly Podgoretsky ©   (03.07.10 13:42) [10]
>
> > Германн  (03.07.2010 01:43:09)  [9]
>
> Не обязательно, но копируемый массив должен быть такого
> же или меньшего
> объема.
>

Тогда возникает вопрос о "правильности" копирования.
Например массив A : array [0..N-1][0..N-1][0..N-1] of Byte  меньше по объёму чем массив B : array [0..M-1][0..M-1] of Byte если N < 2/3 от M. Но что тогда будет после B:=A?



Юрий Зотов ©   (2010-07-04 01:50) [24]

Не въезжаю, о чем спор?

B := A; // Копируется только указатель.
SetLength(B, Length(B)); // Создается реальная копия массива

С этого момента A указывает на старый массив, B - на новый. О каких утечках памяти идет речь?



Германн ©   (2010-07-04 02:08) [25]


> Юрий Зотов ©   (04.07.10 01:50) [24]
>
> Не въезжаю, о чем спор?
>
>

Так ведь в начале были статические массивы.



Демо ©   (2010-07-04 02:52) [26]


> Но что тогда будет после B:=A?


Будет Incompatible types при компиляции.



Германн ©   (2010-07-04 02:56) [27]


> Демо ©   (04.07.10 02:52) [26]
>
>
> > Но что тогда будет после B:=A?
>
>
> Будет Incompatible types при компиляции.

Ну а я про что?



Германн ©   (2010-07-04 03:00) [28]

И при чём тут "объём" массива?



Anatoly Podgoretsky ©   (2010-07-04 11:40) [29]

> Германн  (04.07.2010 01:44:23)  [23]

Массив будет частично запонлнен, но массив А будет скопирован полностью.
Хуже если А > B, вот тогда капут.
В массиве будет M*M элементов и это число надо хранить, что бы можно было
работать с частично заполненым массивов. Вообще то это обычная ситуация,
когда размер массива больше, чем число элементов, правда обычно эту технику
используют для одномерных массивов.

Спрашивается нафиг это нужно, но ведь ранее не было динамических массивов,
люди не умееют работать с динамическими массивами, для преобразования
двумерного массива в одномерный, а работать с приведениями опять же не
умеем. Ну и т.д.



Anatoly Podgoretsky ©   (2010-07-04 11:50) [30]

> Юрий Зотов  (04.07.2010 01:50:24)  [24]

> С этого момента A указывает на старый массив, B - на новый.

Это не строки и операция COPY-ON-WRITE не применима к ним, к ним применим
только счетчик ссылок, по обнулению массив освобождается

> Unlike strings and static arrays, COPY-ON-WRITE is not employed for
> dynamic arrays, so they are not automatically copied before they are
> written to.

>   A[0] := 1;
>   B := A;
>   B[0] := 2;
> end;

> the value of A[0] is 2. (If A and B were static arrays, A[0] would still
> be 1.) и тоже для строк, A[1] будет иметь старое значение
> Assigning to a dynamic-array index (for example, MyFlexibleArray[2] := 7)
> does not reallocate the array.



Anatoly Podgoretsky ©   (2010-07-04 11:52) [31]

> Германн  (04.07.2010 03:00:28)  [28]

А ты налей два литра в литровую тару.



Sha ©   (2010-07-04 12:07) [32]

> Демо ©   (03.07.10 16:53) [11]
> Как для динамических, так и для статических массивов, достаточно выполнить:
> B := A;
> для динамического массива, кроме этого, нужно ещё выполнить
> SetLength(B,Length(B));

Небольшое добавление.
В случае автора (массив массивов) после присваивания оператор
SetLength(B,Length(B));
надо заменить на что-то вроде
SetLength(B,Length(B),Length(B[0]));

Здесь предполагается, что динамический массив двумерный и прямоугольный.



Демо ©   (2010-07-04 14:23) [33]


> > С этого момента A указывает на старый массив, B - на новый.
>  Это не строки и операция COPY-ON-WRITE не применима к ним,
>  к ним применим только счетчик ссылок, по обнулению массив
> освобождается


Весь цимус в использованиии SetLength. SetLength выделяет под массив память и копирует туда данные из исходного массива.
При этом ссылка на массив становится уникальной.

PS.

Статические же массивы возможно копировать только в случае идентичности типов. Ни о какой различной размерности целевого исходного массива речи быть не может.



Sapersky   (2010-07-04 15:18) [34]

В случае автора (массив массивов) после присваивания оператор
SetLength(B,Length(B));
надо заменить на что-то вроде
SetLength(B,Length(B),Length(B[0]));


Я для таких случаев написал функцию UniqueData, по аналогии с UniqueString.
http://sapersky.narod.ru/files/TypInfoEx.rar



Демо ©   (2010-07-04 15:31) [35]


> Sapersky   (04.07.10 15:18) [34]


Универсализм - враг эффективности и простоты кода.



Sapersky   (2010-07-04 17:29) [36]

Копипаст "простых и эффективных" решений тоже сомнительное благо - при этом легко ляпнуть идиотскую ошибку и потом долго её искать.
Истина, видимо, посередине, с отклонениями (по вкусу) в ту или иную сторону.

Конкретно TypInfoEx затраченных на неё усилий не оправдала (кроме той части, которая относится к массивам), получился скорее хакерский концепт-юнит, чем "рабочая лошадка". Но если уж написано - то почему бы не воспользоваться. По крайней мере, для многомерных массивов и пр. сложных структур; хотя и для одномерных SetLength(B,Length(B)) куда больше смахивает на шаманское заклинание, чем UniqueData.




Форум: "Начинающим";
Поиск по всему сайту: www.delphimaster.net;
Текущий архив: 2010.10.03;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.8 MB
Время: 0.029 c
2-1279059236      AKE                   2010-07-14 02:13  2010.10.03  
Как поведёт себя команда Readln(F, var1, var2,..., varn)??


2-1278922587      JohnKorsh             2010-07-12 12:16  2010.10.03  
Печать форм.


2-1279004324      бумбум                2010-07-13 10:58  2010.10.03  
Русские буквы в PDF


3-1245876026      Miau                  2009-06-25 00:40  2010.10.03  
Передача параметра в хранимую процедуру.


2-1278996425      azamatufa             2010-07-13 08:47  2010.10.03  
Подскажите как правильно выводить отчет в Word