Кодирование декодированных URL в C ++ - PullRequest
0 голосов
/ 06 января 2019

Я хочу декодировать закодированные URL. Например, буква ö кодируется как "%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.

Ответы [ 2 ]

0 голосов
/ 07 января 2019

Спасибо за помощь. Вот что я придумала. Может быть, это поможет кому-то еще

#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;
}

Есть еще возможности для оптимизации, но она работает:)

0 голосов
/ 07 января 2019

В POSIX вы можете распечатать строку UTF8 напрямую:

std::string utf8 = "\xc3\xb6"; // or just u8"ö"
printf(utf8);

В Windows вы должны конвертировать в UTF16. Используйте wchar_t вместо char16_t, даже если char16_t считается правильным. Они оба по 2 байта на символ в Windows.

Вы хотите convert.from_bytes конвертировать из UTF8 вместо convert.to_bytes, который конвертирует в UTF8.

Печать Unicode в консоли Windows - еще одна головная боль. Смотрите соответствующие темы.

Обратите внимание, что 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, должны быть закодированы. Пример: * +1021 *

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...