11 November 2026•baca 8 menit

Array Dinamis Pascal: Nilai Keenam yang Tidak Pernah Ikut Terhitung

Enam nilai masuk, lima yang terhitung, dan rata-ratanya tercetak 78.0 karena array tetap berhenti membaca di MAX. SetLength memberi array panjang yang diminta datanya, dan ia juga mengubah arti penugasan.

Baca dalam bahasa Inggris

Kamu memberi program enam nilai dan program itu melaporkan lima. Berkas scores.txt berisi 72, 85, 91, 64, 78, dan 67, satu per baris. Program mencetak hitungan 5 dan rata-rata 78.0, tanpa crash dan tanpa peringatan. Rata-rata sebenarnya 76.2, yaitu 457 dibagi 6.

PASCAL
program average;

{ Versi 1: array tetap berisi lima, dan nilai keenam yang tidak pernah masuk. }

const
  MAX = 5;

var
  scores: array[1..MAX] of integer;
  n, i, sum: integer;

begin
  n := 0;
  sum := 0;
  for i := 1 to MAX do
    if not eof then
    begin
      readln(scores[i]);
      n := n + 1;
      sum := sum + scores[i];
    end;
  writeln('count: ', n);
  writeln('mean: ', sum / n:0:1);
end.
Keluaran
$ fpc average.pas && ./average < scores.txt
count: 5
mean: 78.0

Konstanta MAX menghentikan loop for setelah lima pembacaan, dan baris keenam tetap tidak terbaca di dalam berkas. Ukuran array statis ditetapkan saat kamu menulis programnya, dan loop mematuhi ukuran itu tanpa protes. Tidak ada apa pun di berkas maupun di compiler yang menandai baris yang hilang, jadi satu-satunya cara menangkapnya adalah membandingkan keluaran dengan jawaban yang kamu harapkan.

Poin Penting

  • array[1..MAX] yang tetap berhenti membaca di MAX tanpa peringatan, dan begitulah enam nilai menghasilkan rata-rata dari lima nilai.
  • Array dinamis mulai dengan Length 0 dan sama dengan nil; SetLength memberinya panjang, dan elemen baru datang sebagai nol, bukan sebagai sampah.
  • Indeksnya berjalan dari 0 sampai High, sedangkan array[1..5] statis berjalan dari 1 sampai 5.
  • b := a menyalin pointer, jadi menulis lewat b mengubah a; Copy(a, start, count) yang membuat penyimpanan independen.
  • SetLength(a, 0) melepas apa yang ditunjuk a, tetapi variabel kedua yang memegang blok yang sama menjaga datanya tetap hidup sampai referensi terakhir pergi.
  • Tidak ada yang menghentikan penulisan melewati ujung secara bawaan: bangun dengan -Cr untuk mengubahnya menjadi Runtime error 201 alih-alih korupsi diam-diam.

Beri array panjang saat program berjalan

Array dinamis dideklarasikan sebagai array of integer, tanpa batas. Variabelnya mulai kosong: Length-nya 0 dan nilainya sama dengan nil, nilai pointer yang tidak menunjuk ke apa pun. SetLength memberinya ukuran.

PASCAL
program explore;

var
  a, b: array of integer;
  i: integer;

begin
  writeln('before SetLength: Length = ', Length(a), ', a = nil is ', a = nil);
  SetLength(a, 3);
  writeln('after SetLength(a, 3): Length = ', Length(a), ', Low = ', Low(a), ', High = ', High(a));
  write('elements:');
  for i := Low(a) to High(a) do
    write(' ', a[i]);
  writeln;
  writeln('sizeof(a) = ', sizeof(a));
  a[0] := 10;
  a[1] := 20;
  a[2] := 30;
  SetLength(a, 5);
  writeln('grown to 5: Length = ', Length(a), ', kept ', a[0], ' ', a[1], ' ', a[2], ', new ', a[3], ' ', a[4]);
  b := a;
  b[0] := 99;
  writeln('b[0] = 99, a[0] = ', a[0], ', same storage = ', @b[0] = @a[0]);
  SetLength(a, 0);
  writeln('after SetLength(a, 0): Length = ', Length(a), ', a = nil is ', a = nil);
  writeln('b is still ', Length(b), ' elements, b[0] = ', b[0]);
