Кодировать/декодировать URL-адреса в C++

Кто-нибудь знает какой-нибудь хороший код C++, который делает это?


person user126593    schedule 30.09.2008    source источник
comment
Как насчет принятия ответа?   -  person gsamaras    schedule 14.07.2016


Ответы (19)


На днях я столкнулся с кодировкой половины этой проблемы. Недовольный доступными вариантами, я, взглянув на пример кода C, решил отказаться от моя собственная функция кодирования URL-адреса С++:

#include <cctype>
#include <iomanip>
#include <sstream>
#include <string>

using namespace std;

string url_encode(const string &value) {
    ostringstream escaped;
    escaped.fill('0');
    escaped << hex;

    for (string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) {
        string::value_type c = (*i);

        // Keep alphanumeric and other accepted characters intact
        if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
            escaped << c;
            continue;
        }

        // Any other characters are percent-encoded
        escaped << uppercase;
        escaped << '%' << setw(2) << int((unsigned char) c);
        escaped << nouppercase;
    }

    return escaped.str();
}

Реализация функции декодирования оставлена ​​читателю в качестве упражнения. :П

person xperroni    schedule 17.07.2013
comment
Я считаю более общим (более правильным) заменить ' ' на %20. Я соответственно обновил код; не стесняйтесь откатиться, если вы не согласны. - person Josh Kelley; 15.07.2014
comment
Нет, я согласен. Также воспользовался возможностью удалить этот бессмысленный вызов setw(0) (в то время я думал, что минимальная ширина останется установленной, пока я не изменю ее обратно, но на самом деле она сбрасывается после следующего ввода). - person xperroni; 16.07.2014
comment
На самом деле, это не преобразует «+» в пробел, поэтому происходит сбой. - person xryl669; 03.02.2015
comment
Разве вы не имеете в виду обратное – преобразовать пробел в '+'? В любом случае, прочитайте первый комментарий Джоша Келли, пробелы преобразуются в «% 20», что тоже хорошо. - person xperroni; 04.02.2015
comment
Мне пришлось добавить std::uppercase к экранированной строке ‹‹ '%' ‹‹ std::uppercase ‹‹ std::setw(2) ‹‹ int((unsigned char) c); В случае, если другие люди задаются вопросом, почему это возвращает, например, %3a вместо %3A - person gumlym; 11.09.2015
comment
@gumlym, это не обязательно. Согласно RFC 3984: шестнадцатеричные цифры в верхнем регистре от "A" до "F" эквивалентны строчные цифры от «а» до «f» соответственно. - person oferei; 29.09.2015
comment
Что ж, мне пришлось сделать это, когда я пытался закодировать URL-адрес, чтобы создать подпись для amazon aws, и это не сработало, когда оно вернуло нижний регистр, это сработало в верхнем регистре. Вот поэтому я и выложил - person gumlym; 29.09.2015
comment
На самом деле RFC также говорит, что [f] для согласованности производители URI и нормализаторы должны использовать шестнадцатеричные цифры верхнего регистра для всех процентных кодировок. Так что это разумное изменение. - person xperroni; 30.09.2015
comment
Одна вещь, которую мы должны добавить для потомков. Этот ответ обрабатывает Unicode! Есть много таких решений, которые этого не делают. - person Jonathan Henson; 20.02.2016
comment
Я не вижу смысла проверять c ›= 0 в условном выражении. Символы берутся из текстовой строки, которая должна содержать только допустимые коды символов. Единственный случай, когда он может содержать отрицательные значения, это если строка будет повреждена, или если ввод будет преднамеренно создан, чтобы нарушить функцию — и в обоих случаях вы также можете захотеть завершить работу программы. - person xperroni; 21.02.2016
comment
Это выглядит неправильно, потому что строки UTF-8 не поддерживаются (w3schools.com/tags/ref_urlencode.asp< /а>). Вроде работает только для Windows-1252 - person Skywalker13; 01.12.2016
comment
Проблема была как раз isalnum(c), надо менять на isalnum((unsigned char) c) - person Skywalker13; 01.12.2016
comment
Обратите внимание, что тип символа уже параметризован для строки value_type. Если вы хотите поддерживать UTF-8, правильным изменением будет замена ссылок на std::string, например, на std::u8string в С++ 20. - person xperroni; 20.12.2018
comment
инициализацию цикла for можно заменить на for (string::value_type c: value) вместе с чередованием первой инструкции - person Stavros Avramidis; 06.06.2019

