2009-07-13 11 views
8

J'ai un tel problème de base dans Delphi, je ne peux pas le résoudre.Comment copier une matrice?

Mon code:

Note: Datar est locale dans les méthodes ci-dessous, mais en général il est une classe var.Just pour le concept, il est local.

class procedure TCelebrity.BeginRead(var input:Array of byte); 
var DataR:Array of byte; 
begin 
    VirtualFree(@DataRead,High(DataRead),MEM_RELEASE); 
    SetLength(DataR,Length(input)); 
    Move(input,DataR,Length(input)); 
end; 

Ceci compile, mais après que Move() est exécuté DataR = nil.

Deuxième essai:

class procedure TCelebrity.BeginRead(var input:Array of byte); 
var DataR:Array of byte; 
begin 
    VirtualFree(@DataRead,High(DataRead),MEM_RELEASE); 
    SetLength(DataR,Length(input)); 
    DataR := Copy(input,0,Length(input)); 
end; 

Cela ne compile pas à all.Error à la troisième ligne (Datar: = Copier (entrée ....) en disant "types" incompatibles

Où est. ! le problème Ils sont tous tableau d'octets

Répondre

7

Pourquoi ne pas utiliser pour

SetLength(DataR,Length(input)); 
for i:=Low(input) to High(input) do 
    DataR[i]:=input[i]; 

BTW: si vous voulez avoir des tableaux de passage en tant que paramètre, vous devez les déclarer comme un type, par exemple:

type 
    TMyArray = array of byte; 

et utiliser TMyArray en tant que type de paramètres.

Modifier: J'ai été averti de la plus faible valeur. Dans mon article original, c'était pour i: = 0, mais i: = Low (entrée) est plus sûr et plus pur.

+0

J'ai une question.Le VirtualFree renvoie toujours faux alors comment puis-je libérer le mem actuellement utilisé avec DataR? Note DataR n'est pas local, mais classe var dans le code original. Merci d'avance pour la réponse! –

+0

Non, vous n'avez pas de tableaux simples libres. De tels tableaux sont libérés automatiquement (par exemple lorsque votre classe est détruite). Note: si vous avez un tableau de références à des objets, vous devez libérer ces objets manuellement, car seul le tableau sera libéré par Delphi. – smok1

+0

Notez également que SetLenght réalloue l'ensemble du tableau, évitez donc l'utilisation intensive de cette procédure. Lorsque vous définissez le tableau plus long avec SetLength, le contenu actuel reste intact. Toutefois, lorsque vous le raccourcissez, une partie du contenu est perdue. – smok1

2

Essayez:

class procedure TCelebrity.BeginRead(var input:Array of byte); 
var DataR:Array of byte; 
begin 
    VirtualFree(@DataRead,High(DataRead),MEM_RELEASE); 
    SetLength(DataR,Length(input)); 
    Move(input[0],DataR,Length(input)); 
end; 
+0

Je l'ai fait, cela ne fonctionne pas. –

8

essayer cette

type 
    TByteDynArray = array of Byte; 

function CopyData(const Input:array of Byte):TByteDynArray; 
begin 
    SetLength(Result, Length(Input)); 
    Move(input[0], Result[0], Length(Input)); 
end; 
+5

Une réponse correcte. mais pour en faire une * bonne * réponse, vous devez expliquer * pourquoi * vos changements sont significatifs. Sinon, c'est juste une incantation magique. –

+3

Corrigez-moi si je me trompe, mais il pourrait être intéressant de noter que cela ne fonctionne que comme écrit pour 'array of Byte'. Si le tableau était différent, disons 'array of Integer', alors vous auriez besoin de' Move (entrée [0], résultat [0], longueur (entrée) * SizeOf (Integer)) '. Je dis juste. –

+0

@Rob Kennedy: Move() dans Delphi est similaire à memcpy()/memmove() dans C – dns

1

procédure de déplacement ne se déplace pas une partie de la mémoire. Il copie Count octets. Vous obtiendrez ainsi deux tableaux identiques différents: Input et DataR.

procedure CopyData(const Input: Array of Byte); 
var 
    DataR: Array of Byte; 
begin 
    SetLength(DataR, Length(Input)); 
    Move(Input[0], DataR[0], SizeOf(Byte)*Length(Input)); 
end; 

P.s. Avec les tableaux statiques, vous pouvez utiliser SizeOf (Input) au lieu de SizeOf (Byte) * Length (Input). Au lieu de Byte, il peut s'agir d'un autre type de données.

+0

pourquoi ne pas utiliser SizeOf (Input [0]) au lieu d'un type de données codé en dur? –

Questions connexes