WideCharToMultiByte的一次debug

windows编程中做字符串转换的一次错误总结

在windows客户端开发时,我想通过windows的WideCharToMultiByte实现将std::wstring转为std::string的功能,但是将输出的std::string转给sqlpp11时发生了报错。

报错分析

Sqlite3 error: Could not prepare statement: unrecognized token: "'123456" (statement was >>INSERT INTO account (id,avatar,name) VALUES('123456

这段报错说明,我传入的sql语句发生了截断,往前分析就是一个普通的wstring类型往string类型做了一次转换。

错误代码

下边这段代码是造成问题的代码

std::string WstringToString(const std::wstring& wstr) {
    if (wstr.empty()) return "";

    // 获取所需缓冲区大小(不包括 null 终止符)
    int bufferSize = WideCharToMultiByte(
        CP_UTF8,
        0,
        wstr.c_str(),
        //static_cast<int>(wstr.size()), // 使用实际长度,不是 -1
        -1,
        nullptr,
        0,
        nullptr,
        nullptr
    );

    if (bufferSize == 0) {
        throw std::runtime_error("宽字符转多字节失败");
    }

    std::string str;
    str.resize(bufferSize); // 只分配必要长度,不填充 0

    int result = WideCharToMultiByte(
        CP_UTF8,
        0,
        wstr.c_str(),
        //static_cast<int>(wstr.size()),
        -1,
        &str[0],
        bufferSize,
        nullptr,
        nullptr
    );

    if (result == 0) {
        throw std::runtime_error("宽字符转多字节失败");
    }

    return str;
}

修复后代码

只要把默认的-1换成实际的长度即可。当传入-1的时候,他会把全部的缓冲区读进去,包括字符串结尾的’\0‘。最后输出的字符串也就包括了结尾的\0,导致sql识别异常。

std::string WstringToString(const std::wstring& wstr) {
    if (wstr.empty()) return "";

    // 获取所需缓冲区大小(不包括 null 终止符)
    int bufferSize = WideCharToMultiByte(
        CP_UTF8,
        0,
        wstr.c_str(),
        static_cast<int>(wstr.size()), // 使用实际长度,不是 -1
        nullptr,
        0,
        nullptr,
        nullptr
    );

    if (bufferSize == 0) {
        throw std::runtime_error("宽字符转多字节失败");
    }

    std::string str;
    str.resize(bufferSize); // 只分配必要长度,不填充 0

    int result = WideCharToMultiByte(
        CP_UTF8,
        0,
        wstr.c_str(),
        static_cast<int>(wstr.size()),
        &str[0],
        bufferSize,
        nullptr,
        nullptr
    );

    if (result == 0) {
        throw std::runtime_error("宽字符转多字节失败");
    }

    return str;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值