Tôi cần bất kỳ biểu tượng/chuỗi Unicode nào được nhập chính xác và được xuất ra.
Điều này chắc chắn có thể xảy ra, mặc dù làm cho bảng điều khiển nhắc lệnh Windows đúng cách nhận thức Unicode có một số phép thuật đặc biệt. Tôi nghiêm túc nghi ngờ rằng bất kỳ việc triển khai các chức năng thư viện chuẩn nào sẽ làm điều này, thật không may.
Bạn sẽ tìm thấy một số câu hỏi về nó trên Stack Overflow, nhưng this one is a good one. Về cơ bản, giao diện điều khiển sử dụng những gì được gọi là (phần nào sai) trang mã "OEM" theo mặc định. Bạn muốn thay đổi điều đó thành trang mã UTF-8, giá trị được xác định bởi CP_UTF8
. Để thực hiện việc này, bạn cần phải gọi cả hai chức năng SetConsoleCP
(để đặt đầu vào trang mã) và chức năng SetConsoleOutputCP
(để đặt đầu ra trang mã). Mã sẽ trông giống như sau:
if (!SetConsoleCP(CP_UTF8))
{
// An error occurred; handle it. Call GetLastError() for more information.
// ...
}
if (!SetConsoleOutputCP(CP_UTF8))
{
// An error occurred; handle it. Call GetLastError() for more information.
// ...
}
Để tăng cường độ mạnh, bạn cũng có thể muốn đảm bảo rằng trang mã UTF-8 được hỗ trợ trước, trước khi thử đặt và sử dụng. Bạn sẽ làm điều đó bằng cách gọi hàm IsValidCodePage
. Ví dụ:
if (IsValidCodePage(CP_UTF8))
{
// We're all good, so set the console code page...
}
Bạn cũng sẽ phải thay đổi phông chữ từ mặc định ("Raster Fonts") để một cái gì đó có chứa các ký tự Unicode cần thiết glyphs-ví dụ, Lucida Console hoặc Consolas (reference).. Đó là tầm thường để làm bằng cách sử dụng chức năng SetCurrentConsoleFontEx
.
Thật không may, chức năng này không tồn tại trong các phiên bản Windows trước Vista. Nếu bạn hoàn toàn cần hỗ trợ các hệ điều hành cũ hơn, điều duy nhất tôi biết phải làm là gọi hàm SetConsoleFont
không có giấy tờ. Thông thường, tôi sẽ tư vấn cho mạnh mẽ chống lại việc sử dụng các chức năng không có giấy tờ, nhưng tôi nghĩ rằng vấn đề ở đây ít hơn vì bạn chỉ chỉ sử dụng trong các phiên bản cũ của hệ điều hành.Bạn biết những người đó sẽ không thay đổi. Trên các phiên bản mới hơn có sẵn, bạn gọi hàm được hỗ trợ. Mã mẫu chưa được kiểm tra:
bool IsWinVistaOrLater()
{
OSVERSIONINFOEX osvi;
osvi.dwOSVersionInfoSize = sizeof(osvi);
GetVersionEx(reinterpret_cast<LPOSVERSIONINFO>(&osvi));
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
return osvi.dwMajorVersion >= 6;
}
return false;
}
void SetConsoleToUnicodeFont()
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
if (IsWinVistaOrLater())
{
// Call the documented function.
typedef BOOL (WINAPI * pfSetCurrentConsoleFontEx)(HANDLE, BOOL, PCONSOLE_FONT_INFOEX);
HMODULE hMod = GetModuleHandle(TEXT("kernel32.dll"));
pfSetCurrentConsoleFontEx pfSCCFX = (pfSetCurrentConsoleFontEx)GetProcAddress(hMod, "SetCurrentConsoleFontEx");
CONSOLE_FONT_INFOEX cfix;
cfix.cbSize = sizeof(cfix);
cfix.nFont = 12;
cfix.dwFontSize.X = 8;
cfix.dwFontSize.Y = 14;
cfix.FontFamily = FF_DONTCARE;
cfix.FontWeight = 400; // normal weight
lstrcpy(cfix.FaceName, TEXT("Lucida Console"));
pfSCCFX(hConsole,
FALSE, /* set font for current window size */
&cfix);
}
else
{
// There is no supported function on these older versions,
// so we have to call the undocumented one.
typedef BOOL (WINAPI * pfSetConsoleFont)(HANDLE, DWORD);
HMODULE hMod = GetModuleHandle(TEXT("kernel32.dll"));
pfSetConsoleFont pfSCF = (pfSetConsoleFont)GetProcAddress(hMod, "SetConsoleFont");
pfSCF(hConsole, 12);
}
}
Lưu ý rằng tôi đã thêm lỗi bắt buộc kiểm tra làm bài tập cho người đọc. Trọng tâm ở đây là về kỹ thuật và khả năng đọc; lộn xộn nó với xử lý lỗi sẽ chỉ gây nhầm lẫn vấn đề.
Tôi không biết làm cách nào để thực hiện điều này trên Linux. Tôi nghi ngờ đó là công việc ít hơn rất nhiều, vì mọi người nói với tôi rằng hệ điều hành sử dụng UTF-8 nội bộ. Dù bằng cách nào, bạn đang ở trên của riêng bạn cho điều đó; làm cho Windows purr đủ làm việc cho một câu trả lời!
Chính xác, bạn muốn thay đổi điều gì? Bạn có muốn thay đổi ngôn ngữ của chuỗi không? Ngôn ngữ hệ thống? Ngôn ngữ giao diện người dùng? Hoặc trang mã hoạt động? Đối với luồng, bảng điều khiển hoặc hệ thống? Có rất nhiều tùy chọn, nhiều hơn hàm ý của một hàm 'setlocale' duy nhất. Bạn phải giải thích hiệu ứng * mà bạn muốn xem trước khi chúng tôi có thể cho bạn biết chuyển đổi nào lật. –
@CodyGray, tôi cần bất kỳ biểu tượng/chuỗi Unicode nào được nhập chính xác và được xuất ra. Mô tả đầy đủ này của _effect_? Tôi nghĩ rằng, nó có nghĩa là tôi cần phải thay đổi mã hóa của giao diện điều khiển trong đó chương trình được bắt đầu. –
Nói chung, tôi muốn nói một chương trình không nên sửa đổi ngôn ngữ - nó sẽ hoạt động trong miền địa phương được cung cấp. Nếu không, nó sẽ đánh bại mục đích "quốc tế hóa". –