在C+中将wchar打印到控制台+; 我做了一个简单的程序,它将在PS1存储卡二进制文件中读取,并在VisualStudio中用C++显示控制台中的内容。游戏标题在内存中以Shift JIS格式编码,因此我使用MultiByteToWideChar函数对其进行转换: // Converting Shift-JIS char lTitle[65]; strcpy_s(lTitle, mymemcard[lFrame - 1].title); int lTitleChars = MultiByteToWideChar(932, 0, lTitle, -1, NULL, 0); wchar_t* lTitleL = new wchar_t[lTitleChars]; MultiByteToWideChar(932, 0, lTitle, -1, lTitleL, lTitleChars);

在C+中将wchar打印到控制台+; 我做了一个简单的程序,它将在PS1存储卡二进制文件中读取,并在VisualStudio中用C++显示控制台中的内容。游戏标题在内存中以Shift JIS格式编码,因此我使用MultiByteToWideChar函数对其进行转换: // Converting Shift-JIS char lTitle[65]; strcpy_s(lTitle, mymemcard[lFrame - 1].title); int lTitleChars = MultiByteToWideChar(932, 0, lTitle, -1, NULL, 0); wchar_t* lTitleL = new wchar_t[lTitleChars]; MultiByteToWideChar(932, 0, lTitle, -1, lTitleL, lTitleChars);,c++,visual-studio,shift-jis,C++,Visual Studio,Shift Jis,我的问题是现在无法将lTitleL变量打印到控制台。我试过cout,wcout,printf,wprintf,我不能让它们工作!我知道lTitleL变量PROIPERY具有标题,因为我可以在调试器中看到它。当我调用我尝试过的任何打印函数时,都不会打印任何内容。任何帮助都将不胜感激!谢谢 大编辑: 好的,下面是我的观点: // Converting Shift-JIS to UTF-8 // /////////////////////////////

我的问题是现在无法将lTitleL变量打印到控制台。我试过cout,wcout,printf,wprintf,我不能让它们工作!我知道lTitleL变量PROIPERY具有标题,因为我可以在调试器中看到它。当我调用我尝试过的任何打印函数时,都不会打印任何内容。任何帮助都将不胜感激!谢谢

大编辑:

好的,下面是我的观点:

            // Converting Shift-JIS to UTF-8 //
            ///////////////////////////////////
            // First, convert the multi-byte Shift-JIS format into wide characters
            strcpy_s(lTitle, mymemcard[lFrame - 1].titleMB);
            lTitleChars = MultiByteToWideChar(932, 0, lTitle, -1, NULL, 0);
            wchar_t* lTitleFW = new wchar_t[lTitleChars];
            MultiByteToWideChar(932, 0, lTitle, -1, lTitleFW, lTitleChars);
            wprintf(L"FW, WriteConsoleW - ");
            WriteConsoleW(consoleHandle, lTitleFW, lTitleChars, NULL, 0);
            wprintf(L"\n");
            // Memory card seems to store all characters in their "Full Width" forms, we need to convert them to Half-Width so they display nicely in the console
            wchar_t* lTitleHW = new wchar_t[lTitleChars];
            LCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_HALFWIDTH, lTitleFW, lTitleChars, lTitleHW, lTitleChars, NULL, NULL, 0);
            wprintf(L"HW, WriteConsoleW - ");
            WriteConsoleW(consoleHandle, lTitleHW, lTitleChars, NULL, 0);
            wprintf(L"\n");
            wprintf(L"HW, wprintf()     - %s\n", lTitleHW);
            // Now we can convert it into UTF-8 format to allow it to be printed using std::cout
            // This step isn't necessary as we could call WriteConsoleW on lTitleHW instead, but why not
            lTitleChars = WideCharToMultiByte(CP_UTF8, 0, lTitleHW, -1, NULL, 0, NULL, NULL);
            char* lTitleUTF = new char[lTitleChars];
            WideCharToMultiByte(CP_UTF8, 0, lTitleHW, -1, lTitleUTF, lTitleChars, NULL, NULL);
            strcpy_s(mymemcard[lFrame - 1].titleUTF, lTitleUTF);
            wprintf(L"UTF, wprintf()    - %S\n\n", lTitleUTF);
            delete[] lTitleFW;
            delete[] lTitleHW;
            delete[] lTitleUTF;
            ///////////////////////////////////
  • MultiByteToWideChar将Shift JIS输入字符串转换为wide 查斯
  • 将其打印到控制台进行调试
  • 现在的问题是PS1存储卡以全宽形式存储所有字符,所以我使用LCMapStringEX将它们转换为半宽,以获得更好的输出
  • 将其打印到控制台进行调试
  • 如果我乐意使用WriteConsoleW,这就足够了,但如果不是这样的话,一个问题是某些标点符号的编码很奇怪,并且使用std::wcout或wprintf()无法很好地打印出来。例如,连字符存储为U+FF70-“半宽片假名-平假名延长音标”(转换为半宽后),无论使用何种字体,这些字符都显示为问号(但是,它们使用WriteConsoleW正确打印)
  • 因此,我现在可以使用WideChartMultiByte,使用UTF-8代码页获得字符串的一个版本,该版本可以使用std::wcout或wprintf()很好地打印到控制台。但是,我必须调用SetConsoleCP(65001)和SetConsoleOutputCP(65001)才能正确打印,否则多字节字符(如我提到的U+FF70)将逐字节打印
  • 最后,对于任何不寻常的字符显示,我需要有一个字体选择,可以显示他们。在我的控制台中,我发现只有NSimSun和SimSun ExtB可以使用默认字体,其他字体似乎都不包含日语字符(至少对于U+FF70字符)
