C++で16進数文字列を文字列に変換する方法について


Pythonだと[次のような方法](https://qiita.com/atsaki/items/6120cad2e3c448d774bf)で、16進数文字列を文字列に変換することができます。

[code]

    import binascii
    binascii.unhexlify(b'48656c6c6f') # => b'Hello'
    
[/code]

C++では、[文字列を16進数文字列に変換する方法](https://www.delftstack.com/ja/howto/cpp/string-to-
hex-cpp/)は見つかったのですが、逆に16進数文字列を文字列に戻す方法が分かりません。

以下が、文字列を16進数文字列に変換するコードですが、16進数文字列を文字列に変換する方法が知りたいです。

[code]

    #include <iostream>
    #include <string>
    #include <sstream>
    #include <iterator>
    
    using std::cout; using std::endl;
    using std::string; using std::hex;
    using std::stringstream;
    
    int main(){
        string s1 = "This will be converted to hexadecimal";
        string s2;
        stringstream ss;
    
        cout << "string: " << s1 << endl;
    
        for (const auto &item : s1) {
            ss << hex << int(item);
        }
        s2 = ss.str();
        cout << "hexval: " << s2 << endl;
    
        return EXIT_SUCCESS;
    }
    
[/code]

C++超初心者なので、どんなアドバイスでも歓迎です。

ちなみに、上記コードの`ss << hex << int(item);`という部分もどのような処理が行われているのか分からないので知りたいです...。  
`int(item)`と書くことで何が行われているのでしょうか？  
coutでitemの中身を確認すると、文字が入っているのですが、文字列をint()で数値に変換できるというのが何をやっているのかよく分かりません。




以下の記事の質問に書いてあるように、2文字づつ切り出して同じ`std::hex`に渡せば良いのでは？  
[C++ converting long hex string to
binary](https://stackoverflow.com/q/35522507/9014308)

>
[code]

>     std::string hex2bin(std::string s) {
>         std::string rc;
>         int nLen = s.length();
>         int tmp;
>         for (int i(0); i + 1 < nLen; i += 2) {
>             if (std::istringstream(s.substr(i, 2)) >> std::hex >> tmp) {
>                 rc.push_back(tmp);
>             }
>         }
>         return rc;
>     }
>  
[/code]

こんな風に呼べるでしょう。

[code]

    int main(){
        string s1 = "This will be converted to hexadecimal";
        string s2;
        stringstream ss;
    
        cout << "string: " << s1 << endl;
    
        for (const auto &item : s1) {
            ss << hex << int(item);
        }
        s2 = ss.str();
        cout << "hexval: " << s2 << endl;
    
        ////==== 文字列への再変換
        string s3;
        s3 = hex2bin(s2);
        cout << "re-string: " << s3 << endl;
        ////====
    
        return EXIT_SUCCESS;
    }
    
[/code]

* * *

> ちなみに、上記コードのss << hex << int(item);という部分もどのような処理が行われているのか分からないので知りたいです...。  
>  `int(item)`と書くことで何が行われているのでしょうか？  
>  coutでitemの中身を確認すると、文字が入っているのですが、文字列をint()で数値に変換できるというのが何をやっているのかよく分かりません。

これはその部分よりも、その上の`for (const auto &item : s1) {`に注目して調べると分かりやすいのでは？  
[範囲for文](https://cpprefjp.github.io/lang/cpp11/range_based_for.html)

> 範囲for文（The range-based for statement）は配列やコンテナを簡潔に扱うためのfor文の別表現である。

[auto](https://cpprefjp.github.io/lang/cpp11/auto.html)

> C++11 から、変数宣言時に具体的な型名のかわりに auto キーワードを指定する事によって、変数の型を初期化子から推論できるようになった。

つまり`文字列をint()で数値に変換できる`というのが誤解で、`for`文により`文字列`を`文字`に分解して1文字づつ処理するループになっている訳です。

なので、`1文字づつ数値に変換`して`hex処理`を行い`ssに追加`している。と言う風に考えられます。

* * *

コメントに対して：

> Pythonの場合だと、`test =
> "h";print(int(test));`としてもエラーになるのに対してC++だと普通に文字を数値に変換できるというのが何故なのか分かりません。

Pythonで文字を数値に変換するには、[ord()](https://docs.python.org/ja/3/library/functions.html#ord)という専用の関数が必要であるからです。

> 1 文字の Unicode 文字を表す文字列に対し、その文字の Unicode コードポイントを表す整数を返します。例えば、`ord('a')`は整数
> 97 を返し、`ord('€')`(ユーロ記号) は 8364
> を返します。これは[chr()](https://docs.python.org/ja/3/library/functions.html#chr)の逆です。

Pythonの[int()](https://docs.python.org/ja/3.8/library/functions.html#int)はC/C++で言えば[atoi()](https://docs.microsoft.com/ja-
jp/cpp/c-runtime-library/reference/atoi-atoi-l-wtoi-
wtoi-l?view=msvc-160)に相当するでしょう。

言語が違うので、同じ名前の関数であったとしても同じ機能とは限らない訳です。




以下の記事の質問に書いてあるように、2文字づつ切り出して同じ`std::hex`に渡せば良いのでは？  
[C++ converting long hex string to
binary](https://stackoverflow.com/q/35522507/9014308)

>
[code]

>     std::string hex2bin(std::string s) {
>         std::string rc;
>         int nLen = s.length();
>         int tmp;
>         for (int i(0); i + 1 < nLen; i += 2) {
>             if (std::istringstream(s.substr(i, 2)) >> std::hex >> tmp) {
>                 rc.push_back(tmp);
>             }
>         }
>         return rc;
>     }
>  
[/code]

こんな風に呼べるでしょう。

[code]

    int main(){
        string s1 = "This will be converted to hexadecimal";
        string s2;
        stringstream ss;
    
        cout << "string: " << s1 << endl;
    
        for (const auto &item : s1) {
            ss << hex << int(item);
        }
        s2 = ss.str();
        cout << "hexval: " << s2 << endl;
    
        ////==== 文字列への再変換
        string s3;
        s3 = hex2bin(s2);
        cout << "re-string: " << s3 << endl;
        ////====
    
        return EXIT_SUCCESS;
    }
    
[/code]

* * *

> ちなみに、上記コードのss << hex << int(item);という部分もどのような処理が行われているのか分からないので知りたいです...。  
>  `int(item)`と書くことで何が行われているのでしょうか？  
>  coutでitemの中身を確認すると、文字が入っているのですが、文字列をint()で数値に変換できるというのが何をやっているのかよく分かりません。

これはその部分よりも、その上の`for (const auto &item : s1) {`に注目して調べると分かりやすいのでは？  
[範囲for文](https://cpprefjp.github.io/lang/cpp11/range_based_for.html)

> 範囲for文（The range-based for statement）は配列やコンテナを簡潔に扱うためのfor文の別表現である。

[auto](https://cpprefjp.github.io/lang/cpp11/auto.html)

> C++11 から、変数宣言時に具体的な型名のかわりに auto キーワードを指定する事によって、変数の型を初期化子から推論できるようになった。

つまり`文字列をint()で数値に変換できる`というのが誤解で、`for`文により`文字列`を`文字`に分解して1文字づつ処理するループになっている訳です。

なので、`1文字づつ数値に変換`して`hex処理`を行い`ssに追加`している。と言う風に考えられます。

* * *

コメントに対して：

> Pythonの場合だと、`test =
> "h";print(int(test));`としてもエラーになるのに対してC++だと普通に文字を数値に変換できるというのが何故なのか分かりません。

Pythonで文字を数値に変換するには、[ord()](https://docs.python.org/ja/3/library/functions.html#ord)という専用の関数が必要であるからです。

> 1 文字の Unicode 文字を表す文字列に対し、その文字の Unicode コードポイントを表す整数を返します。例えば、`ord('a')`は整数
> 97 を返し、`ord('€')`(ユーロ記号) は 8364
> を返します。これは[chr()](https://docs.python.org/ja/3/library/functions.html#chr)の逆です。

Pythonの[int()](https://docs.python.org/ja/3.8/library/functions.html#int)はC/C++で言えば[atoi()](https://docs.microsoft.com/ja-
jp/cpp/c-runtime-library/reference/atoi-atoi-l-wtoi-
wtoi-l?view=msvc-160)に相当するでしょう。

言語が違うので、同じ名前の関数であったとしても同じ機能とは限らない訳です。

