首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在c++中编码已解码的urls

在c++中编码已解码的urls
EN

Stack Overflow用户
提问于 2019-01-06 17:48:45
回答 2查看 249关注 0票数 0

我想解码编码的urls。例如,字母ö被编码为对应于其十六进制utf-8编码0xc3b6 (50102)的"%C3%B6"

我现在需要知道如何在控制台上将此值打印为ö或将其打印到字符串缓冲区中。

简单地转换为char、wchar_t、char16_t或char32_t并打印为cout或wcout不起作用。

我得到的最接近的是使用它的utf-16表示0x00f6。下面的代码片段打印ö

代码语言:javascript
复制
#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';
}

我现在需要一种从0xc3b6计算0x00f6的方法,或者另一种解码url的方法。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-01-07 08:25:50

在POSIX中,您可以直接打印UTF8字符串:

代码语言:javascript
复制
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已被弃用,并且到目前为止还没有替代品。

代码语言:javascript
复制
#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字符。示例:

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2019-01-07 20:07:11

谢谢你的帮助。这是我想出来的。也许它会帮助其他人

代码语言:javascript
复制
#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;
}

仍然有优化的空间,但它是有效的:)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54060359

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档