본문 바로가기

코딩 이야기/델파이 코딩

델파이 배열(Array) 종류별 설명 및 예시

배열(Array) 종류별 설명 및 예시

델파이에서 배열(Array)은 동일한 타입의 요소(Element)들을 연속된 메모리 공간에 저장하고, 각 요소에 인덱스(Index)를 통해 접근하는 자료 구조입니다. 델파이는 다양한 종류의 배열을 지원하며, 각각의 특징과 용도가 다릅니다. 크게 정적 배열, 동적 배열, 공개 배열로 나눌 수 있습니다.

1. 정적 배열 (Static Arrays)

설명

정적 배열은 배열의 크기(요소의 개수)가 컴파일 시점에 결정되고, 프로그램 실행 중에는 변경할 수 없는 배열입니다. 배열의 인덱스 범위를 직접 지정할 수 있으며, 0부터 시작하지 않아도 됩니다.

  • 선언: var 변수명: array[최소인덱스..최대인덱스] of 요소타입; 형식으로 선언합니다.
  • 인덱스 범위: 정수뿐만 아니라 열거형(Enumerated type)이나 문자(Char) 같은 순서 타입(Ordinal type)도 인덱스로 사용할 수 있습니다. (예: array['A'..'Z'] of Integer)
  • 메모리: 프로그램의 데이터 영역이나 스택(Stack)에 할당되며, 크기가 고정되어 있어 메모리 관리가 단순하고 접근 속도가 빠릅니다.
  • 다차원 배열: array[범위1, 범위2] of 타입; 또는 array[범위1] of array[범위2] of 타입; 형태로 선언할 수 있습니다.

// 정적 배열 선언 예시
var
  Numbers: array[0..9] of Integer;      // 0부터 9까지 10개의 정수 배열
  Names: array[1..5] of string;        // 1부터 5까지 5개의 문자열 배열
  Flags: array[Boolean] of Integer;    // False, True를 인덱스로 사용하는 배열 (2개 요소)
  Matrix: array[1..3, 1..4] of Double; // 3x4 크기의 2차원 실수 배열

예제

정적 배열을 선언하고, 값을 할당하며, 반복문을 통해 접근하는 기본적인 예제입니다. 1차원 및 2차원 배열을 포함합니다.


uses System.SysUtils;

procedure StaticArrayExample;
var
  // 1차원 정적 배열
  Scores: array[0..4] of Integer;
  Weekdays: array[1..7] of string;

  // 2차원 정적 배열
  Matrix: array[1..2, 1..3] of Integer; // 2행 3열

  I, J: Integer;
begin
  // 1차원 배열 초기화 및 접근
  Scores[0] := 90;
  Scores[1] := 85;
  Scores[2] := 77;
  Scores[3] := 92;
  Scores[4] := 88;

  Write('점수: ');
  for I := Low(Scores) to High(Scores) do // Low=0, High=4
    Write(Scores[I], ' ');
  Writeln; // 출력: 점수: 90 85 77 92 88

  Weekdays[1] := '월'; Weekdays[2] := '화'; Weekdays[3] := '수';
  Weekdays[4] := '목'; Weekdays[5] := '금'; Weekdays[6] := '토'; Weekdays[7] := '일';

  Writeln('3번째 요일: ' + Weekdays[3]); // 출력: 3번째 요일: 수

  // 2차원 배열 초기화 및 접근
  for I := Low(Matrix, 1) to High(Matrix, 1) do // 1차원(행) 범위: 1..2
  begin
    for J := Low(Matrix, 2) to High(Matrix, 2) do // 2차원(열) 범위: 1..3
    begin
      Matrix[I, J] := I * 10 + J;
      Write(Format('%3d', [Matrix[I, J]])); // 3자리 정수 출력
    end;
    Writeln;
  end;
  { 출력:
     11 12 13
     21 22 23
  }
end;
        

Low(배열변수)High(배열변수) 함수는 정적 배열의 인덱스 최소값과 최대값을 반환합니다. 2차원 이상 배열의 경우 Low(배열변수, 차원번호) 형태로 특정 차원의 범위를 알 수 있습니다.

2. 동적 배열 (Dynamic Arrays)

설명

동적 배열은 프로그램 실행 중에 크기를 결정하거나 변경할 수 있는 배열입니다. 크기가 정해져 있지 않으므로 선언 시에는 인덱스 범위를 지정하지 않습니다. SetLength 프로시저를 사용하여 배열의 크기를 설정하거나 변경합니다.

  • 선언: var 변수명: array of 요소타입; 형식으로 선언합니다.
  • 크기 설정: SetLength(배열변수, 원하는크기);를 호출하여 메모리를 할당하고 크기를 설정합니다. 이전에 배열에 내용이 있었다면, 크기 변경 시 기존 내용은 유지될 수 있습니다 (단, 줄어드는 경우 잘릴 수 있음).
  • 인덱스: 항상 0부터 시작합니다. (Low(배열)은 항상 0, High(배열)Length(배열) - 1).
  • 메모리: 힙(Heap) 영역에 할당되며, 델파이의 ARC(Automatic Reference Counting) 또는 전통적인 참조 카운팅 방식으로 관리됩니다. 따라서 개발자가 직접 메모리를 해제할 필요는 없습니다 (변수가 범위를 벗어나면 자동으로 관리됨).
  • 다차원 배열: 동적 배열의 요소로 다시 동적 배열을 사용하여 구현합니다. 각 차원의 크기를 다르게 설정할 수 있습니다 (Jagged Array).

