C ++到wstring的字符串打印错误,无法获取unicode路径

时间:2019-01-12 10:02:31

标签: c++ unicode wstring

#include <iostream>
#include <Windows.h>
#include <locale>
#include <string>
#include <codecvt>
typedef wchar_t* LPWSTR, *PWSTR;

template <typename Facet>
struct deletable_facet : Facet
{
    using Facet::Facet;
};

int main(int argc, char *argv[])
{
    std::cout << argv[0] << std::endl;

    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
    //std::wcout << converter.from_bytes(argv[0]) << std::endl; // range error


    std::wstring_convert<deletable_facet<std::codecvt<wchar_t, char, std::mbstate_t>>> conv;
    std::wstring ns = conv.from_bytes(argv[0]);
    std::wcout << ns << std::endl;

    wchar_t filename[MAX_PATH];
    //GetModuleFileName(NULL,filename,MAX_PATH); // cant convert wstring_t* to char*
    GetModuleFileNameW(NULL,filename,MAX_PATH);
    std::wcout << filename << std::endl;


    getchar();
    return 0;
}

输出:

 C:\Users\luka\Desktop\ⁿ?icΣ\unicode.exe
 C:\Users\luka\Desktop\ⁿ?icΣ\unicode.exe
 C:\Users\luka\Desktop\ⁿ

该文件夹的实际名称为üлicä

大约2个小时以来,我一直在尝试许多不同的方法,据我所见,人们建议使用GetModuleFileName,但是您可以看到返回转换错误(typedef wchar_t * LPWSTR,* PWSTR;尚未修复)。

那么有什么方法可以获取unicode中的当前文件夹路径,并将其余的输入参数获取为unicode(非拉丁字符)

4 个答案:

答案 0 :(得分:1)

GetModuleFileName的用法正确。您应该使用MessageBoxW(0, filename, 0, 0);

查看预期结果

问题出在Windows控制台上打印L"üлicä"

尝试在控制台上打印"üлicä"

int main(int argc, char *argv[])
{
    DWORD count;
    std::wstring str = GetCommandLineW() + (std::wstring)L"\n";
    WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str.c_str(), str.size(), &count, 0);
    MessageBoxW(0, str.c_str(), 0, 0);

    wchar_t filename[MAX_PATH];
    GetModuleFileNameW(0, filename, MAX_PATH);
    WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), filename, wcslen(filename), &count, 0);
    return 0;
}

在Visual Studio中,您还可以使用_setmode启用std::wcout/std::wcin

您还具有可选的入口点wmain(int argc, wchar_t *argv[]),它以UTF16编码提供argv

main入口点以ANSI编码(不是UTF8编码)提供argv。与Unicode不同,ANSI可以释放信息。

答案 1 :(得分:0)

这可能与程序无关,但与控制台有关,我建议您尝试输出到文件中并检查编码是否正确。

您可以使用freopen

int main(int argc, char *argv[]){ freopen("output-file-name.txt", "w", stdout); /*rest of code*/ }

如果问题仍然存在,请按照以下说明在使用_setmode(..., _O_U16TEXT)之前尝试将Visual Studio与wcout一起使用:https://stackoverflow.com/a/9051543/9541897

答案 2 :(得分:0)

以下是适用于Windows的示例。您必须找到正确的编译器/链接器设置,以支持MinGW上的wmain,但是它将起作用。 _setmode可以直接将Unicode写入终端,并且只要字体支持字符就可以使用。在我的示例中,我使用了一些中文,我的字体支持:

#include <Windows.h>
#include <iostream>
#include "fcntl.h"
#include "io.h"

int wmain(int argc, wchar_t* argv[])
{
    _setmode(_fileno(stdout), _O_U16TEXT);
    std::wcout << argv[0] << std::endl;

    wchar_t filename[MAX_PATH];
    GetModuleFileNameW(NULL,filename,MAX_PATH);
    std::wcout << filename << std::endl;

    return 0;
}

输出:

马克.exe
C:\üлicä\马克.exe

答案 3 :(得分:0)

为什么要手动键入LPWSTRPWSTRwindows.h已经为您处理了。

无论如何,如@ n.m。在注释中说,main()的参数未在Windows上以UTF-8编码,因此使用UTF8-> UTF16转换器转换非ASCII字符将不会产生正确的输出。请使用Win32 MultiByteToWideChar()函数来转换参数,并使用CP_ACP作为要转换的代码页。或者,使用wmain()代替,它以wchar_t*而不是char*的形式提供参数。

这将为您提供所需的数据。然后,您只需要处理将Unicode输出到控制台的问题。正如其他答案所指出的那样,Windows控制台默认情况下不支持通过std::wcout通过UTF-16输出,因此您必须跳过一些附加的步骤才能使其正常工作(StackOverflow上还有很多其他有关该问题的问题)。