Отвечая на мой собственный вопрос...

libcurl имеет curl_easy_escape для кодирования.

Для декодирования curl_easy_unescape

person user126593    schedule 30.09.2008
comment
Вы должны принять этот ответ, чтобы он отображался вверху (и людям было проще найти его). - person Mouagip; 04.11.2015
comment
вам нужно использовать curl, чтобы это работало, и вам нужно освободить память - person xinthose; 05.11.2017
comment
Связанный с этим вопрос: почему unescape curl не справляется с заменой «+» на пробел? Разве это не стандартная процедура при декодировании URL? - person Stéphane; 27.05.2019

string urlDecode(string &SRC) {
    string ret;
    char ch;
    int i, ii;
    for (i=0; i<SRC.length(); i++) {
        if (int(SRC[i])==37) {
            sscanf(SRC.substr(i+1,2).c_str(), "%x", &ii);
            ch=static_cast<char>(ii);
            ret+=ch;
            i=i+2;
        } else {
            ret+=SRC[i];
        }
    }
    return (ret);
}

не лучший, но работает нормально ;-)

person Community    schedule 28.01.2011
comment
Конечно, вы должны использовать '%' вместо 37. - person John Zwinck; 27.05.2014
comment
Это не преобразует «+» в пробел - person xryl669; 03.02.2015

cpp-netlib имеет функции

namespace boost {
  namespace network {
    namespace uri {    
      inline std::string decoded(const std::string &input);
      inline std::string encoded(const std::string &input);
    }
  }
}

они позволяют очень легко кодировать и декодировать строки URL.

person Yuriy Petrovskiy    schedule 15.08.2014
comment
омг спасибо. документация по cpp-netlib скудна. У вас есть ссылки на хорошие шпаргалки? - person user249806; 13.05.2017

Обычно добавление '%' к значению int символа не будет работать при кодировании, предполагается, что значение равно шестнадцатеричному эквиваленту. например, '/' - это '%2F', а не '%47'.

Я думаю, что это лучшее и лаконичное решение как для кодирования, так и для декодирования URL-адресов (без особых зависимостей заголовков).

string urlEncode(string str){
    string new_str = "";
    char c;
    int ic;
    const char* chars = str.c_str();
    char bufHex[10];
    int len = strlen(chars);

    for(int i=0;i<len;i++){
        c = chars[i];
        ic = c;
        // uncomment this if you want to encode spaces with +
        /*if (c==' ') new_str += '+';   
        else */if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') new_str += c;
        else {
            sprintf(bufHex,"%X",c);
            if(ic < 16) 
                new_str += "%0"; 
            else
                new_str += "%";
            new_str += bufHex;
        }
    }
    return new_str;
 }

string urlDecode(string str){
    string ret;
    char ch;
    int i, ii, len = str.length();

    for (i=0; i < len; i++){
        if(str[i] != '%'){
            if(str[i] == '+')
                ret += ' ';
            else
                ret += str[i];
        }else{
            sscanf(str.substr(i + 1, 2).c_str(), "%x", &ii);
            ch = static_cast<char>(ii);
            ret += ch;
            i = i + 2;
        }
    }
    return ret;
}
person tormuto    schedule 30.04.2015
comment
if(ic < 16) new_str += "%0"; Для чего это питание?? @тормуто @reliasn - person KriyenKP; 20.02.2017
comment
@Kriyen используется для заполнения закодированного HEX начальным нулем, если в результате получается одна буква; так как от 0 до 15 в HEX это от 0 до F. - person tormuto; 02.03.2017
comment
Такой подход мне нравится больше всего. +1 за использование стандартных библиотек. Хотя есть две проблемы, которые нужно исправить. Я чех и использовал букву ý. Результат: %0FFFFFFFC3%0FFFFFFBD. Во-первых, использование переключателя 16 не требуется, поскольку utf8 гарантирует, что все конечные байты начинаются с 10, и, похоже, это не помогло моему мультибайту. Второй проблемой является FF, потому что не все компьютеры имеют одинаковое количество бит на целое число. Исправление состояло в том, чтобы пропустить переключатель 16 (не нужен) и получить последние два символа из буфера. (Я использовал stringstream, так как мне удобнее использовать строковый буфер). Еще поставил точку. Рамка тоже нравится - person Volt; 26.12.2017
comment
@Volt, не могли бы вы опубликовать обновленный код в новом ответе? Вы упоминаете проблемы, но информации недостаточно для очевидного решения. - person gregn3; 31.05.2018
comment
У этого ответа есть некоторые проблемы, потому что он использует strlen. Во-первых, это не имеет смысла, потому что мы уже знаем размер строкового объекта, так что это пустая трата времени. Однако гораздо хуже то, что строка может содержать 0 байтов, которые будут потеряны из-за strlen. Кроме того, if(i‹ 16) неэффективен, потому что это может быть покрыто самим printf с помощью %%%02X. И, наконец, c должен быть байтом без знака, иначе вы получите эффект, описанный @Volt с ведущим «0xFFF...». - person Devolus; 11.01.2019

