2008-12-01 76 views
44

Mã hóa chuẩn của mã nguồn C++ là gì? Liệu các tiêu chuẩn C + + thậm chí nói một cái gì đó về điều này? Tôi có thể viết nguồn C++ bằng Unicode không?Sử dụng mã nguồn Unicode trong C++

Ví dụ: tôi có thể sử dụng các ký tự không phải ASCII như ký tự tiếng Trung trong nhận xét không? Nếu vậy, toàn bộ Unicode được cho phép hay chỉ là một tập hợp con của Unicode? (ví dụ: trang đầu tiên 16 bit hoặc bất kỳ trang nào được gọi.)

Hơn nữa, tôi có thể sử dụng Unicode cho chuỗi không? Ví dụ:

Wstring str=L"Strange chars: â Țđ ě €€"; 
+0

* RE: "mọi thứ được gọi là": * [Từ Wikipedia] (https://en.wikipedia.org/wiki/Plane_%28Unicode%29#Basic_Multilingual_Plane): Mặt phẳng đầu tiên, ** mặt phẳng 0 **, ** Basic Multilingual Plane (BMP) ** chứa các ký tự cho hầu hết các ngôn ngữ hiện đại và một số lượng lớn các ký hiệu. Mục tiêu chính của BMP là hỗ trợ thống nhất các bộ ký tự trước cũng như ký tự viết. Hầu hết các điểm mã được chỉ định trong BMP được sử dụng để mã hóa các ký tự ** Trung Quốc **, ** Nhật Bản ** và ** Hàn Quốc (CJK) **. – DavidRR

Trả lời

33

Mã hóa bằng C++ khá phức tạp một chút. Đây là sự hiểu biết của tôi về nó.

Mọi triển khai đều phải hỗ trợ các ký tự từ bộ ký tự nguồn cơ bản. Chúng bao gồm các ký tự phổ biến được liệt kê trong §2.2/1 (§2.3/1 trong C++ 11). Những nhân vật này phải phù hợp với một char. Ngoài ra, việc triển khai phải hỗ trợ cách đặt tên cho các ký tự khác bằng cách gọi là universal-character-names và trông giống như \uffff hoặc \Uffffffff và có thể được sử dụng để chỉ các ký tự Unicode. Một tập con của chúng có thể sử dụng được trong các mã định danh (được liệt kê trong Phụ lục E).

Điều này thật tuyệt, nhưng ánh xạ từ các ký tự trong tệp, đến ký tự nguồn (được sử dụng tại thời gian biên dịch) được thực hiện xác định. Điều này tạo thành mã hóa được sử dụng. Đây là những gì nó nói theo nghĩa đen (C++ 98 phiên bản):

ký tự file nguồn vật lý là ánh xạ, trong một thực hiện xác định cách, với nhân vật nguồn cơ bản bộ (giới thiệu nhân vật mới dòng đối với các chỉ báo cuối dòng) nếu cần . Các chuỗi Trigraph (2.3) được thay thế bằng các biểu diễn nội bộ đơn lẻ tương ứng. Bất kỳ tệp nguồn nào ký tự không nằm trong nguồn cơ bản bộ ký tự (2.2) được thay thế bằng tên ký tự phổ quát mà des- kích hoạt ký tự đó.(An thực hiện có thể sử dụng bất kỳ mã hóa nội bộ, miễn là một thực tế ký tự mở rộng gặp phải trong file nguồn, và cùng mở rộng nhân vật thể hiện bằng các nguồn tập tin như một ký tự tên phổ biến (ví dụ sử dụng \ uXXXX ký hiệu), được xử lý tương đương.)

Đối với gcc, bạn có thể thay đổi bằng cách sử dụng tùy chọn -finput-charset=charset. Ngoài ra, bạn có thể thay đổi ký tự thực hiện được sử dụng để represet giá trị khi chạy. Tùy chọn thích hợp cho điều này là -fexec-charset=charset cho char (mặc định là utf-8) và -fwide-exec-charset=charset (mặc định là utf-16 hoặc utf-32 tùy thuộc vào kích thước của wchar_t).

9

Tiêu chuẩn C++ không nói bất kỳ điều gì về mã hóa tệp mã nguồn, cho đến giờ tôi biết.

Mã hóa thông thường là (hoặc từng là) ASCII 7 bit - một số trình biên dịch (ví dụ Borland) sẽ balk tại các ký tự ASCII sử dụng bit cao. Không có lý do kỹ thuật nào mà các ký tự Unicode không thể được sử dụng, nếu trình biên dịch và trình soạn thảo của bạn chấp nhận chúng - hầu hết các công cụ dựa trên Linux hiện đại và nhiều trình soạn thảo dựa trên Windows tốt hơn, xử lý mã hóa UTF-8 mà không có vấn đề gì, mặc dù tôi 'không chắc chắn rằng trình biên dịch của Microsoft sẽ.

EDIT: Dường như trình biên dịch của Microsoft sẽ chấp nhận file Unicode mã hóa, nhưng đôi khi sẽ tạo ra lỗi trên 8-bit ASCII quá:

warning C4819: The file contains a character that cannot be represented 
in the current code page (932). Save the file in Unicode format to prevent 
data loss. 
+0

Nó sắp xếp. Tôi không nghĩ rằng nó ngăn chặn hoặc cho phép unicode rõ ràng, nhưng đây là bộ ký tự cho phép tối thiểu: http://www.csci.csusb.edu/dick/c++std/cd2/lex.html#lex.charset –

+0

Kể từ khi C++ Builder2007, trình biên dịch Borland/Codegear đã hỗ trợ các tệp nguồn unicode: tức là các chuỗi ký tự Unicode, các chú thích unicode. IDe đã đấu tranh một chút với họ, nhưng trình biên dịch của hạnh phúc! – Roddy

+0

Điều Borland tôi đã đề cập từ khoảng hai mươi năm trước (lần cuối cùng tôi thử đặt một ký tự ASCII cao trong một tệp mã nguồn). :-) Tôi đã không sử dụng một trình biên dịch Borland trong khoảng mười năm. –

