Mảng

Mảng trong D có thể là mảng động hoặc mảng tĩnh. Việc sử dụng mảng luôn phải đảm bảo các chặn trên dưới được đảm bảo, về bản chất là ngăn chặn truy cập ra ngoài vùng nhớ đang được cấp phát cho mảng. Việc truy cập ngoài chặn (trên, dưới) sẽ phát sinh lỗi RangeError và làm chương trình dừng lại. Nếu đủ dũng cảm, bạn có thể yêu cầu trình biên dịch bỏ qua việc kiểm tra chặn bằng chỉ thị -boundscheck=off: việc này có thể giúp chương trình chạy nhanh hơn với cái giá phải trả là sự mất an toàn :)

Mảng tĩnh

Vùng nhớ cấp phát cho mảng tĩnh bên trong một hàm nằm trên bộ nhớ stack, còn cho các mảng tĩnh khác thì thuộc về vùng nhớ tĩnh. Lý do là mảng tĩnh có kích thước (bộ nhớ) cố định mà trình biên dịch có thể biết được ngay. Ví dụ với khai báo

int[8] arr;

thì arr kiểu int[8]. Trái với C/++, kích thước được chỉ ra ngay sau kiểu của từng phần tử trong mảng.

Mảng động

Vùng nhớ cấp phát cho mảng động nằm trên heap, và có thể co dãn lúc chương trình đang chạy. Mảng động được khai báo với new

int size = 8; // biến thay đổi lúc chạy
int[] arr = new int[size];

Kiểu của arrint[], là một lát cắt trên bộ nhớ. Chi tiết về lát cắt có trong phần sau; tạm thời bạn hiểu đó là một khối liên tục trên bộ nhớ máy tính.

Mảng nhiều chiều được khai báo như trong ví dụ auto arr = new int[3][3].

Phép toán và thuộc tính trên mảng

Dùng ~ để nối hai mảng với nhau, kết quả là mảng động mới.

Các phép toán cơ bản như cộng, trừ, ... có thể áp dụng trên toàn bộ mảng có cú pháp đơn giản như ví dụ c[] = a[] + b[]; trong ví dụ này, kết quả là mảng c sao cho c[0] = a[0] + b[0], c[1] = a[1] + b[1], v.v... Bạn cũng có thể dùng cú pháp sau

a[] *= 2; // nhân mỗi phần tử với 2
a[] %= 26; // chia mô-đun-lô mỗi phần từ cho 26

Các phép toán kiểu này có thể được trình biên dịch lựa chọn dịch qua các mã máy sử dụng các chỉ thị đặc biệt của bộ vi xử lý có hỗ trợ tính toán trên mảng.

Cả mảng động và tĩnh đều có thuộc tính .length chỉ kích thước (số phần tử) của mảng. Đối với mảng tĩnh, thuộc tính đó chỉ để đọc, không thể thay đổi. Với mảng động, có thể dùng .length để co dãn mảng.

Thuộc tính .dup sao chép một mảng (việc sao chép trên bộ nhớ thực sự diễn ra nhé!)

Mỗi phần tử của mảng được truy cập nhờ cú pháp chỉ số arr[idx]. Thay cho .length bạn có thể dùng ký hiệu tắt $, ví dụ arr[$ - 1] tương đương với arr[arr.length - 1] là phần tử cuối cùng bên phải của mảng.

Bài tập

Hoàn thiện hàm encrypt để mã hóa tin đầu vào theo kiểu Caesar. Để đơn giản, ta giả định rằng tin đầu vào chỉ gồm các ký tự trong dải từ a tới z.

Lời giải tham khảo có ở đây.

Đọc thêm

rdmd playground.d