閉じる

C++の文字列⇔数値変換 入門: std::stoi/std::stod と std::to_stringの使い方

文字列から数値、数値から文字列への変換は、ユーザー入力の処理やファイル入出力、ログ出力などで頻繁に登場します。

本記事ではC++のstd::stoistd::stodstd::to_stringを中心に、初心者の方がつまずきやすい点を避けながら、正しく使いこなすための基本と実践方法を解説します。

C++の文字列⇔数値変換の基本

使う型(int, double, std::string)の確認

C++で文字列と数値の相互変換を扱う際、まず関係する代表的な型を整理します。

整数はint、浮動小数点数はdouble、文字列はstd::stringを基本として扱います

整数が非常に大きい場合はlong long、より高精度の小数が必要な場合はlong doubleなどもありますが、入門ではintdoubleで十分です。

次の表は用途の目安です。

用途推奨型補足
カウント、インデックス、年齢などint実装依存ですが多くの環境で32bitです
金額や比率の概算、実数計算double丸め誤差に注意が必要です
文字データの保持、入出力std::stringUTF-8文字列も保持できます

型を正しく選ぶことが変換の正確さと安全性につながります

変換が必要になる場面(入出力・計算)

ユーザーから標準入力やファイルで受け取る値は多くの場合文字列です。

計算に使うには一度数値型へ変換してから演算し、結果を画面やログに出す際に再び文字列へ戻すという流れになります。

GUIやWeb連携でも同様で、境界(入力/出力)で文字列、内部で数値という役割分担が基本です。

文字列→数値: std::stoi/std::stodの使い方

std::stoiの基本(例と戻り値)

std::stoiは文字列をintに変換します。

成功すれば整数値を返し、必要なら解析済み文字数を取得できます

C++
#include <iostream>
#include <string>

int main() {
    std::string s1 = "42";
    std::string s2 = "  -15xyz"; // 先頭空白と符号、末尾に余分な文字
    std::size_t pos = 0;         // どこまで読んだかを受け取る位置

    int a = std::stoi(s1);                 // "42" → 42
    int b = std::stoi(s2, &pos, 10);       // 基数10で変換。posに消費した文字数が入る

    std::cout << "a = " << a << "\n";
    std::cout << "b = " << b << ", pos = " << pos << "\n";
    std::cout << "未処理の残り = '" << s2.substr(pos) << "'\n";

    // 基数0なら "0x" や先頭の0を自動判定(16進/8進/10進)
    std::string hex = "0xFF";
    int c = std::stoi(hex, nullptr, 0);
    std::cout << "c = " << c << "\n";
}
実行結果
a = 42
b = -15, pos = 5
未処理の残り = 'xyz'
c = 255

第2引数のposで「どこまでが数値として読めたか」を知ることで、余分な文字が混じっていないか検査できます。

std::stodの基本(例と戻り値)

std::stodは文字列をdoubleへ変換します。

指数表記も扱えます。

C++
#include <iostream>
#include <string>

int main() {
    std::string s1 = "3.14159";
    std::string s2 = "  +2.5e2 rest"; // 先頭空白、符号、指数表記、末尾に余分な文字
    std::size_t pos = 0;

    double x = std::stod(s1);                 // 3.14159
    double y = std::stod(s2, &pos);           // 2.5e2 → 250.0

    std::cout << "x = " << x << "\n";
    std::cout << "y = " << y << ", pos = " << pos << "\n";
    std::cout << "未処理の残り = '" << s2.substr(pos) << "'\n";
}
実行結果
x = 3.14159
y = 250, pos = 8
未処理の残り = ' rest'

浮動小数点の変換はロケールに依存せず「小数点はピリオド(.)」です

カンマ(,)は区切りとして扱われません。

変換失敗時の注意点(エラーと例外)

std::stoi/std::stodは失敗時に例外を投げます。

パースする前提の文字列が本当に数値か、範囲内かを想定して、try/catchで守るのが安全です。

C++
#include <iostream>
#include <string>
#include <stdexcept>

int main() {
    for (std::string s : {"abc", "9999999999999999999999"}) {
        try {
            int v = std::stoi(s);
            std::cout << "成功: " << v << "\n";
        } catch (const std::invalid_argument& e) {
            std::cout << "invalid_argument: 数値として解釈できません (" << s << ")\n";
        } catch (const std::out_of_range& e) {
            std::cout << "out_of_range: intの範囲を超えています (" << s << ")\n";
        }
    }
}
実行結果
invalid_argument: 数値として解釈できません (abc)
out_of_range: intの範囲を超えています (9999999999999999999999)

「異常時は例外が発生する」点を忘れると、プログラムが突然終了する原因になります

入力の前後空白や符号の扱い

std::stoi/std::stod先頭の空白符号(+/-)を自動的に受け付けます。

ただし末尾に余分な文字があっても途中までの数値だけ読んで成功してしまうため、posで全消費か確認すると堅牢です。

C++
#include <iostream>
#include <string>

bool parse_int_strict(const std::string& s, int& out) {
    std::size_t pos = 0;
    try {
        int v = std::stoi(s, &pos, 10);
        // 全文字が消費されていれば厳密に数値とみなす
        if (pos == s.size()) {
            out = v;
            return true;
        }
        return false;
    } catch (...) {
        return false;
    }
}

int main() {
    for (std::string s : {"  +123", "45x", " -7 "}) {
        int v = 0;
        bool ok = parse_int_strict(s, v);
        std::cout << "'" << s << "' -> ok=" << std::boolalpha << ok
                  << (ok ? ", value=" + std::to_string(v) : "") << "\n";
    }
}
実行結果
'  +123' -> ok=true, value=123
'45x' -> ok=false
' -7 ' -> ok=false

