C++中对含扩展ASCII的std::string进行URL编码的实现方法
我来帮你一步步搞定这个问题——先解决编码转换的坑,再实现字节遍历和URL编码,确保能被JavaScript的decodeURIComponent完美解码。
第一步:将Windows-1252编码的
std::string转换为UTF-8 你的原始字符串是基于Windows-1252的扩展ASCII字符,而decodeURIComponent只认UTF-8编码的URL字符串,所以第一步必须完成编码转换。下面是利用MultiByteToWideChar和WideCharToMultiByte的正确实现:
#include <string> #include <windows.h> std::string windows1252ToUtf8(const std::string& windows1252Str) { // 第一步:Windows-1252转UTF-16(宽字符) int wideCharLen = MultiByteToWideChar(CP_WINDOWS_1252, 0, windows1252Str.c_str(), -1, nullptr, 0); if (wideCharLen == 0) { // 可根据需求替换为异常抛出或其他错误处理 return ""; } std::wstring wideStr(wideCharLen, L'\0'); int convertResult = MultiByteToWideChar(CP_WINDOWS_1252, 0, windows1252Str.c_str(), -1, wideStr.data(), wideCharLen); if (convertResult == 0) { return ""; } // 第二步:UTF-16转UTF-8 int utf8Len = WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), -1, nullptr, 0, nullptr, nullptr); if (utf8Len == 0) { return ""; } std::string utf8Str(utf8Len, '\0'); convertResult = WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), -1, utf8Str.data(), utf8Len, nullptr, nullptr); if (convertResult == 0) { return ""; } // 移除转换时自动添加的末尾空字符 if (!utf8Str.empty() && utf8Str.back() == '\0') { utf8Str.pop_back(); } return utf8Str; }
第二步:遍历UTF-8字符串的单个字节并做URL编码
拿到UTF-8字符串后,遍历字节非常简单——std::string在MSVC里每个char对应一个字节,直接遍历即可。接下来要按照URL编码规则处理每个字节:
- ASCII安全字符(字母、数字、
-_.~)直接保留 - 其他字符(包括非ASCII的UTF-8字节)转成
%XX的十六进制格式
实现代码如下:
#include <sstream> #include <iomanip> std::string urlEncodeUtf8(const std::string& utf8Str) { std::ostringstream oss; oss << std::hex << std::uppercase; // 输出大写十六进制,小写也可兼容JS解码 for (unsigned char byte : utf8Str) { // 用unsigned char避免符号扩展问题 // 判断是否为URL安全ASCII字符 if ((byte >= 'A' && byte <= 'Z') || (byte >= 'a' && byte <= 'z') || (byte >= '0' && byte <= '9') || byte == '-' || byte == '_' || byte == '.' || byte == '~') { oss << byte; } else { // 转成%XX格式,补0确保两位十六进制 oss << '%' << std::setw(2) << std::setfill('0') << static_cast<int>(byte); } } return oss.str(); }
第三步:整合测试与字节遍历示例
把两个函数结合起来,就能得到可以直接给JS解码的URL编码字符串。如果只是单纯想遍历UTF-8的每个字节,直接用范围for循环即可:
#include <iostream> int main() { std::string originalStr = "čáě"; // 假设此字符串为Windows-1252编码 std::string utf8Str = windows1252ToUtf8(originalStr); std::string encodedStr = urlEncodeUtf8(utf8Str); // 遍历并输出UTF-8的每个字节(十六进制) std::cout << "UTF-8字节序列:"; for (unsigned char byte : utf8Str) { std::cout << std::hex << std::uppercase << static_cast<int>(byte) << " "; } std::cout << "\nURL编码结果:" << encodedStr << std::endl; // 此时encodedStr传给JS后,decodeURIComponent("%C4%8D%C3%A1%C4%9B")会得到"čáě" return 0; }
内容的提问来源于stack exchange,提问作者freemanovec
相关产品推荐
相关产品推荐

