2011-03-18 6 views
0

요약 :2 차원 배열의 두 행을 교체하는 방법과 작동 원리는 무엇입니까?

아래의 David, Uwe 및 기타 전문가의 의견을 확인하십시오.

============================================== ==================================

다음 코드는 2 차원에서 두 행 스왑 double 값의 동적 배열. 나는 궁금해 : (1) 다음 코드는 2 차원 배열의 두 행을 교환하는 가장 좋은 방법입니다 여부? 그렇지 않다면, 이런 일을하는 가장 좋은 방법은 무엇입니까? (2) 왜 다음 코드가 작동합니까? 내 말은, 2 차원 배열이 아닌 연속 연속적인 메모리 섹션입니까? 다음 코드는 운에 의해서만 작동합니까? 어떤 제안이라도 감사드립니다!

unit Unit5; 

    interface 

    uses 
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
     Dialogs; 

    type 
     TAADouble = array of array of Double; 

     TForm5 = class(TForm) 
     procedure FormShow(Sender: TObject); 
     private 
     { Private declarations } 
     public 
     { Public declarations } 
     end; 

    var 
     Form5: TForm5; 

    procedure SwapRows(arr: TAADouble; row0, row1: Integer); 

    implementation 

    {$R *.dfm} 

    procedure SwapRows(arr: TAADouble; row0, row1: Integer); 
    var 
     Tmp: Integer; 
    begin 
     {$IFDEF FPC} 
     Tmp := PtrUInt(arr[row0]); 
     PtrUInt(arr[row0]) := PtrUInt(arr[row1]); 
     PtrUInt(arr[row1]) := Tmp; 
     {$ELSE} 
     Tmp := Integer(arr[row0]); 
     Integer(arr[row0]) := Integer(arr[row1]); 
     Integer(arr[row1]) := Tmp; 
     {$ENDIF} 

    end; 

    procedure TForm5.FormShow(Sender: TObject); 
    var 
     tmpArray: TAADouble; 
     I, J: Integer; 
     rowStr: string; 
    begin 
     SetLength(tmpArray, 10, 10); 
     rowStr := ''; 

     for I := 0 to 9 do 
     for J := 0 to 9 do 
      tmpArray[I][J] := I * J; 

     for I := 0 to 9 do 
     begin 
     rowStr := ''; 
     for J := 0 to 9 do 
      rowStr := rowStr + FloatToStr(tmpArray[I][J]) + ' '; 
     OutputDebugString(PWideChar(rowStr)); 
     end; 

     SwapRows(tmpArray, 3, 4); 

     for I := 0 to 9 do 
     begin 
     rowStr := ''; 
     for J := 0 to 9 do 
      rowStr := rowStr + FloatToStr(tmpArray[I][J]) + ' '; 
     OutputDebugString(PWideChar(rowStr)); 
     end; 
    end; 

    end. 
+1

을 -이 64 비트 버전이 도착하면 비참하게 실패 할 것입니다 ... 최근 Delphi를 사용하고 있다면 NativeInt 유형을 사용하십시오. 그렇지 않으면 직접 포인터 크기와 일치하도록 설정할 수 있습니다. –

답변

4

당신은 질문 :

는 행운에 의해 다음과 같은 코드를 사용할 수 있습니까?

음, 그래, 당신이 구현 구체적인 세부 사항에 의존하고 있습니다. 사실

를 작성하는 올바른 방법은 완벽하게 자연스럽고 간단하다

type 
    TDoubleArray = array of Double; 
    TDoubleMatrix = array of TDoubleArray; 

procedure SwapRows(M: TDoubleMatrix; Row1, Row2: Integer); 
var 
    Temp: TDoubleArray; 
begin 
    Temp := M[Row1]; 
    M[Row1] := M[Row2]; 
    M[Row2] := Temp; 
end; 

당신이 스왑에 임시로 할당을 수행 할 수 있도록 당신은, 행, TDoubleArray에 대한 중간 타입을 선언 할 필요가 루틴.

차원 일정한 크기 어레이

array [1..M] of array [1..N] of TMyType 

메모리의 연속 블록이다. 당신이 가지고있는

차원 동적 크기 배열이 아닙니다. 실제로 행에 다른 수의 열이 있다는 의미에서 불규칙하게 보일 수도 있습니다. 예를 들어 삼각형 행렬을 가질 수 있습니다.

+0

@David : 2D 상수 크기 배열은 인접한 메모리 블록이라는 것을 알아두면 좋습니다. 2D 동적 크기 배열은 그렇지 않습니다. 행마다 열의 수가 다르다는 점에서 실제로는 불평 할 수도 있습니다. '도움을 주셔서 대단히 감사합니다! – SOUser

+0

@David : 그럼에도 불구하고'TDoubleMatrix'에'var' 접두사가 필요합니까? 만약'var' 접두사가 없다면 이상한 에러가 나올까? – SOUser

+1

@ Xichen 아니야.나는 내가 생각하는 습관에서 그렇게한다. 그것은 그것없이 완벽하게 작동합니다. 나는 var의 유무에 관계없이 그럴만한 이유가 있다고 생각하지 않습니다. 그것은 단지 습관 일뿐입니다. –

4

동적 배열은 그 배열을 나타내는 메모리 블록에 대한 포인터로서 구현된다. 따라서 2 차원 동적 배열은 실제로 포인터 배열에 대한 포인터입니다. 그게 왜 행 (- 포인터)을 바꾸는 것이 실제로 효과가 있는지.

깨끗한 접근 방식에 대한 참조 다윗의 대답.

업데이트 : 당신이이 할 수있는 제네릭을 사용할 수있는 경우 : (순간) 위의 작품은, 정수에 대한 포인터를 캐스팅하는 것은 안전하지 않습니다 동안

procedure <SomeClassOrRecord>.SwapRows<T>(var arr: TArray<T>; row0, row1: Integer); 
var 
    Tmp: T; 
begin 
    Tmp := arr[row0]; 
    arr[row0] := arr[row1]; 
    arr[row1] := Tmp; 
end; 
+0

@Uwe : 유용한 의견을 보내 주셔서 감사합니다. – SOUser

+0

@David : '행의 참조 수가 다른 경우 작동하지 않을 것입니다.'라는 것이 무슨 뜻인지에 대해 설명하는 데 도움이 될 수 있습니까? – SOUser

+1

@ Xichen 아니요. 나는 혼란스러워하고 있습니다. 그 진술은 정확하지 않습니다. –

관련 문제