我有一个 std::string 包含正常的字母和数字,但所有标点符号(例如括号、方括号、逗号和冒号)都在它们的 ASCII 表示中(例如、%28
和%29
)。 %2C
%3A
解析我的字符串、保留“普通”字符并将十六进制值转换为它们的 ASCII 表示的最快方法是什么?
您可以使用例如该find
功能来搜索'%'
字符。如果接下来的两个字符是十六进制数字,则将这三个字符替换为实际字符。在你找到'%'
.
您可以遍历字符串,将普通字符附加到另一个字符串,而不是进行就地替换,当您到达 a 时,'%'
您检查它是否是有效的 URL 转义,并将正确的字符附加到输出字符串。
libcurl 具有curl_easy_unescape功能:
char *curl_easy_unescape( CURL * curl , char * url ,
int inlength , int * outlength );
此函数将给定的 URL 编码输入字符串转换为“纯字符串”并将其返回到分配的内存区域。所有经过 URL 编码的输入字符(%XX,其中 XX 是两位十六进制数)都将转换为其二进制版本。
这是一个就地版本:
void unescape(std::string & s)
{
for (std::size_t r = 0, w = 0; r != s.size(); )
{
char digit;
if (s[r] != '%')
{
++r;
++w;
}
else if (r + 1 < s.size() && s[r + 1] == '%')
{
r += 2;
++w;
}
else if (r + 2 < s.size()) && is_hex(s, r + 1, digit))
{
s[w] = digit;
++w;
r += 3;
}
else
{
// error, throw exception?
}
}
s.erase(s.begin() + r, s.end());
}
bool is_hex(std::string const & s, std::size_t offset, char & result)
{
unsigned char d1, d2;
if (hex_digit(s[offset], d1) && hex_digit(s[offset + 1], d2))
{
result = d1 * 16 + d2;
return true;
}
return false;
}
bool hex_digit(char c, unsigned char & value)
{
if (c >= '0' && c <= '9') { value = c - '0'; return true; }
if (c >= 'a' && c <= 'f') { value = c - 'a' + 10; return true; }
if (c >= 'A' && c <= 'F') { value = c - 'A' + 10; return true; }
return false;
}