Chuỗi và Tên thân mật

Trong các phần trước bạn được biết về mảng, bất biến, các kiểu cơ bản. Giờ bạn đoán xem mã sau nhắn gửi điều gì:

alias string = immutable(char)[];

Trong D, chính xác là kiểu chuỗi (string) chỉ là tên khác, hay tên thân mật, của kiểu immutable(char)[], diễn giải ra là một bất biến mảng các ký tự, hay cũng vậy, một lát cắt gồm các ký tự.

Vì là bất biến, một chuỗi được hình thành sẽ không thể thay đổi (bất kỳ thay đổi nào cũng làm phát sinh vùng nhớ mới là bản sao của chuỗi ban đầu.) Ứng dụng rất cụ thể của thiết kế này là các chuỗi có thể chia sẻ giữa các luồng xử lý khác nhau.

Vì thực chất chuỗi là lát cắt, bạn có thể làm việc qua các "lăng kính" mà không phát sinh tốn kém bộ nhớ. Ví dụ hàm std.algorithm.splitter tách chuỗi ban đầu thành các phần, nhưng nó kết quả thực tế là nó tạo ra các lăng kính nhỏ hơn chứ không yêu cầu cấp phát thêm bất kỳ vùng nhớ nào.

Lưu ý là kiểu string chỉ thích hợp cho chuỗi UTF-8. Với các bảng mã phức tạp hơn, bạn cần wstring hoặc dstring:

alias wstring = immutable(wchar)[]; // UTF-16
alias dstring = immutable(dchar)[]; // UTF-32

Việc chuyển đổi giữa các kiểu chuỗi này được thực hiện qua hàm to:

import std.conv: to;
dstring myDstring = to!dstring(myString);
string myString   = to!string(myDstring);

Chuỗi ký tự Unicode

Kiểu chuỗi string có thể xem như là mảng gồm các phần tử 8 bit code unit. Các hàm tác động trên chuỗi như thế cũng có tác dụng đối với chuỗi, nhưng ở mức tối thiểu là code unit chứ không phải ở mức ký tự. Ồ, phân biệt ký tựcode unit là việc khó mà bạn cần đọc kỹ hơn nhé.

Cũng vậy, các thuật toán tiêu chuẩn trong D xem string như dải các code point, hoặc grapheme (xem thư viện std.uni.byGrapheme.)

Ví dụ minh họa cho các cách nhìn khác nhau này:

string s = "\u0041\u0308"; // Ä

writeln(s.length); // 3

import std.range : walkLength;
writeln(s.walkLength); // 2

import std.uni : byGrapheme;
writeln(s.byGrapheme.walkLength); // 1

Mảng s có chiều dài thật sự là 3, và gồm 3 code unit 0x41, 0x030x08. Hai code unit cuối có thể gộp là thành code point (bạn có nhớ ký tự unicode tổ hợp?), và hàm walkLength (thuộc bộ thư viện tiêu chuẩn xử lý các dải) hiểu được điều này, nên gộp chúng thành 1 và nhìn mảng s có chiều dài 2. Cùng lúc đó, byGrapheme lại hiểu hai code point như thành phần một ký tự nên chỉ trả về kết quả 1.

Xử lý hợp lý đầu vào Unicode là việc phức tạp, nhưng hầu hết trường hợp bạn chỉ cần quan tâm tới kiểu chuỗi string. Nếu cần quan tâm chi tiết tới từng code unit, bạn có thể xem byCodeUnit.

Việc xử lý các kiểu Unicode khác nhau được mô tả trong Unicode gems chapter.

Chuỗi nhiều dòng

Một chuỗi có thể gồm nhiều dòng

string multiline = "
This
may be a
long document
";

Khi cần phải thể hiện dấu nháy ("), bạn để ý tới chuỗi Wysiwygheredoc.

Chuỗi Wysiwyg

Tốt nhất phần này được hiểu qua các minh họa:

string raw  =  `raw "string"`; // chuỗi "string"
string raw2 = r"raw `string`"; // chuỗi `string`

Còn nhiều cách khác để biểu diễn chuỗi bạn có thể xem ở đây.

Đọc thêm

rdmd playground.d