[Режим некроманта включен]
Наткнулся на этот вопрос, когда искал быстрое, современное, независимое от платформы и элегантное решение. Не понравилось ничего из вышеперечисленного, cpp-netlib был бы победителем, но он имеет ужасную уязвимость памяти в «декодированной» функции. Поэтому я придумал решение для повышения духовной ци/кармы.

namespace bsq = boost::spirit::qi;
namespace bk = boost::spirit::karma;
bsq::int_parser<unsigned char, 16, 2, 2> hex_byte;
template <typename InputIterator>
struct unescaped_string
    : bsq::grammar<InputIterator, std::string(char const *)> {
  unescaped_string() : unescaped_string::base_type(unesc_str) {
    unesc_char.add("+", ' ');

    unesc_str = *(unesc_char | "%" >> hex_byte | bsq::char_);
  }

  bsq::rule<InputIterator, std::string(char const *)> unesc_str;
  bsq::symbols<char const, char const> unesc_char;
};

template <typename OutputIterator>
struct escaped_string : bk::grammar<OutputIterator, std::string(char const *)> {
  escaped_string() : escaped_string::base_type(esc_str) {

    esc_str = *(bk::char_("a-zA-Z0-9_.~-") | "%" << bk::right_align(2,0)[bk::hex]);
  }
  bk::rule<OutputIterator, std::string(char const *)> esc_str;
};

Использование вышеуказанного следующим образом:

std::string unescape(const std::string &input) {
  std::string retVal;
  retVal.reserve(input.size());
  typedef std::string::const_iterator iterator_type;

  char const *start = "";
  iterator_type beg = input.begin();
  iterator_type end = input.end();
  unescaped_string<iterator_type> p;

  if (!bsq::parse(beg, end, p(start), retVal))
    retVal = input;
  return retVal;
}

std::string escape(const std::string &input) {
  typedef std::back_insert_iterator<std::string> sink_type;
  std::string retVal;
  retVal.reserve(input.size() * 3);
  sink_type sink(retVal);
  char const *start = "";

  escaped_string<sink_type> g;
  if (!bk::generate(sink, g(start), input))
    retVal = input;
  return retVal;
}

[Режим некроманта выключен]

EDIT01: исправлено заполнение нулями — особая благодарность Хартмуту Кайзеру
EDIT02: Live on CoLiRu

person kreuzerkrieg    schedule 16.04.2015

CGICC включает методы кодирования и декодирования URL. form_urlencode и form_urldecode

person alanc10n    schedule 30.09.2008
comment
вы только что вызвали приличный разговор в нашем офисе с этой библиотекой. - person J.J.; 30.09.2008
comment
Это на самом деле самый простой и правильный код. - person xryl669; 03.02.2015

Я остановился на этом вопросе при поиске API для декодирования URL-адреса в приложении Win32 С++. Поскольку в вопросе не совсем указана платформа, предполагается, что окна не так уж плохи.

