如何交换二维数组的两行,为什么它会起作用?

发布于 2024-10-22 11:35:03 字数 1980 浏览 5 评论 0原文

总结:

请查看以下来自 David、Uwe 和其他专家的评论。

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

以下代码交换二维动态双精度值数组中的两行。我想知道:(1)下面的代码是否是交换二维数组的两行的最佳实践?如果不是,那么完成此类工作的最佳实践是什么? (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.

Summarization:

Please check the comments below from David, Uwe, and other experts.

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

The following code swaps two rows in a two-dimensional, dynamic array of double values. I am wondering: (1) whether the following code is a best practice of swapping two rows of a two-dimensional array? If not, then what is the best practice to do this kind of job? (2) why would the following code work? I mean, isn't two-dimensional array a continuous contiguous section of memory? Does the following code work only by luck? Any suggestion is appreciated!

    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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谜泪 2024-10-29 11:35:03

你问:

下面的代码只能运行吗
运气好?

嗯,是的,您依赖于特定于实现的细节。

事实上,正确的编写方法是非常自然和简单的:

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,以便您可以在交换例程中执行对 Temp 的赋值。

二维常量大小数组

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

是连续的内存块。

您拥有的二维动态大小数组不是。事实上,它甚至可能是参差不齐的,因为行具有不同数量的列。所以你可以有一个三角矩阵。

You ask:

Does the following code work only by
luck?

Well, yes, you are relying on implementation specific details.

In fact the correct way to write it is perfectly natural and simple:

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;

You need to declare an intermediate type for the row, TDoubleArray, so that you can perform the assignment to Temp in the swap routine.

A 2D constant size array

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

is a contiguous block of memory.

A 2D dynamically size array as you have is not. Indeed it can even be ragged in the sense that the rows have different numbers of columns. So you can have, say, a triangular matrix.

ま昔日黯然 2024-10-29 11:35:03

动态数组被实现为指向表示该数组的内存块的指针。所以二维动态数组实际上是一个指向指针数组的指针。这就是为什么交换行(-指针)实际上有效。

请参阅大卫的回答以获得更简洁的方法。

更新:
如果您被允许使用泛型,您不妨这样做:

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;

A dynamic array is implemented as a pointer to a memory block representing that array. So a two-dimensional dynamic array is actually a pointer to an array of pointers. Thats why swapping the row(-pointer)s actually works.

See David's answer for a cleaner approach.

Update:
If you are allowed to use generics you might as well do this:

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文