我怎么能cin和cout一些unicode文本?

时间:2010-07-08 20:28:15

标签: c++ windows unicode console

我问一个代码片段,其中包含一个unicode文本,将另一个unicode one连接到第一个unicode文本,然后将cout连接到结果。

P.S。这段代码将帮助我解决unicode的另一个更大的问题。但在关键是要完成我的要求之前。

ADDED:BTW我在运行可执行文件时无法在命令行中写入任何unicode符号。我应该怎么做?

5 个答案:

答案 0 :(得分:8)

取决于你的意思是什么类型的unicode。我认为你的意思是你只是在与std::wstring合作。在这种情况下,请使用std::wcinstd::wcout

对于编码之间的转换,您可以使用您的操作系统功能,例如Win32:WideCharToMultiByteMultiByteToWideChar,或者您可以使用像libiconv这样的库

答案 1 :(得分:7)

过去我遇到了类似的问题,在我的情况下imbuesync_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;
}

答案 2 :(得分:6)

这是一个示例,显示了四种不同的方法,其中只有第三种(C conio)和第四种(本机Windows API)工作(但仅当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 :我添加了基于conio的方法。
  • 编辑2 :我在Michael Kaplan的博客中描述了_O_U16TEXT,但似乎只有wgets解释了(8位)来自ReadFile的数据为UTF-16。我会在周末进一步调查这一点。

答案 3 :(得分:0)

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

如果你知道你有UTF编码的比特(即,要被解码成一串逻辑字符的比特数组),那么有一个较小的解决方案 AND 你知道输出的目标stream期望完全相同的位格式,然后您可以跳过解码和重新编码步骤并按原样写入()位。这仅在您知道双方使用相同的编码格式时才有效,对于不打算与其他语言环境中的进程通信的小实用程序可能就是这种情况。

答案 4 :(得分:-1)

这取决于操作系统。如果您的操作系统了解您可以直接发送UTF-8序列。