InternetCanonicalizeUrl — это API для программ Windows. Подробнее здесь

        LPTSTR lpOutputBuffer = new TCHAR[1];
        DWORD dwSize = 1;
        BOOL fRes = ::InternetCanonicalizeUrl(strUrl, lpOutputBuffer, &dwSize, ICU_DECODE | ICU_NO_ENCODE);
        DWORD dwError = ::GetLastError();
        if (!fRes && dwError == ERROR_INSUFFICIENT_BUFFER)
        {
            delete lpOutputBuffer;
            lpOutputBuffer = new TCHAR[dwSize];
            fRes = ::InternetCanonicalizeUrl(strUrl, lpOutputBuffer, &dwSize, ICU_DECODE | ICU_NO_ENCODE);
            if (fRes)
            {
                //lpOutputBuffer has decoded url
            }
            else
            {
                //failed to decode
            }
            if (lpOutputBuffer !=NULL)
            {
                delete [] lpOutputBuffer;
                lpOutputBuffer = NULL;
            }
        }
        else
        {
            //some other error OR the input string url is just 1 char and was successfully decoded
        }

InternetCrackUrl (здесь ) также, кажется, имеет флаги, чтобы указать, следует ли декодировать URL-адрес

person moonlightdock    schedule 04.01.2012

Вдохновленный xperroni, я написал декодер. Спасибо за указатель.

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

char from_hex(char ch) {
    return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
}

string url_decode(string text) {
    char h;
    ostringstream escaped;
    escaped.fill('0');

    for (auto i = text.begin(), n = text.end(); i != n; ++i) {
        string::value_type c = (*i);

        if (c == '%') {
            if (i[1] && i[2]) {
                h = from_hex(i[1]) << 4 | from_hex(i[2]);
                escaped << h;
                i += 2;
            }
        } else if (c == '+') {
            escaped << ' ';
        } else {
            escaped << c;
        }
    }

    return escaped.str();
}

int main(int argc, char** argv) {
    string msg = "J%C3%B8rn!";
    cout << msg << endl;
    string decodemsg = url_decode(msg);
    cout << decodemsg << endl;

    return 0;
}

edit: удалены ненужные cctype и iomainip.

person kometen    schedule 15.09.2015
comment
Блок if (c == '%') требует дополнительной проверки выхода за границы, i[1] и/или i[2] могут находиться за пределами text.end(). Я бы тоже переименовал escaped в unescaped. экранированный.заполнить('0'); скорее всего ненужно. - person roalz; 23.03.2018
comment
Пожалуйста, посмотрите на мою версию. Он более оптимизирован. pastebin.com/g0zMLpsj - person KoD; 20.10.2020

Windows API имеет функции UrlEscape./UrlUnescape, экспортированный shlwapi.dll, для этой задачи.

person deltanine    schedule 23.10.2014
comment
примечание: UrlEscape не кодирует + - person Orwellophile; 16.10.2017

Добавление дополнения к рекомендации Билла по использованию libcurl: отличное предложение и требует обновления:
через 3 года curl_escape устарела, поэтому для будущего использования лучше использовать curl_easy_escape.

person Bagelzone Ha'bonè    schedule 28.06.2011

Я не смог найти здесь декодирование/удаление URI, которое также декодирует 2- и 3-байтовые последовательности. Предлагаю свою собственную высокопроизводительную версию, которая на лету преобразует ввод c sting в wstring:

#include <string>

const char HEX2DEC[55] =
{
     0, 1, 2, 3,  4, 5, 6, 7,  8, 9,-1,-1, -1,-1,-1,-1,
    -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
    -1,10,11,12, 13,14,15
};

#define __x2d__(s) HEX2DEC[*(s)-48]
#define __x2d2__(s) __x2d__(s) << 4 | __x2d__(s+1)

std::wstring decodeURI(const char * s) {
    unsigned char b;
    std::wstring ws;
    while (*s) {
        if (*s == '%')
            if ((b = __x2d2__(s + 1)) >= 0x80) {
                if (b >= 0xE0) { // three byte codepoint
                    ws += ((b & 0b00001111) << 12) | ((__x2d2__(s + 4) & 0b00111111) << 6) | (__x2d2__(s + 7) & 0b00111111);
                    s += 9;
                }
                else { // two byte codepoint
                    ws += (__x2d2__(s + 4) & 0b00111111) | (b & 0b00000011) << 6;
                    s += 6;
                }
            }
            else { // one byte codepoints
                ws += b;
                s += 3;
            }
        else { // no %
            ws += *s;
            s++;
        }
    }
    return ws;
}
person jamacoe    schedule 02.01.2017
comment
#define __x2d2__(s) (__x2d__(s) << 4 | __x2d__(s+1)), и он должен собираться с параметром -WError. - person Janek Olszak; 13.06.2017
comment
Извините, но высокая производительность при добавлении отдельных символов в wstring нереальна. По крайней мере, reserve достаточно места, иначе у вас все время будут массовые перераспределения - person Felix Dombek; 18.08.2017