// 동적 배열 선언 및 사용 예시
var
  DynInts: array of Integer; // 1차원 동적 정수 배열
  DynMatrix: array of array of string; // 2차원 동적 문자열 배열
  I: Integer;
begin
  // 1차원 동적 배열 크기 설정 및 초기화
  SetLength(DynInts, 5); // 5개의 정수 공간 할당 (0..4 인덱스)
  for I := Low(DynInts) to High(DynInts) do // Low는 0, High는 4
    DynInts[I] := I * 10;

  // 2차원 동적 배열 크기 설정 (Jagged Array)
  SetLength(DynMatrix, 3); // 첫 번째 차원 크기 3으로 설정 (0..2)
  for I := Low(DynMatrix) to High(DynMatrix) do
  begin
    SetLength(DynMatrix[I], I + 2); // 각 행의 크기를 다르게 설정 (2, 3, 4)
    // DynMatrix[0]은 크기 2 (0..1)
    // DynMatrix[1]은 크기 3 (0..2)
    // DynMatrix[2]은 크기 4 (0..3)
  end;
  DynMatrix[1][2] := 'Test';

  // 사용 후 SetLength(배열, 0) 또는 변수가 범위를 벗어나면 자동 관리됨
end;
        
참고: 동적 배열은 참조 타입(Reference Type)입니다. 변수 간의 대입은 배열 데이터 전체 복사가 아니라 참조(주소) 복사입니다. 배열 내용을 복사하려면 System.Copy 함수나 루프를 사용해야 합니다.

예제

동적 배열을 선언하고 SetLength로 크기를 설정하며, 값을 할당하고 Length, Low, High 함수를 사용하는 예제입니다. 2차원 동적 배열(Jagged Array) 예제도 포함합니다.


uses System.SysUtils;

procedure DynamicArrayExample;
var
  Data: array of Integer;         // 1차원 동적 배열
  Grid: array of array of string; // 2차원 동적 배열
  I, J: Integer;
begin
  // 1차원 동적 배열 사용
  Writeln('초기 Data 배열 길이: ', Length(Data)); // 출력: 0

  SetLength(Data, 5); // 크기를 5로 설정 (인덱스 0..4)
  Writeln('SetLength(5) 후 Data 배열 길이: ', Length(Data)); // 출력: 5
  Writeln('Low(Data): ', Low(Data), ', High(Data): ', High(Data)); // 출력: Low(Data): 0, High(Data): 4

  for I := Low(Data) to High(Data) do
    Data[I] := (I + 1) * 100;

  Write('Data 배열 내용: ');
  for I := 0 to Length(Data) - 1 do // Length 사용 가능
    Write(Data[I], ' ');
  Writeln; // 출력: Data 배열 내용: 100 200 300 400 500

  SetLength(Data, 3); // 크기를 3으로 줄임 (0..2). 기존 앞부분 내용은 유지됨
  Write('SetLength(3) 후 Data 배열 내용: ');
  for I := Low(Data) to High(Data) do
    Write(Data[I], ' ');
  Writeln; // 출력: SetLength(3) 후 Data 배열 내용: 100 200 300

  SetLength(Data, 0); // 배열 비우기 (메모리 해제)
  Writeln('SetLength(0) 후 Data 배열 길이: ', Length(Data)); // 출력: 0

  // 2차원 동적 배열 (Jagged Array) 사용
  SetLength(Grid, 3); // 3행 생성 (0..2)
  for I := Low(Grid) to High(Grid) do
  begin
    SetLength(Grid[I], I + 1); // 각 행의 열 개수를 다르게 설정 (1, 2, 3)
    for J := Low(Grid[I]) to High(Grid[I]) do
    begin
      Grid[I, J] := Format('(%d,%d)', [I, J]); // 각 셀에 좌표 문자열 저장
    end;
  end;

  Writeln('2차원 동적 배열 Grid 내용:');
  for I := 0 to Length(Grid) - 1 do
  begin
    for J := 0 to Length(Grid[I]) - 1 do
    begin
      Write(Grid[I, J] + ' ');
    end;
    Writeln;
  end;
  { 출력:
    (0,0)
    (1,0) (1,1)
    (2,0) (2,1) (2,2)
  }

  // 동적 배열은 변수가 범위를 벗어나면 참조 카운트에 의해 자동으로 관리됨