为了帮助可视化此操作的输出,以下是使用NSimSun字体的控制台屏幕截图:

这里是ConsoleAS字体:

现在我要问的是:我并不特别喜欢NSimSun字体,有没有其他更像Consolas字体的字体包含全半角日语字符的所有字形?如果是这样的话,我如何将它们打包到我的控制台应用程序中,使其可移植


谢谢

Windows对在控制台上打印Unicode的支持有限。使用
MessageBoxW(0,lTitleL,0,0)
测试您的转换,只要转换正常,它就保证成功

要打印到控制台窗口,您必须调用
\u setmode(\u fileno(stdout),\u O\u U16TEXT)
以打印ASCII范围以外的字符

坚持使用
std::wcout
wprintf(L“%s”,str)

如果控制台不支持正确的字体,则会出现另一个问题。你必须尝试不同的字体。见下面的例子。也可以考虑使用<代码> STD::WSCONT/<代码>,它具有自动清除功能。
#include <iostream>
#include <string>
#include <io.h> 
#include <fcntl.h> 
#include <Windows.h>

int main()
{
    const wchar_t *src = L"ABC 日本語";

    int size;
    size = WideCharToMultiByte(932, 0, src, -1, NULL, 0, 0, 0);
    std::string temp(size, 0);
    WideCharToMultiByte(932, 0, src, -1, temp.data(), size, 0, 0);

    size = MultiByteToWideChar(932, 0, temp.data(), -1, 0, 0);
    std::wstring dst(size, 0);
    MultiByteToWideChar(932, 0, temp.c_str(), -1, dst.data(), size);

    _setmode(_fileno(stdout), _O_U16TEXT);

    wprintf(L"%s\n", dst.c_str());

    //Try with different font
    CONSOLE_FONT_INFOEX font = { sizeof(font) };
    HANDLE hcout = GetStdHandle(STD_OUTPUT_HANDLE);
    GetCurrentConsoleFontEx(hcout, FALSE, &font);
    wcscpy_s(font.FaceName, L"MS Gothic");
    SetCurrentConsoleFontEx(hcout, FALSE, &font);
    std::wcout << dst << "\n";

    return 0;
}
#包括
#包括
#包括
#包括
#包括
int main()
{
常数wchar_t*src=L“ABC日本語";
整数大小;
大小=宽图表多字节(932,0,src,-1,NULL,0,0,0);
标准:字符串温度(大小,0);
宽图表多字节(932,0,src,-1,temp.data(),size,0,0);
size=MultiByteToWideChar(932,0,temp.data(),-1,0,0);
std::wstring dst(大小,0);
MultiByteToWideChar(932,0,temp.c_str(),-1,dst.data(),size);
_setmode(_fileno(stdout),_O_16text);
wprintf(L“%s\n”,dst.c_str());
//尝试使用不同的字体
CONSOLE_FONT_INFOEX FONT={sizeof(FONT)};
句柄hcout=GetStdHandle(标准输出句柄);
GetCurrentConsoleFontEx(hcout、FALSE和font);
wcscpy_s(字体名称,L“MS哥特式”);
SetCurrentConsoleFontEx(hcout、FALSE和font);

std::wcout查看从地址0x013055d0开始的内存内容。您看到了什么?@TonyK我已回复编辑。谢谢!我对Windows了解不够,但这可能取决于控制台中使用的编码。在Linux中,我会将宽字符转换为UTF-8并打印结果。可能这与此相关?>控制台不是su支持通用Windows平台(UWP)应用程序。我已添加了另一个编辑,并对该情况进行了更新。感谢Barmak,我将对问题进行大编辑,以更新我的最新进展。编辑已启动!你不应该这样更改你的问题。请阅读有关如何提问的帮助部分。问题和答案应该对其他访问者有用s、 我保留了原始问题的完整性。我的编辑提供了问题的部分解决方案,因此对未来的访问者有用,并且与问题的标题相关。您的问题是关于打印Unicode,但似乎您已将其更改为关于字体的问题。我不知道您是否遵循了我的建议。我已经解决了这个问题e字体选项。您应该发布一个关于字体的新问题,或者搜索现有主题。
AddFontMemResourceEx
允许在一个进程中使用字体,但我认为这不适用于控制台应用程序,因此您可能必须单独安装字体。