Эта версия написана на чистом C и может дополнительно нормализовать путь к ресурсу. Использование его с C++ тривиально:

#include <string>
#include <iostream>

int main(int argc, char** argv)
{
    const std::string src("/some.url/foo/../bar/%2e/");
    std::cout << "src=\"" << src << "\"" << std::endl;

    // either do it the C++ conformant way:
    char* dst_buf = new char[src.size() + 1];
    urldecode(dst_buf, src.c_str(), 1);
    std::string dst1(dst_buf);
    delete[] dst_buf;
    std::cout << "dst1=\"" << dst1 << "\"" << std::endl;

    // or in-place with the &[0] trick to skip the new/delete
    std::string dst2;
    dst2.resize(src.size() + 1);
    dst2.resize(urldecode(&dst2[0], src.c_str(), 1));
    std::cout << "dst2=\"" << dst2 << "\"" << std::endl;
}

Выходы:

src="/some.url/foo/../bar/%2e/"
dst1="/some.url/bar/"
dst2="/some.url/bar/"

И фактическая функция:

#include <stddef.h>
#include <ctype.h>

/**
 * decode a percent-encoded C string with optional path normalization
 *
 * The buffer pointed to by @dst must be at least strlen(@src) bytes.
 * Decoding stops at the first character from @src that decodes to null.
 * Path normalization will remove redundant slashes and slash+dot sequences,
 * as well as removing path components when slash+dot+dot is found. It will
 * keep the root slash (if one was present) and will stop normalization
 * at the first questionmark found (so query parameters won't be normalized).
 *
 * @param dst       destination buffer
 * @param src       source buffer
 * @param normalize perform path normalization if nonzero
 * @return          number of valid characters in @dst
 * @author          Johan Lindh <[email protected]>
 * @legalese        BSD licensed (http://opensource.org/licenses/BSD-2-Clause)
 */
ptrdiff_t urldecode(char* dst, const char* src, int normalize)
{
    char* org_dst = dst;
    int slash_dot_dot = 0;
    char ch, a, b;
    do {
        ch = *src++;
        if (ch == '%' && isxdigit(a = src[0]) && isxdigit(b = src[1])) {
            if (a < 'A') a -= '0';
            else if(a < 'a') a -= 'A' - 10;
            else a -= 'a' - 10;
            if (b < 'A') b -= '0';
            else if(b < 'a') b -= 'A' - 10;
            else b -= 'a' - 10;
            ch = 16 * a + b;
            src += 2;
        }
        if (normalize) {
            switch (ch) {
            case '/':
                if (slash_dot_dot < 3) {
                    /* compress consecutive slashes and remove slash-dot */
                    dst -= slash_dot_dot;
                    slash_dot_dot = 1;
                    break;
                }
                /* fall-through */
            case '?':
                /* at start of query, stop normalizing */
                if (ch == '?')
                    normalize = 0;
                /* fall-through */
            case '\0':
                if (slash_dot_dot > 1) {
                    /* remove trailing slash-dot-(dot) */
                    dst -= slash_dot_dot;
                    /* remove parent directory if it was two dots */
                    if (slash_dot_dot == 3)
                        while (dst > org_dst && *--dst != '/')
                            /* empty body */;
                    slash_dot_dot = (ch == '/') ? 1 : 0;
                    /* keep the root slash if any */
                    if (!slash_dot_dot && dst == org_dst && *dst == '/')
                        ++dst;
                }
                break;
            case '.':
                if (slash_dot_dot == 1 || slash_dot_dot == 2) {
                    ++slash_dot_dot;
                    break;
                }
                /* fall-through */
            default:
                slash_dot_dot = 0;
            }
        }
        *dst++ = ch;
    } while(ch);
    return (dst - org_dst) - 1;
}
person Johan    schedule 09.11.2013
comment
Спасибо. Здесь это без необязательных путей. pastebin.com/RN5g7g9u - person Julian; 03.06.2014
comment
Это не соответствует никаким рекомендациям и совершенно неверно по сравнению с тем, что просит автор (например, «+» не заменяется пробелом). Нормализация пути не имеет ничего общего с декодированием URL. Если вы намерены нормализовать свой путь, вы должны сначала разделить свой URL-адрес на части (схема, полномочия, путь, запрос, фрагмент), а затем применить любой алгоритм, который вам нравится, только к части пути. - person xryl669; 03.02.2015