end;
        

3. 공개 배열 (Open Arrays)

설명

공개 배열은 주로 프로시저나 함수의 파라미터 타입으로 사용되어, 정적 배열이나 동적 배열 등 크기나 인덱스 범위가 다른 여러 종류의 배열을 동일한 파라미터로 전달받을 수 있게 해줍니다. 함수 내부에서는 전달된 배열을 항상 0부터 시작하는 인덱스로 접근합니다.

  • 선언 (파라미터): procedure 이름(const 파라미터명: array of 요소타입); 형식으로 선언합니다. const (읽기 전용 권장), var (수정 가능), 값 전달 방식 모두 가능합니다.
  • 내부 접근: 함수/프로시저 내부에서는 전달된 배열의 원래 인덱스 범위와 상관없이 항상 0부터 High(파라미터명) 까지의 인덱스를 사용합니다.
  • 호환성: 정적 배열(인덱스 범위 무관), 동적 배열, 심지어는 배열 생성자([요소1, 요소2, ...])를 직접 인수로 전달할 수 있습니다.
  • 목적: 다양한 형태의 배열을 처리하는 유연한 함수를 작성할 수 있게 합니다.

// 공개 배열 파라미터를 사용하는 프로시저
procedure ProcessArray(const Data: array of Integer);
var
  I: Integer;
  Sum: Integer;
begin
  Sum := 0;
  // 내부에서는 항상 0부터 High(Data)까지 접근
  for I := Low(Data) to High(Data) do // Low(Data)는 항상 0
  begin
    Write(Data[I], ' '); // 요소 출력
    Sum := Sum + Data[I];
  end;
  Writeln;
  Writeln('배열 합계: ', Sum);
  Writeln('배열 크기 (High+1): ', Length(Data)); // Length도 사용 가능
end;

// 사용 예시
var
  StaticArr: array[1..5] of Integer = (10, 20, 30, 40, 50); // 정적 배열 (1..5)
  DynamicArr: array of Integer; // 동적 배열
begin
  // 정적 배열 전달
  ProcessArray(StaticArr);
  // 출력: 10 20 30 40 50
  // 배열 합계: 150
  // 배열 크기 (High+1): 5

  // 동적 배열 설정 및 전달
  SetLength(DynamicArr, 3);
  DynamicArr[0] := 1;
  DynamicArr[1] := 2;
  DynamicArr[2] := 3;
  ProcessArray(DynamicArr);
  // 출력: 1 2 3
  // 배열 합계: 6
  // 배열 크기 (High+1): 3

  // 배열 생성자를 직접 전달
  ProcessArray([100, 200, 300, 400]);
  // 출력: 100 200 300 400
  // 배열 합계: 1000
  // 배열 크기 (High+1): 4
end;
        

예제

정적 배열과 동적 배열, 그리고 배열 리터럴을 모두 받을 수 있는 공개 배열 파라미터를 가진 프로시저를 정의하고 호출하는 예제입니다.


uses System.SysUtils;

// 공개 배열 파라미터를 사용하여 배열 요소의 합계를 계산하고 출력하는 함수
function SumArray(const Values: array of Double): Double;
var
  I: Integer;
begin
  Result := 0.0;
  // 함수 내부에서는 항상 0-based 인덱스로 접근
  for I := Low(Values) to High(Values) do // Low는 0, High는 Length-1
  begin
    Result := Result + Values[I];
  end;
  Writeln(Format('  (함수 내부: Low=%d, High=%d, Length=%d)', [Low(Values), High(Values), Length(Values)]));
end;

procedure OpenArrayExample;
var
  StaticPrices: array[101..103] of Double = (1500.50, 2300.00, 990.75); // 인덱스 101..103
  DynamicQuantities: array of Double;
  Total: Double;
begin
  Writeln('정적 배열 전달:');
  Total := SumArray(StaticPrices);
  Writeln('  합계: ', Total:0:2); // 출력: 합계: 4791.25

  Writeln('동적 배열 전달:');
  SetLength(DynamicQuantities, 4);
  DynamicQuantities[0] := 10.5;
  DynamicQuantities[1] := 5.0;
  DynamicQuantities[2] := 20.25;
  DynamicQuantities[3] := 8.0;
  Total := SumArray(DynamicQuantities);
  Writeln('  합계: ', Total:0:2); // 출력: 합계: 43.75

  Writeln('배열 생성자 리터럴 전달:');
  Total := SumArray([1.1, 2.2, 3.3]);
  Writeln('  합계: ', Total:0:2); // 출력: 합계: 6.60
end;
        

공개 배열 파라미터로 전달된 배열은 함수 내부에서 Low 함수는 항상 0을 반환하고, High 함수는 Length - 1을 반환합니다. 이는 원본 배열의 인덱스 범위와 관계없이 일관된 접근 방식을 제공합니다.