end.
Keluaran
$ fpc explore.pas && ./explore
before SetLength: Length = 0, a = nil is TRUE
after SetLength(a, 3): Length = 3, Low = 0, High = 2
elements: 0 0 0
sizeof(a) = 8
grown to 5: Length = 5, kept 10 20 30, new 0 0
b[0] = 99, a[0] = 99, same storage = TRUE
after SetLength(a, 0): Length = 0, a = nil is TRUE
b is still 5 elements, b[0] = 99

Indeksnya berjalan dari 0 sampai 2, sedangkan array[1..5] berjalan dari 1 sampai 5. Elemen baru bernilai nol, bukan sisa sampah. Membesarkan array dari 3 ke 5 mempertahankan 10 20 30 dan mengisi dua slot baru dengan nol.

sizeof(a) bernilai 8 berapa pun panjangnya, karena variabelnya menyimpan pointer ke data, bukan datanya. array[1..5] of integer statis menempati 10 byte di sini: lima integer masing-masing dua byte, ukuran bawaan Free Pascal. Versi dinamis menggantikan 10 byte itu dengan pointer 8 byte ditambah blok heap, yaitu memori yang diminta program saat ia berjalan.

Dua nama, satu array

Penugasan b := a menyalin pointer, bukan elemennya. Setelah b[0] := 99, a[0] juga terbaca 99, dan @b[0] = @a[0] bernilai TRUE: kedua nama mencapai penyimpanan yang sama. SetLength(a, 0) mengosongkan a, tetapi b masih memegang kelima elemennya. Pascal menghitung referensi ke blok itu dan membebaskannya ketika referensi terakhir pergi.

Copy memberimu penyimpanan yang independen. Copy(a, 1, 3) pada array yang berisi 3 4 5 6 7 8 mengembalikan 4 5 6, karena indeks awalnya berbasis 0 seperti array itu sendiri. Copy(a, 4, 3) hanya mengembalikan 7 8, karena tersisa dua elemen saja. Mengubah elemen pertama salinan menjadi 999 membiarkan aslinya di 3, dan @original[0] = @copy[0] bernilai FALSE.

Pengecualiannya: tidak ada yang menjaga ujung

PASCAL
program probe4;

{ Di luar batas dengan indeks yang tidak bisa dilihat compiler. }

var
  dyn: array of integer;
  i: integer;

begin
  SetLength(dyn, 3);
  i := Length(dyn);
  writeln('writing at index ', i, ' of length ', Length(dyn));
  dyn[i] := 42;
  writeln('survived, dyn[i] = ', dyn[i]);
end.
Keluaran
$ fpc probe4.pas && ./probe4
writing at index 3 of length 3
survived, dyn[i] = 42

Indeks 3 pada array yang panjangnya 3 menulis ke memori yang bukan milik array itu, dan program keluar dengan status 0. Pemeriksaan rentang mati secara bawaan. Bangun dengan -Cr dan penulisan yang sama menghentikan program:

Keluaran
$ fpc -Cr probe4.pas && ./probe4
writing at index 3 of length 3
Runtime error 201 at $00000000004011D9
  $00000000004011D9
  $000000000042308C

Status keluarnya 201. Indeks konstanta tertangkap lebih awal: dengan -Cr, menulis indeks 4 ke array[1..3] yang tetap menghentikan kompilasi dengan Error: range check error while evaluating constants (4 must be between 1 and 3).

Buat pemeriksanya gagal lebih dulu

Simpan ini sebagai check_average.pas. Program ini membaca keluaran sebuah program dari stdin dan membandingkannya dengan dua baris yang diharapkan. Untuk setiap baris ia mencetak PASS atau FAIL, dan baris yang tidak pernah datang dihitung sebagai kegagalan dengan catatan "no such line".

