75247


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()で数値に変換できるというのが何をやっているのかよく分かりません。


CC BY-SA 4.0
2021-04-13T13:43:51.203
75245
2021-04-13T23:07:59.300
2021-04-13T22:06:50.587
36446
36446
question
c++
C++で16進数文字列を文字列に変換する方法について


以下の記事の質問に書いてあるように、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)に相当するでしょう。

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


CC BY-SA 4.0
2021-04-13T15:01:28.607
75247
2021-04-13T23:07:59.300
2021-04-13T23:07:59.300
26370
26370
75245
answer


C++言語において文字とは文字コードを値に持つ数値でもあります。そこで質問のように16進文字列を復元するには文字列を数値化することになります。これについて、C++17で追加された文字列から数値へ変換する[`std::from_chars`関数](https://ja.cppreference.com/w/cpp/utility/from_chars)が使えます。

[code]

    #include <charconv>
    #include <string>
    #include <string_view>
    
    auto hex2str(std::string_view hex) {
        std::string result(hex.size() / 2, '\0');
        for (size_t i = 0; i < hex.size() / 2; i++)
            std::from_chars(&hex[i * 2], &hex[i * 2 + 2], reinterpret_cast<unsigned char&>(result[i]), 16);
        return result;
    }
    
[/code]

エラー処理は省いています。16進文字列が偶数だとか、適切な文字となっているかなどは別途検査してください。

呼び出し例はこんな感じ。

[code]

    #include <iostream>
    using namespace std::literals;
    
    int main() {
        auto str = hex2str("48656c6c6f"sv);
        std::cout << str << std::endl;
    }
    
[/code]

* * *

> `sv`というのはどのような処理を行っているのでしょうか？

C++17で導入された[文字列ビューを構築するリテラル](https://ja.cppreference.com/w/cpp/string/basic_string_view/operator%22%22sv)となります。通常の`""`ですと文字列の長さ情報を持たない`const
char*`となりますが、`""sv`ですと長さ情報を持つ`std::string_view`が構築されます。


CC BY-SA 4.0
2021-04-13T22:21:47.683
75249
2021-04-13T23:03:38.127
2021-04-13T23:03:38.127
4236
4236
75245
answer