95

誰かがこれを行う良いC++コードを知っていますか?

4

19 に答える 19

90

先日、この問題の半分のエンコーディングに直面しました。利用可能なオプションに不満があり、この C サンプル コードを見てから、独自の C++ url-encode 関数を展開することにしました。

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

デコード関数の実装は、読者の課題として残されています。:P

于 2013-07-17T19:40:36.487 に答える
85

自分の質問に答える...

libcurl には、エンコード用のcurl_easy_escapeがあります。

デコードの場合、curl_easy_unescape

于 2008-09-30T19:41:49.060 に答える
14
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);
}

最高ではありませんが、正常に動作しています;-)

于 2011-01-28T00:52:06.050 に答える
11

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 文字列を非常に簡単にエンコードおよびデコードできます。

于 2014-08-15T22:36:32.137 に答える
11

通常、char の int 値に '%' を追加しても、エンコード時に機能しません。値は 16 進数に相当するものと見なされます。たとえば、'/' は '%47' ではなく '%2F' です。

これは、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;
}
于 2015-04-30T07:59:08.773 に答える
6

win32 C++ アプリで URL をデコードするための API を検索しているときに、この質問にたどり着きました。Windowsが悪いことではないと仮定して、質問はプラットフォームを完全に指定していないためです。

InternetCanonicalizeUrl は、Windows プログラムの API です。詳細はこちら

        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 をデコードするかどうかを指定するフラグがあるようです

于 2012-01-04T19:31:20.743 に答える
6

CGICCには、URL のエンコードとデコードを行うメソッドが含まれています。form_urlencode と form_urldecode

于 2008-09-30T19:27:03.027 に答える
4

libcurl の使用に関する Bill の推奨事項にフォローアップを追加: 素晴らしい提案であり、更新予定:
3 年後、curl_escape関数は廃止されるため、今後使用する場合はcurl_easy_escapeを使用することをお勧めします。

于 2011-06-28T22:11:48.090 に答える
3

ここでは、2 および 3 バイト シーケンスもデコードする URI デコード/unescape を見つけることができませんでした。オンザフライで c 文字列入力を 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;
}
于 2017-01-02T23:16:20.480 に答える
1

ジューシービット

#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]);

のように

// %7B = '{'

char d = from_hex('7') << 4 | from_hex('B');
于 2015-05-28T07:03:39.643 に答える
1

別の解決策として、 Facebook の愚かなライブラリ:folly::uriEscapeとを使用できますfolly::uriUnescape

于 2016-04-05T16:36:18.683 に答える
-2

Boostなしのプロジェクトでそれをしなければなりませんでした。それで、自分で書くことになりました。GitHub に置くだけです: https://github.com/corporateshark/LUrlParser

clParseURL URL = clParseURL::ParseURL( "https://name:pwd@github.com: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;
}
于 2015-02-04T16:27:55.240 に答える