Length
trả về số phần tử khi xem chuỗi là mảng.
- Đối với chuỗi có loại phần tử 8 bit (ANSI, UTF-8) thì
Length
cho bạn số byte vì số byte giống với số lượng phần tử.
- Đối với các chuỗi có phần tử 16 bit (UTF-16) thì
Length
là một nửa số byte vì mỗi phần tử rộng 2 byte.
Chuỗi của bạn '1 ¢' có hai điểm mã, nhưng điểm mã thứ hai yêu cầu hai byte để mã hóa nó trong UTF-8. Do đó, Length(Utf8String('1¢'))
đánh giá thành ba.
Bạn đề cập đến SizeOf
trong tiêu đề câu hỏi. Việc chuyển một biến chuỗi thành SizeOf
sẽ luôn trả về kích thước của một con trỏ, vì biến chuỗi là, dưới mui xe, chỉ là một con trỏ.
Để câu hỏi cụ thể của bạn:
Tại sao sự khác biệt trong việc xử lý luôn luôn ở đó?
Chỉ có sự khác biệt nếu bạn nghĩ về Length
liên quan đến byte. Nhưng đó là cách sai lầm để suy nghĩ về nó Length
luôn luôn trả về một số phần tử, và khi được xem theo cách đó, có hành vi là thống nhất trên tất cả các loại chuỗi, và thực sự trên tất cả các loại mảng.
Tại sao Length() không làm những gì được mong đợi, chỉ trả về độ dài của tham số (như trong số lượng phần tử) thay vì cho kích thước tính bằng byte trong một số trường hợp?
Nó luôn trả về số phần tử. Nó chỉ xảy ra khi kích thước phần tử là một byte đơn, sau đó đếm phần tử và số byte xảy ra giống nhau. Trong thực tế, tài liệu mà bạn tham chiếu cũng chứa các phần sau ngay trên đoạn trích mà bạn đã cung cấp: Trả về số ký tự trong một chuỗi hoặc các phần tử trong một mảng. Đó là văn bản chính. Đoạn trích mà bạn đưa vào có nghĩa là minh họa cho các tác động của văn bản in nghiêng này.
Tại sao tiểu bang phân chia kết quả bằng 2 cho chuỗi Unicode (UTF-16)? AFAIK UTF-16 tối đa là 4 byte và do đó điều này sẽ cho kết quả không chính xác.
Yếu tố ký tự UTF-16 luôn rộng 16 bit. Tuy nhiên, một số điểm mã Unicode yêu cầu hai yếu tố ký tự để mã hóa. Các cặp yếu tố nhân vật này được gọi là cặp thay thế.
Bạn đang hy vọng, tôi nghĩ rằng, Length
sẽ trả về số điểm mã trong chuỗi. Nhưng nó không. Nó trả về số lượng các phần tử ký tự. Và đối với các bảng mã có độ dài thay đổi, số lượng các điểm mã không nhất thiết giống như số lượng các phần tử ký tự. Nếu chuỗi của bạn được mã hóa dưới dạng UTF-32 thì số lượng các điểm mã sẽ giống với số phần tử ký tự vì UTF-32 là một mã hóa có kích thước không đổi.
Cách nhanh chóng để đếm các điểm mã là quét qua chuỗi kiểm tra các cặp thay thế. Khi bạn gặp một cặp thay thế, hãy đếm một điểm mã. Nếu không, khi bạn gặp phải một phần tử ký tự không phải là một phần của cặp thay thế, hãy đếm một điểm mã. Trong mã giả:
N := 0;
for C in S do
if C.IsSurrogate then
inc(N)
else
inc(N, 2);
CodePointCount := N div 2;
Một điểm khác cần thực hiện là số điểm mã không giống với số ký tự hiển thị. Một số điểm mã được kết hợp các ký tự và được kết hợp với các điểm mã lân cận của chúng để tạo thành một ký tự có thể nhìn thấy hoặc glyph.
Cuối cùng, nếu tất cả các bạn đang hy vọng làm là tìm ra kích thước byte payload chuỗi, sử dụng biểu thức này:
Length(S) * SizeOf(S[1])
biểu hiện này làm việc cho tất cả các loại chuỗi.
Hãy rất cẩn thận về chức năng System.SysUtils.ByteLength
. Đối mặt với nó, điều này dường như chỉ là những gì bạn muốn. Tuy nhiên, hàm đó trả về độ dài byte của chuỗi được mã hóa UTF-16. Vì vậy, nếu bạn vượt qua nó AnsiString
, giả sử, sau đó giá trị được trả về bởi ByteLength
gấp đôi số byte của AnsiString
.
thử 'LenInBytes: = Độ dài (UTF8Encode ('строка'))' hoặc 'var u8: UTF8String; u8: = 'строка'; I: = Length (u8) '- không có typecast –
Tôi đã viết điều này bởi vì nó theo nghĩa đen được viết bằng tên của mã hóa bao nhiêu nó cần để mã hóa một nhân vật. Tôi chỉ nhầm lẫn với mã hóa khác. – ZzZombo
Tôi đã hoàn nguyên tất cả các chỉnh sửa của bạn. Chủ yếu là bởi vì tôi không đặc biệt muốn tiếp tục cập nhật câu trả lời của mình cho phù hợp! ;-) Dù sao, tôi nghĩ rõ ràng là bạn đang ở trên đầu trang của điều này ngay bây giờ. Câu hỏi là một câu hỏi hay. Chúng ta không thể để nó như thế được. –