末尾の空白は「余分な文字」として扱われるため、必要に応じてトリム(前後空白の除去)してから変換するか、パーサを工夫します。

数値→文字列: std::to_stringの使い方

整数を文字列に変換(int → std::string)

std::to_stringは数値を手軽にstd::stringへ変換します。

ログメッセージやIDの連結などで簡潔に使えるのが利点です。

C++
#include <iostream>
#include <string>

int main() {
    int id = 1234;
    std::string msg = "ID=" + std::to_string(id); // 連結も簡単
    std::cout << msg << "\n";
}
実行結果
ID=1234

小数を文字列に変換(double → std::string)

浮動小数点数も同様に変換できます。

C++
#include <iostream>
#include <string>

int main() {
    double pi = 3.1415926535;
    std::string s = std::to_string(pi);
    std::cout << s << "\n"; // 多くの実装で小数点以下6桁相当の出力になります
}

実行結果例(典型):

3.141593

出力の見た目は実装に依存しますが、多くの環境で固定桁数(例: 6桁)になりがちです。

小数の桁数の注意点(to_stringの出力)

std::to_stringは小数点以下の桁数を直接指定できません

見た目を制御したい場合はstd::ostringstreamと<iomanip>のstd::fixed/std::setprecisionを使います。

C++
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>

int main() {
    double rate = 0.123456789;

    // to_string は手軽だが桁数は制御しにくい
    std::cout << "to_string: " << std::to_string(rate) << "\n";

    // 書式を指定して文字列化する
    std::ostringstream oss;
    oss << std::fixed << std::setprecision(3) << rate; // 小数点以下3桁
    std::string s = oss.str();
    std::cout << "formatted: " << s << "\n";
}
実行結果
to_string: 0.123457
formatted: 0.123

金額など表示桁数が重要な場合はstd::to_stringだけに頼らず、明示的に書式を指定してください

実用サンプルとチェックリスト

文字列→数値→計算→文字列の一連の流れ

税込価格を文字列で受け取り、消費税率を適用して合計を出し、所定の桁数で文字列化する例です。

C++
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <stdexcept>

// 前後空白を取り除くユーティリティ(簡易版)
std::string trim(const std::string& s) {
    const auto first = s.find_first_not_of(" \t\r\n");
    if (first == std::string::npos) return "";
    const auto last = s.find_last_not_of(" \t\r\n");
    return s.substr(first, last - first + 1);
}

int main() {
    // 入力(本来は std::getline(std::cin, ...) などで受け取る)
    std::string price_str = "  1980  "; // 価格(円)
    std::string tax_str   = " 0.10 ";   // 税率(10%なら0.10)

    try {
        // 1) 文字列を前後トリム
        price_str = trim(price_str);
        tax_str   = trim(tax_str);

        // 2) 数値へ変換
        std::size_t p1 = 0, p2 = 0;
        int price = std::stoi(price_str, &p1);
        double tax = std::stod(tax_str, &p2);

        // 全消費チェックで混入文字を検出
        if (p1 != price_str.size() || p2 != tax_str.size()) {
            throw std::invalid_argument("余分な文字を検出しました");
        }

        // 3) 計算
        double total = price * (1.0 + tax);

        // 4) 小数2桁で表示用文字列を作る
        std::ostringstream oss;
        oss << std::fixed << std::setprecision(2) << total;
        std::string total_str = oss.str();

        std::cout << "税込金額: " << total_str << " 円\n";

        // 5) ログやID連結など、整数は to_string が手軽
        std::string log = "price=" + std::to_string(price) + ", tax=" + std::to_string(static_cast<int>(tax * 100)) + "%";
        std::cout << log << "\n";

    } catch (const std::exception& e) {
        std::cerr << "入力エラー: " << e.what() << "\n";
        return 1;
    }
}
実行結果
税込金額: 2178.00 円
price=1980, tax=10%

入力の正当性検証、変換、計算、書式化の4段階を意識すると、バグの混入を防ぎやすくなります

よくあるミス(全角数字・余分な文字・範囲外)

実務で頻発する落とし穴を把握しておくと、デバッグ時間を大幅に節約できます。

症状原因対策
全角数字で失敗“123”std::stoiはASCII数字のみ解釈入力を正規化する、全角→半角変換を行う
末尾に余分な文字“45kg”数値の後ろを読まずに成功することがあるposで全消費確認、またはトリム/バリデーション
範囲外“999999999999”intの範囲超過でstd::out_of_rangelong long系(std::stoll)を検討、例外処理を追加
小数点がカンマ“3,14”小数点はピリオドのみ事前置換やロケール対応のパーサを利用
期待桁で表示されない“3.140000”std::to_stringは桁数制御不可ostringstreamsetprecision指定

「パースできた=正しい入力」とは限りません

残り文字の有無、範囲、表記揺れをチェックすることが重要です。

まとめ

本記事ではstd::stoistd::stodでの文字列→数値変換、std::to_stringでの数値→文字列変換の基本を解説しました。

例外処理とposによる検証で入力の健全性を確保し、表示はostringstreamで桁数を明示するのが実践的な指針です。

初心者のうちは、余分な文字や範囲外、全角数字といった落とし穴をサンプルのように丁寧に検査しながら、安全で読みやすいコードを心がけてください。

この記事を書いた人
エーテリア編集部
エーテリア編集部

C++をこれから学ぶ方に向けて、基礎的な文法や標準ライブラリの使い方を紹介します。モダンな書き方も初心者に合わせてやさしく説明しています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!