C++ Cin和getline赢得';无法正确保存非ascii字符

C++ Cin和getline赢得';无法正确保存非ascii字符,c++,unicode,utf-8,ascii,C++,Unicode,Utf 8,Ascii,我正在尝试打开一个路径包含非ascii字符的文件。用户将文件拖到cmd中,我用getline获得路径。 当我尝试使用用户提供的路径打开文件时,它不起作用 #include <iostream> #include <string> #include <fstream> #include <cstdlib> using namespace std; int main() { string userInput; //Saves the u

我正在尝试打开一个路径包含非ascii字符的文件。用户将文件拖到cmd中,我用getline获得路径。 当我尝试使用用户提供的路径打开文件时,它不起作用

#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>

using namespace std;

int main() {
    string userInput;   //Saves the user input
    string autoInput = "C:\\Espolón\\file.txt"; //Specifying the path like this works
    ifstream file1; //For opening the file with the userInput
    ifstream file2; //For opening the file with autoInput

    getline(cin, userInput);

    system("CLS");  //Clears the CMD

    file1.open(userInput);  //This throws an error. Note that I didn't use is_open for cleaner code but im actually using it in my tests
    file2.open(autoInput);  //This works perfectly


    cout << "User input: " + userInput << endl<<"Auto input: " + autoInput << endl; //Both show correctly in the CMD
    system("pause");
}
#包括
#包括
#包括
#包括
使用名称空间std;
int main(){
字符串userInput;//保存用户输入
string autoInput=“C:\\Espolón\\file.txt”;//像这样指定路径很有效
ifstream file1;//用于使用userInput打开文件
ifstream file2;//用于使用自动输入打开文件
getline(cin,userInput);
系统(“CLS”);//清除命令
file1.open(userInput);//这会引发一个错误。请注意,我没有使用is_open for cleaner代码,但实际上我在测试中使用了它
file2.open(autoInput);//这非常有效

coutWindows API需要UTF16LE格式的Unicode,而不是UTF8格式。宽字符串字符和函数在Windows中被视为UTF16

字母
ó
是ANSI,而不是ASCII。Windows也支持ANSI。如果程序在自己的计算机上运行,通常可以使用ANSI,但即使这样,也会遇到问题。如果希望使用ANSI,请尽量不要将其与UTF16和宽字符串格式(
std::wstring
)混合使用

Windows 8和10对UTF8的控制台支持有限。但是如果您想避免UTF8的缺陷,建议使用UTF16

以下是UTF16版本:

#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <io.h> 
#include <fcntl.h> 

using namespace std;

int main()
{
    _setmode(_fileno(stdout), _O_U16TEXT);
    _setmode(_fileno(stdin), _O_U16TEXT);

    wstring userInput;  
    wstring autoInput = L"C:\\Espolón\\file.txt";
    ifstream file1, file2;

    getline(wcin, userInput);

    file1.open(userInput);
    file2.open(autoInput);
    wcout << L"file1: " << (file1.good() ? L"good\n" : L"bad\n");
    wcout << L"file2: " << (file1.good() ? L"good\n" : L"bad\n");

    wcout << L"User input: " + userInput << endl;
    wcout << L"Auto input: " + autoInput << endl;
    system("pause");

    return 0;
}

看看你有没有尝试过使用宽字符版本的
std::string
cout
cin
?对我来说,你的代码很有效。(即使是第一个版本)@ThomasMatthews是的!这在第二个代码块中。@n314159您是否尝试过使用非ascii字符的路径?您使用的是哪种IDE?我使用的是Visual Studio Community 2019。它可以工作!感谢您完整且内容丰富的回答:)不客气,但我的回答还远远不够完整。对于Windows和Uni,这个主题有点混乱代码。请参阅更新的答案和其他参考资料。
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <io.h> 
#include <fcntl.h> 

using namespace std;

int main()
{
    _setmode(_fileno(stdout), _O_U16TEXT);
    _setmode(_fileno(stdin), _O_U16TEXT);

    wstring userInput;  
    wstring autoInput = L"C:\\Espolón\\file.txt";
    ifstream file1, file2;

    getline(wcin, userInput);

    file1.open(userInput);
    file2.open(autoInput);
    wcout << L"file1: " << (file1.good() ? L"good\n" : L"bad\n");
    wcout << L"file2: " << (file1.good() ? L"good\n" : L"bad\n");

    wcout << L"User input: " + userInput << endl;
    wcout << L"Auto input: " + autoInput << endl;
    system("pause");

    return 0;
}
//need at least c++11 for writable std::string::data()
std::string get_u8(const std::wstring u16)
{
    if(u16.empty()) return std::string();
    int size = WideCharToMultiByte(CP_UTF8, 0, u16.c_str(), -1, 0, 0, 0, 0);
    std::string u8(size, 0);
    WideCharToMultiByte(CP_UTF8, 0, u16.c_str(), -1, u8.data(), size, 0, 0);
    return u8;
}

std::wstring get_u16(const std::string u8)
{
    if(u8.empty()) return std::wstring();
    int size = MultiByteToWideChar(CP_UTF8, 0, u8.c_str(), -1, 0, 0);
    std::wstring u16(size, 0);
    MultiByteToWideChar(CP_UTF8, 0, u8.c_str(), -1, u16.data(), size);
    return u16;
}