сочные кусочки

#include <ctype.h> // isdigit, tolower

from_hex(char ch) {
  return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
}

char to_hex(char code) {
  static char hex[] = "0123456789abcdef";
  return hex[code & 15];
}

отмечая, что

char d = from_hex(hex[0]) << 4 | from_hex(hex[1]);

as in

// %7B = '{'

char d = from_hex('7') << 4 | from_hex('B');
person Gabe Rainbow    schedule 28.05.2015

Вы можете использовать функцию "g_uri_escape_string()", предоставленную glib.h. https://developer.gnome.org/glib/stable/glib-URI-Functions.html

#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
int main() {
    char *uri = "http://www.example.com?hello world";
    char *encoded_uri = NULL;
    //as per wiki (https://en.wikipedia.org/wiki/Percent-encoding)
    char *escape_char_str = "!*'();:@&=+$,/?#[]"; 
    encoded_uri = g_uri_escape_string(uri, escape_char_str, TRUE);
    printf("[%s]\n", encoded_uri);
    free(encoded_uri);

    return 0;
}

скомпилируйте его с помощью:

gcc encoding_URI.c `pkg-config --cflags --libs glib-2.0`
person Vineet Mimrot    schedule 11.03.2016

вы можете просто использовать функцию AtlEscapeUrl() из atlutil.h, просто просмотрите ее документацию о том, как ее использовать.

person Pratik    schedule 22.01.2018
comment
это будет работать только на окнах - person kritzikratzi; 22.01.2018
comment
Да, я пробовал это на окнах. - person Pratik; 23.01.2018

Другое решение доступно с использованием библиотеки глупостей Facebook: folly::uriEscape и folly::uriUnescape.

person Dalzhim    schedule 05.04.2016

Я знаю, что вопрос требует метода C++, но для тех, кому это может понадобиться, я придумал очень короткую функцию на простом C для кодирования строки. Он не создает новую строку, а изменяет существующую, а это означает, что она должна иметь достаточный размер для хранения новой строки. Очень легко не отставать.

void urlEncode(char *string)
{
    char charToEncode;
    int posToEncode;
    while (((posToEncode=strspn(string,"1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.~"))!=0) &&(posToEncode<strlen(string)))
    {
        charToEncode=string[posToEncode];
        memmove(string+posToEncode+3,string+posToEncode+1,strlen(string+posToEncode));
        string[posToEncode]='%';
        string[posToEncode+1]="0123456789ABCDEF"[charToEncode>>4];
        string[posToEncode+2]="0123456789ABCDEF"[charToEncode&0xf];
        string+=posToEncode+3;
    }
}
person Alfredo Meraz    schedule 10.11.2015

Пришлось делать это в проекте без Boost. Итак, в итоге написал свой собственный. Я просто размещу его на GitHub: https://github.com/corporateshark/LUrlParser.

clParseURL URL = clParseURL::ParseURL( "https://name:[email protected]:80/path/res" );

if ( URL.IsValid() )
{
    cout << "Scheme    : " << URL.m_Scheme << endl;
    cout << "Host      : " << URL.m_Host << endl;
    cout << "Port      : " << URL.m_Port << endl;
    cout << "Path      : " << URL.m_Path << endl;
    cout << "Query     : " << URL.m_Query << endl;
    cout << "Fragment  : " << URL.m_Fragment << endl;
    cout << "User name : " << URL.m_UserName << endl;
    cout << "Password  : " << URL.m_Password << endl;
}
person Sergey K.    schedule 04.02.2015
comment
Ваша ссылка на библиотеку, которая анализирует URL-адрес. Он не %-кодирует URL-адрес. (Или, по крайней мере, я нигде не видел % в источнике.) Таким образом, я не думаю, что это отвечает на вопрос. - person Martin Bonner supports Monica; 20.11.2015