文字列を整数に変換する | Programming Place Plus C++編 逆引き

トップページC++編逆引き

C++編で扱っている C++ は 2003年に登場した C++03 という、とても古いバージョンのものです。C++ はその後、C++11 -> C++14 -> C++17 -> C++20 と更新されており、今後も 3年ごとに更新されます。
なかでも C++11 での更新は非常に大きなものであり、これから C++ の学習を始めるのなら、C++11 よりも古いバージョンを対象にするべきではありません。特に事情がないなら、新しい C++ を学んでください。 当サイトでは、C++14 をベースにした新C++編を作成中です。

目的

“100” や “-50” のような文字列を、整数型の値に変換したいとします。前者なら 100、後者なら -50 にします。

“100abc” のように、整数と関係がない文字が登場した場合、その手前までで打ち切ります。また、“abc100” の場合は、先頭部分が整数と関係がない文字なので、変換に失敗します。

方法①(std::stoi関数を使う)[C++11~]

C++11以降であれば、std::stoi関数があります。この関数は、C言語の strtol関数をラップしたもので、変換のエラーを、例外によって報告するようになっています。

#include <iostream>
#include <string>

int main()
{
    try {
        int v;

        v = std::stoi("100");
        std::cout << v << std::endl;

        v = std::stoi("-50");
        std::cout << v << std::endl;

        v = std::stoi("+50");
        std::cout << v << std::endl;

        v = std::stoi("0");
        std::cout << v << std::endl;

        v = std::stoi("100abc");
        std::cout << v << std::endl;

        v = std::stoi("abc100");  // 失敗する
        std::cout << v << std::endl;
    }
    catch (const std::invalid_argument& ex) {
        std::cerr << ex.what() << std::endl;
    }
    catch (const std::out_of_range& ex) {
        std::cerr << ex.what() << std::endl;
    }
}

実行結果:

100
-50
50
0
100
invalid stoi argument

先頭の文字が数字でない場合のように、変換がまったく行われなかった場合は、std::invalid_argument例外が、変換結果が大きすぎたり、小さすぎたりして、表現できない場合は、std::out_of_range例外が送出されます。

また、strtol関数のように、変換できなかった最初の文字を得るための第2引数(strtol関数はポインタを使いますが、std::stoi関数は std::size_t型を使い文字数で表現されます)や、基数を指定する第3引数があります。これらの引数には、デフォルト実引数が設定されているため、上記サンプルプログラムのように、省略してしまっても動作します。

方法②(std::istringstream を使う)[C++03~]

C++11 の機能が使えない場合は、std::istringstream を使います。

#include <iostream>
#include <sstream>

int main()
{
    int v;

    std::istringstream iss1("100");
    iss1 >> v;
    if (iss1) {
        std::cout << v << std::endl;
    }

    std::istringstream iss2("-50");
    iss2 >> v;
    if (iss2) {
        std::cout << v << std::endl;
    }

    std::istringstream iss3("+50");
    iss3 >> v;
    if (iss3) {
        std::cout << v << std::endl;
    }

    std::istringstream iss4("0");
    iss4 >> v;
    if (iss4) {
        std::cout << v << std::endl;
    }

    std::istringstream iss5("100abc");
    iss5 >> v;
    if (iss5) {
        std::cout << v << std::endl;
    }

    std::istringstream iss6("abc100");
    iss6 >> v;
    if (iss6) {
        std::cout << v << std::endl;
    }
}

実行結果:

100
-50
50
0
100

>>演算子によって読み取りを行う際にエラーが起きた場合、ストリームの状態(【標準ライブラリ】第27章)が変化しています。「if (iss1)」のような判定によって、ストリームの状態が正常かどうか分かるので、これを使って、エラーが発生していないかどうかチェックしています。


参考リンク


更新履歴

’2017/6/13 新規作成。



逆引きのトップページへ

C++編のトップページへ

Programming Place Plus のトップページへ



はてなブックマーク に保存 Pocket に保存 Facebook でシェア
X で ポストフォロー LINE で送る noteで書く
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー
先頭へ戻る