我想解码编码的网址。例如,字母ö被编码为"%C3%B6"
,对应于其十六进制utf-8编码0xc3b6
(50102)。
现在需要知道如何在控制台上或在字符串缓冲区中以ö形式打印此值。
仅强制转换为char,wchar_t,char16_t或char32_t并打印至cout或wcout无效。
我最近得到的就是使用其utf-16表示形式0x00f6
。以下代码段打印ö
#include <codecvt>
#include <iostream>
#include <locale>
int main() {
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> convert;
std::cout << convert.to_bytes(0x00f6) << '\n';
}
我现在需要从0x00f6
计算0xc3b6
的方法,或另一种对URL进行解码的方法。
答案 0 :(得分:1)
在POSIX中,您可以直接打印UTF8字符串:
std::string utf8 = "\xc3\xb6"; // or just u8"ö"
printf(utf8);
在Windows中,您必须转换为UTF16。即使应该使用wchar_t
,也请使用char16_t
而不是char16_t
。在Windows中,每个字符都是2个字节。
您希望convert.from_bytes
从UTF8转换,而不是convert.to_bytes
从UTF8转换。
在Windows控制台中打印Unicode是另一个麻烦。请参阅相关主题。
请注意,std::wstring_convert
已过时,并且目前没有替代品。
#include <iostream>
#include <string>
#include <codecvt>
#include <windows.h>
int main()
{
std::string utf8 = "\xc3\xb6";
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> convert;
std::wstring utf16 = convert.from_bytes(utf8);
MessageBox(0, utf16.c_str(), 0, 0);
DWORD count;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), utf16.c_str(), utf16.size(), &count, 0);
return 0;
}
编码/解码URL
“ URL安全字符”不需要编码。所有其他字符,包括非ASCII字符,都应进行编码。示例:
std::string encode_url(const std::string& s)
{
const std::string safe_characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
std::ostringstream oss;
for(auto c : s) {
if (safe_characters.find(c) != std::string::npos)
oss << c;
else
oss << '%' << std::setfill('0') << std::setw(2) <<
std::uppercase << std::hex << (0xff & c);
}
return oss.str();
}
std::string decode_url(const std::string& s)
{
std::string result;
for(std::size_t i = 0; i < s.size(); i++) {
if(s[i] == '%') {
try {
auto v = std::stoi(s.substr(i + 1, 2), nullptr, 16);
result.push_back(0xff & v);
} catch(...) { } //handle error
i += 2;
}
else {
result.push_back(s[i]);
}
}
return result;
}
答案 1 :(得分:1)
感谢所有帮助。这是我想出的。也许会帮助别人
#include <iomanip>
#include <iostream>
#include <sstream>
#include <cstdint>
std::string encode_url(const std::string& s) {
std::ostringstream oss;
for (std::uint16_t c : s) {
if (c > 0 && c < 128) {
oss << static_cast<char>(c);
}
else {
oss << '%' << std::uppercase << std::hex << (0x00ff & c);
}
}
return std::move(oss).str();
}
int parse_hex(const std::string& s) {
std::istringstream iss(s);
int n;
iss >> std::uppercase >> std::hex >> n;
return n;
}
std::string decode_url(const std::string& s) {
std::string result;
result.reserve(s.size());
for (std::size_t i = 0; i < s.size();) {
if (s[i] != '%') {
result.push_back(s[i]);
++i;
}
else {
result.push_back(parse_hex(s.substr(i + 1, 2)));
i += 3;
}
}
return result;
}
仍然有优化的余地,但是它可以工作:)