【问题标题】:Unicode characters become question marks (C++ and MFC Dialog Based App)Unicode 字符变成问号(基于 C++ 和 MFC 对话框的应用程序)
【发布时间】:2023-03-13 14:41:01
【问题描述】:

这些代码将值设置为编辑框。但是当我从 MySQL 表中检索 Unicode 字符时遇到了麻烦。

例如,字符串nüşabə 设置为nüşabÉ™

这是我的代码。

void CmysqlDlg::OnBnClickedButton3()
{
    USES_CONVERSION;

    try
    {
        mysql::MySQL_Driver *driver = new mysql::MySQL_Driver;
        Connection *dbConn;
        Statement *st;
        ResultSet *res;

        driver = mysql::get_mysql_driver_instance();
        dbConn = driver->connect("tcp://127.0.0.1:3306", "root", "connection");
        dbConn->setSchema("mfc_app_database");

        st = dbConn->createStatement();
        res = st->executeQuery("SELECT password FROM users WHERE id=1");
        string z;
        while (res->next())
        {
            //k = res->getString("username");
            //cs.Format(_T("%s"), k);
            //CString cs(k.c_str(), CP_UTF8);
            //combo.AddString(cs);
            //usernameData.SetWindowTextW(cs);

            z = res->getString("password");
            CString pass(z.c_str()/*, CP_UTF8*/);
            nameData.SetWindowTextW(pass);
        }


        delete res;
        delete st;
        delete dbConn;
        delete driver;
    }
    catch (exception e)
    {
        ofstream file("sadaasad.txt");
        file << e.what();
        file.close();
    }
}

数据库排序规则设置为utf8_general_ci。 其实我也不知道该怎么办……脑子停了……

请帮忙。谢谢。

【问题讨论】:

  • 我希望你知道你是slicing the caught exception
  • @chris 感谢您的快速回复。但我无法理解你的意思。你能解释一下吗?
  • 捕获异常为catch (exception const &amp; e)
  • @RichardCritten 我试过了。但也不例外。程序在不停止工作的情况下运行。
  • @coni,这只是代码的一个问题。您捕获异常的方法不会尊重任何派生异常类所做的覆盖。

标签: c++ mysql unicode mfc


【解决方案1】:

如果为 UNICODE 编译 MFC,CString 将使用UTF16 encoding 定义为wchar_t 的字符串。

像您一样直接从char* 构造CString,仅当所有字符都在UNICODE 的ASCII 子集中时才有效:

  • 一旦 unicode char 不是 ASCII,它将以 UTF8 编码为几个字节,但 CString 构造函数随后将其解释为两个不同的字符。
  • nüşabəüşə 就是这种情况,它们在 UTF8 中都需要 2 个字节,并导致 CString 比预期的长 3 个字符。

因此,当您在 char* 中有一个 UTF8 编码的字符串时,您需要按照 this SO answer 中的说明使用 MultiByteToWideChar() 对其进行转换。

编辑:代码示例

代替

        CString pass(z.c_str());

你可以这样写:

        wchar_t *p = new wchar_t[z.size()+1];  // UTF16 has same length or less thant UTF8 equivalent
        MultiByteToWideChar(
             CP_UTF8,         // CodePage,
             0,               // flags,
             z.c_str(),       // pointer to UTF8 string
             -1,              // -1 for null terminated string, size otherwise 
             p,               // destination buffer for converted wchar_t string 
             z.size()+1);        // size of buffer
        CString pass(p);
        delete p; 

请注意,MultiByteToWideChar() 及其反向 WideCharToMultiByte() 属于 Windows API 而不是 MFC。

请注意,标准 C++ 字符串具有可移植的标准转换函数:

 wstring_convert<codecvt_utf8_utf16<wchar_t>, wchar_t> conversion;
 wstring s = conversion.from_bytes(z.c_str());
 string mbs = conversion.to_bytes(L"\u00c6\u0186"); 

【讨论】:

  • 感谢您的回答。它看起来很有帮助,但实际上我不知道如何编写这段代码:(
  • @coni 我已经编辑了一些代码来展示如何做到这一点。
  • 哦,亲爱的,非常非常非常非常非常非常感谢。它解决了我的问题。我的天啊!再次感谢!
猜你喜欢
  • 1970-01-01
  • 2011-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-12
  • 2014-02-01
  • 1970-01-01
相关资源
最近更新 更多