PASCAL
program check_average;

{ Membaca keluaran program dari stdin dan membandingkannya dengan baris yang diharapkan. }

var
  expected: array[1..2] of string;
  line: string;
  i, passed, failed, total: integer;

procedure Report(ok: boolean; n: integer; want, got: string);
begin
  if ok then
  begin
    writeln('PASS  line ', n, ': ', want);
    passed := passed + 1;
  end
  else
  begin
    if got = '' then
      writeln('FAIL  line ', n, ': expected "', want, '", no such line')
    else
      writeln('FAIL  line ', n, ': expected "', want, '", got "', got, '"');
    failed := failed + 1;
  end;
end;

begin
  expected[1] := 'count: 6';
  expected[2] := 'mean: 76.2';

  passed := 0;
  failed := 0;
  total := 2;
  i := 0;

  while (not eof) and (i < total) do
  begin
    readln(line);
    i := i + 1;
    Report(line = expected[i], i, expected[i], line);
  end;

  while i < total do
  begin
    i := i + 1;
    Report(false, i, expected[i], '');
  end;

  writeln;
  writeln(passed, ' of ', total, ' checks passed');
  if failed > 0 then
    ExitCode := 1;
end.

Kompilasi pemeriksa itu dan versi 1 average.pas dengan fpc, lalu salurkan yang satu ke yang lain.

Keluaran
$ ./average < scores.txt | ./check_average
FAIL  line 1: expected "count: 6", got "count: 5"
FAIL  line 2: expected "mean: 76.2", got "mean: 78.0"

0 of 2 checks passed

Pemeriksa keluar dengan status 1 di sini, jadi sebuah skrip bisa memakainya sebagai gerbang.

Beralih ke array dinamis

Ganti average.pas dengan versi 2. Array tetapnya menjadi array of integer, dan SetLength(scores, n + 1) dijalankan sebelum setiap pembacaan.

PASCAL
program average;

{ Versi 2: array tumbuh mengikuti apa pun yang datang. }

var
  scores: array of integer;
  n, sum: integer;

begin
  n := 0;
  sum := 0;
  while not eof do
  begin
    SetLength(scores, n + 1);
    readln(scores[n]);
    sum := sum + scores[n];
    n := n + 1;
  end;
  writeln('count: ', Length(scores));
  writeln('mean: ', sum / n:0:1);
end.

Kompilasi dan jalankan pipa yang sama.

Keluaran
$ ./average < scores.txt | ./check_average
PASS  line 1: count: 6
PASS  line 2: mean: 76.2

2 of 2 checks passed

Pemeriksa sekarang keluar dengan status 0. Versi 2 melaporkan Length(scores) sebagai hitungannya, jadi angkanya datang dari array itu sendiri. Loop tidak punya MAX yang menghentikannya, dan array berakhir sepanjang berkasnya.

Memilih di antara keduanya

Tanyakan siapa yang menentukan jumlahnya. Kalau kamu yang memutuskannya saat menulis program, pakai array[1..N] dengan sebuah konstanta. Kalau datanya yang menentukan, pakai array of dan indeks dari 0. Bangun dengan -Cr selama kamu menguji, karena array dinamis tidak menghentikan penulisan melewati ujungnya secara bawaan.

Biar makin jago ngoding.

Yuk gabung bareng temen-temen developer lainnya buat dapet update teknologi, tips, dan tutorial santai tiap minggu.

Biar Nggak Kudet

Update teknologi, tips ngoding, dan insight santai langsung ke email kamu tiap minggu.

Santai, anti spam. Bisa berhenti langganan kapan aja.

Baca Selanjutnya

Lihat semua
Struktur DataTentang Struktur Data LinkedList

Linked list adalah rantai linear berisi node, dan setiap node menyimpan data plus pointer ke node berikutnya. Ini bentuk rantainya, ongkosnya dibanding array, dan implementasi paling sederhana dalam Java, Python, serta JavaScript.

Untuk developer yang belajar dari kesulitan

© 2026 Inva.dev.