3

Đối với mã hóa trong chuỗi Tôi nghĩ rằng bạn có nghĩa là để sử dụng \ u ký hiệu, ví dụ:

std::wstring str = L"\u20AC"; // Euro character 
0

AFAIK Không được tiêu chuẩn hóa vì bạn có thể đặt bất kỳ loại ký tự nào trong chuỗi rộng. Bạn chỉ cần kiểm tra xem trình biên dịch của bạn có được đặt thành mã nguồn Unicode để làm cho nó hoạt động đúng không.

2

Cũng cần lưu ý rằng các ký tự rộng trong C++ không thực sự là chuỗi Unicode như vậy. Chúng chỉ là các chuỗi ký tự lớn hơn, thường là 16, nhưng đôi khi là 32 bit. Tuy nhiên, đây là định nghĩa thực hiện, IIRC bạn có thể có8 bit Bạn không có bảo đảm thực sự về mã hóa trong đó, vì vậy nếu bạn đang cố gắng làm một việc như xử lý văn bản, có thể bạn sẽ muốn một typedef nhiều nhất loại số nguyên thích hợp cho thực thể Unicode của bạn.

C++ 1x có hỗ trợ thêm unicode dưới dạng UTF-8 xâu mã hóa (u8"text"), và UTF-16 và UTF-32 kiểu dữ liệu (char16_tchar32_t IIRC) cũng như các hằng chuỗi tương ứng (u"text"U"text"). Mã hóa trên các ký tự được chỉ định mà không có hằng số \uxxxx hoặc \Uxxxxxxxx vẫn được xác định theo mặc định (và không hỗ trợ mã hóa cho các loại chuỗi phức tạp bên ngoài các chữ)

+0

Không phải chữ thường 'u' chỉ có nghĩa là ký tự? – Tomasito665

6

Có hai vấn đề ở đây. Đầu tiên là các ký tự được cho phép trong mã C++ (và các chú thích), chẳng hạn như các tên biến. Thứ hai là những ký tự được cho phép trong chuỗi và chuỗi ký tự.

Như đã lưu ý, trình biên dịch C++ phải hỗ trợ bộ ký tự ASCII rất hạn chế cho các ký tự được phép trong mã và nhận xét. Trong thực tế, bộ ký tự này không hoạt động tốt với một số bộ ký tự châu Âu (và đặc biệt là với một số bàn phím Châu Âu không có vài ký tự - như dấu ngoặc vuông), vì vậy khái niệm về hình ảnh và hình chữ nhật giới thiệu. Nhiều trình biên dịch chấp nhận nhiều hơn ký tự này vào lúc này, nhưng không có bất kỳ sự bảo đảm nào.

Đối với chuỗi và chuỗi ký tự, C++ có khái niệm về ký tự rộng và chuỗi ký tự rộng. Tuy nhiên, mã hóa cho tập ký tự đó không được xác định. Trong thực tế nó hầu như luôn luôn là Unicode, nhưng tôi không nghĩ rằng có bất kỳ sự bảo đảm nào ở đây. Các chuỗi ký tự chuỗi ký tự rộng trông giống như chữ "chuỗi chữ", và chúng có thể được gán cho std :: wstring's.


C++ 11 bổ sung hỗ trợ rõ ràng cho các chuỗi Unicode và xâu, mã hóa theo UTF-8, UTF-16 về cuối lớn, UTF-16 little endian, UTF-32 về cuối lớn và UTF-32 little endian .

9

Ngoài bài đăng của litb, MSVC++ cũng hỗ trợ Unicode. Tôi hiểu nó được mã hóa Unicode từ BOM. Nó chắc chắn hỗ trợ mã như int (*♫)(); hoặc const std::set<int> ∅; Nếu bạn thực sự vào mã obfuscuation:

typedef void ‼; // Also known as \u203C 
class ooɟ { 
    operator ‼() {} 
}; 
+1

Điều này có thể hữu ích cho việc viết, ví dụ, phần mềm toán học nơi mã nguồn có thể được căn chỉnh với tài liệu nguồn. Bạn có thể làm điều này trong Java, chấp nhận mã nguồn UTF-8. Tuy nhiên, đối với C++ (và C) có thể có các vấn đề về cách các mã thông báo không phải ASCII được chuyển đổi thành các tên biểu tượng, nó phải tương thích với phần còn lại của hệ điều hành - không chỉ là một tính năng của trình biên dịch. Đối với C++, điều này có thể được gộp lại bằng tên mangling. –

2

Trong bối cảnh này, nếu bạn nhận được MSVC++ cảnh báo C4819, chỉ cần thay đổi các tập tin nguồn mã hóa để "UTF-8 với Bom" .

GCC 4.1 không hỗ trợ điều này, nhưng GCC 4.4 thực hiện và phiên bản Qt mới nhất sử dụng GCC 4.4, vì vậy hãy sử dụng "UTF-8 với Bom" làm mã nguồn tệp.