代码之家  ›  专栏  ›  技术社区  ›  Narek

如何输入和输出一些unicode文本?

  •  12
  • Narek  · 技术社区  · 15 年前

    我询问一个代码片段,它将一个unicode文本连接到另一个unicode文本和第一个unicode文本,然后返回结果。

    另外,这段代码将帮助我解决unicode的另一个更大的问题。但关键是完成我的要求。

    5 回复  |  直到 8 年前
        1
  •  7
  •   Philipp    15 年前

    下面的例子展示了四种不同的方法,其中只有第三种(C conio )第四个(原生windowsapi)可以工作(但只有在stdin/stdout没有被重定向的情况下)。请注意,您仍然需要一个包含要显示的字符的字体(Lucida Console至少支持希腊语和西里尔语)。请注意,这里的一切都是完全不可移植的,只是没有可移植的方式在终端上输入/输出Unicode字符串。

    #ifndef UNICODE
    #define UNICODE
    #endif
    
    #ifndef _UNICODE
    #define _UNICODE
    #endif
    
    #define STRICT
    #define NOMINMAX
    #define WIN32_LEAN_AND_MEAN
    
    #include <iostream>
    #include <string>
    #include <cstdlib>
    #include <cstdio>
    
    #include <conio.h>
    #include <windows.h>
    
    void testIostream();
    void testStdio();
    void testConio();
    void testWindows();
    
    int wmain() {
        testIostream();
        testStdio();
        testConio();
        testWindows();
        std::system("pause");
    }
    
    void testIostream() {
        std::wstring first, second;
        std::getline(std::wcin, first);
        if (!std::wcin.good()) return;
        std::getline(std::wcin, second);
        if (!std::wcin.good()) return;
        std::wcout << first << second << std::endl;
    }
    
    void testStdio() {
        wchar_t buffer[0x1000];
        if (!_getws_s(buffer)) return;
        const std::wstring first = buffer;
        if (!_getws_s(buffer)) return;
        const std::wstring second = buffer;
        const std::wstring result = first + second;
        _putws(result.c_str());
    }
    
    void testConio() {
        wchar_t buffer[0x1000];
        std::size_t numRead = 0;
        if (_cgetws_s(buffer, &numRead)) return;
        const std::wstring first(buffer, numRead);
        if (_cgetws_s(buffer, &numRead)) return;
        const std::wstring second(buffer, numRead);
        const std::wstring result = first + second + L'\n';
        _cputws(result.c_str());
    }
    
    void testWindows() {
        const HANDLE stdIn = GetStdHandle(STD_INPUT_HANDLE);
        WCHAR buffer[0x1000];
        DWORD numRead = 0;
        if (!ReadConsoleW(stdIn, buffer, sizeof buffer, &numRead, NULL)) return;
        const std::wstring first(buffer, numRead - 2);
        if (!ReadConsoleW(stdIn, buffer, sizeof buffer, &numRead, NULL)) return;
        const std::wstring second(buffer, numRead);
        const std::wstring result = first + second;
        const HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
        DWORD numWritten = 0;
        WriteConsoleW(stdOut, result.c_str(), result.size(), &numWritten, NULL);
    }
    
    • 编辑1 :我添加了一个基于 .
    • 编辑2 _O_U16TEXT 有点像迈克尔卡普兰的博客中描述的,但似乎只有 wgets 解释来自的(8位)数据 ReadFile 作为UTF-16。我会在周末进一步调查。
        2
  •  11
  •   Post Self    8 年前

    imbue sync_with_stdio 我成功了。试试这个:

    #include <iostream>
    #include <locale>
    #include <string>
    
    using namespace std;
    
    int main() {
        ios_base::sync_with_stdio(false);
        wcin.imbue(locale("en_US.UTF-8"));
        wcout.imbue(locale("en_US.UTF-8"));
    
        wstring s;
        wstring t(L" la Polynésie française");
    
        wcin >> s;
        wcout << s << t << endl;
        return 0;
    }
    
        3
  •  9
  •   Brian R. Bondy    15 年前

    取决于你的意思。我想你的意思是你只是在和 std::wstring 不过。在这种情况下使用 std::wcin std::wcout

    对于编码之间的转换,您可以使用操作系统函数,如Win32: WideCharToMultiByte MultiByteToWideChar 或者你可以使用像 libiconv

        4
  •  0
  •   John    15 年前

    如果您有实际的文本(即,一个逻辑字符字符串),则插入到宽流。宽流将自动对字符进行编码,以匹配区域设置编码所需的位(如果您使用了编码位,则流将对这些位进行解码,然后重新编码以匹配区域设置。)

    如果您知道有UTF编码的位(即,打算解码为逻辑字符字符串的位数组),则有一个较小的解决方案 您知道输出流的目标需要相同的位格式,那么您可以跳过解码和重新编码步骤,按原样写入()位。只有当您知道双方都使用相同的编码格式时,这种方法才有效,对于不打算与其他区域设置中的进程通信的小型实用程序可能就是这种情况。

        5
  •  -1
  •   Edward Strange    15 年前