2012-04-12 26 views
10

Tôi đang làm việc với các chuỗi, có thể chứa ký tự unicode thay thế (không phải BMP, 4 byte cho mỗi ký tự).Sự cố với các ký tự unicode thay thế trong F #

Khi tôi sử dụng định dạng "\ Uxxxxxxxxv" để chỉ định ký tự thay thế trong F # - đối với một số ký tự, nó cho kết quả khác với trường hợp của C#. Ví dụ:

C#:

string s = "\U0001D11E"; 
bool c = Char.IsSurrogate(s, 0); 
Console.WriteLine(String.Format("Length: {0}, is surrogate: {1}", s.Length, c)); 

Cung cấp: Length: 2, is surrogate: True

F #:

let s = "\U0001D11E" 
let c = Char.IsSurrogate(s, 0) 
printf "Length: %d, is surrogate: %b" s.Length c 

Cung cấp: Length: 2, is surrogate: false

Lưu ý: Một số ký tự thay thế hoạt động trong F # ("\ U0010011", "\ U00100011"), nhưng một số ký tự không hoạt động.

Q: Đây có phải là lỗi trong F # không? Làm thế nào tôi có thể xử lý cho phép các ký tự unicode thay thế trong chuỗi với F # (Liệu F # có định dạng khác nhau, hoặc cách duy nhất là sử dụngChar.ConvertFromUtf32 0x1D11E)

Cập nhật:
s.ToCharArray() cho cho F # [| 0xD800; 0xDF41 |]; cho C# { 0xD834, 0xDD1E }

+0

Đây là những phương pháp khuôn khổ do đó, không khác nhau giữa C# và F #. Các lỗi như một lỗi trình biên dịch xử lý chuỗi ký tự. Tài liệu những gì bạn nhận được ra khỏi s.ToCharArray(). –

+0

1) Char.IsSurrogate có 2 chữ ký - thứ hai cho phép sử dụng chuỗi và vị trí; 2) * let s = '\ U0001D11E' * kết quả trong lỗi biên dịch – Vitaliy

Trả lời

5

Điều đó rõ ràng có nghĩa là F # mắc lỗi khi phân tích cú pháp một số chuỗi ký tự. Điều đó được chứng minh bằng ký tự thực tế mà bạn đã đề cập là không phải BMP, và trong UTF-16 nó phải được biểu diễn như là cặp thay thế. Surrogates là các từ trong phạm vi 0xD800-0xDFFF, trong khi không phải ký tự trong chuỗi sản xuất phù hợp trong phạm vi đó.

Nhưng việc xử lý người thay thế không thay đổi, vì khuôn khổ (cái gì dưới mui xe) là giống nhau.Vì vậy, bạn đã có câu trả lời trong câu hỏi của mình - nếu bạn cần chuỗi ký tự bằng ký tự không phải BMP trong mã của bạn, bạn chỉ nên sử dụng Char.ConvertFromUtf32 thay vì ký hiệu \ UXXXXXXXX. Và tất cả việc xử lý còn lại sẽ giống như mọi khi.

+0

Cảm ơn, và có Char.ConvertFromUtf32 có thể được sử dụng làm giải pháp là một số trường hợp, nó chắc chắn cho giới hạn (Tôi không thể khai báo các ký tự theo cách như vậy trong hằng số) – Vitaliy

+0

Bạn có thể hack các hằng số như sau: '' \ uD834 \ uDD1E'' . Nó không phải là rất dễ đọc, có lẽ nó là tốt hơn để thêm bình luận mô tả những gì đó, nhưng vẫn tốt hơn mà không có gì. –

+0

Cảm ơn - điều này sẽ hoạt động như cách giải quyết – Vitaliy

1

Dường như với tôi rằng đây là điều gì đó được kết nối với các hình thức chuẩn hóa khác nhau. Cả trong C# và F # s.IsNormalized() trả về true Nhưng trong C#

s.ToCharArray() cho chúng ta {55.348, 56.606} // 0xD834, 0xDD1E

và trong F #

s.ToCharArray() cho chúng ta {65.533, 57.422} // 0xFFFD, 0xE04E

Và như bạn có thể biết System.Char.IsSurrogate được thực hiện theo cách sau:

public static bool IsSurrogate(char c) 
    { 
     return (c >= HIGH_SURROGATE_START && c <= LOW_SURROGATE_END); 
    } 

nơi

HIGH_SURROGATE_START = 0x00d800; 
    LOW_SURROGATE_END = 0x00dfff; 

Vì vậy, trong C# đầu tiên char (55.348) nhỏ hơn LOW_SURROGATE_END nhưng trong F # đầu tiên char (65.533) là không ít hơn LOW_SURROGATE_END.

Tôi hy vọng điều này sẽ hữu ích.

+0

Cảm ơn bạn đã mô tả sự cố, do đó, vấn đề bạn nghĩ là với việc chuẩn hóa khác nhau được sử dụng trong F #. Ok, nhưng làm thế nào tôi có thể thêm nhân vật thay thế vào chuỗi với F #, nếu * "\ U0001D11E" * không hoạt động cho tôi? – Vitaliy

+0

Tôi không nghĩ rằng vấn đề này có liên quan đến việc bình thường hóa. Trên thực tế, chuỗi như thế này nên được phân tích cú pháp và trình bày như là, và đó chắc chắn là những gì sẽ xảy ra. –

7

Đây là lỗi đã biết trong trình biên dịch F # được vận chuyển với VS2010 (và SP1); sửa chữa xuất hiện trong các bit VS11, vì vậy nếu bạn có bản Beta VS11 và sử dụng trình biên dịch F # 3.0, bạn sẽ thấy hành vi này như mong đợi.

(Nếu câu trả lời khác/bình luận ở đây không cung cấp cho bạn một cách giải quyết phù hợp trong khi chờ đợi, cho tôi biết.)

+0

Cảm ơn bạn - vâng, giải pháp của @Andriy K hoạt động cho tôi – Vitaliy

Các vấn đề liên quan