【C++】文字列を数値に変換する複数の方法【string to int/double、stoi関数概要】

std::string → 数値

文字列型std::stringintdouble等の数値型に変換する方法です。

int型への変換はstd::stoi関数、double型の変換はstd::stodを用います。

std::string str = "3.14";

int    i = std::stoi(str); // 3
double d = std::stod(str); // 3.14

long型、float型への変換やstd::sto~系関数の詳細については後半で解説します(# std::sto~系関数)。

文字列(配列)→ 数値

C言語スタイルの文字列(char[], const char*)を整数値や浮動小数点数に変換する場合は、C言語由来の関数を用いる必要があります。

// #include <cstdlib> // std::atoi, std::strtol
// #include <cstdio>  // std::sscanf

std::string s = "99yen";

// atoi関数による変換
int i = std::atoi(s.c_str());                 // 99 == i

// strtol関数による変換
long l = std::strtol(s.c_str(), nullptr, 10); // 99 == l

// sscanf関数による変換
int n = std::sscanf(s.c_str(), "%d", &i);     // 99 == i, 1 == n

各関数の詳しい説明や注意点については、以下のページを参考にしてください。

参考: 【C言語】文字列を数値に変換する方法【危険なatoi関数、厳格なstrtol関数、怠慢なsscanf】

std::sto~系関数

目次

変換関数一覧

long型やfloat型用の専用関数も用意されています。

対応する関数
intstd::stoi
longstd::stol
unsigned longstd::stoul
long longstd::stoll
unsigned long longstd::stoull
floatstd::stof
doublestd::stod
long doublestd::stold

関数の概要

// #include <string>
int    stoi(const std::string& str, size_t* idx = 0, int base = 10);
double stod(const std::string& str, size_t* idx = 0);
戻り値変換後の値
第一引数読み取り文字列
第二引数変換完了後の読み取り位置
第三引数基数
例外std::invalid_argument, std::out_of_range
参考特殊な形式の数値を変換する

第二引数 ─ インデックスの取得

第二引数にsize_t型のポインタを渡すことで、文字列中の「変換完了位置+1」のインデックスを取得することが可能です。

size_t index;

std::stod("3.1%", &index);
printf("%ld", index);        // 3
printf("%c", "3.1%"[index]); // '%'

std::stod(" 1e4", &index);
printf("%ld", index);        // 4
printf("%c", " 1e4"[index]); // '\0' (終端文字)

第三引数 ─ 基数の指定

第三引数に基数を指定することが可能です。

2を指定すれば2進数、16を指定すれば16進数として文字列の変換作業が行われます。

std::stoi("1000", nullptr, 2); //  8 (0b1000 2進数)
std::stoi("10", nullptr, 8);   //  8 (010    8進数)
std::stoi("10", nullptr, 16);  // 16 (0x10  16進数)

std::stoi("0xF", nullptr, 16);  // 15 (0x0F)
std::stoi("F", nullptr, 16);    // 15 (0x0F)
std::stoi("F", nullptr, 2);     // 例外発生:std::invalid_argument: stoi: no conversion

第三引数に0が指定された場合は基数の自動判定が行われます。

std::stoi("010", nullptr, 0);  //  8 ( 8進数)
std::stoi("0xf", nullptr, 0);  // 15 (16進数)

例外

std::invalid_argument

文字列を数値に変換できなかった場合にはstd::invalid_argument例外が発生し、プログラムは異常終了します。C言語のatoi関数とは挙動が異なるため注意が必要です。

// 実行時エラー: libc++abi.dylib: terminating with uncaught exception of type std::invalid_argument: stoi: no conversion
std::stoi("mad");
std::atoi("mad"); // エラーにならない。戻り値は0

以下の方法で例外を捕捉します。

try {
  std::stoi("mad");
} catch (const std::invalid_argument& e) {
  // 変換失敗時の処理
  std::cout << e.what(); // "stoi: no conversion"
  std::cout << "変換に失敗しました";
}

std::out_of_range

数値変換中に、値のオーバーフローまたはアンダーフローが発生した場合にはstd::out_of_range例外が発生します。

// 実行時エラー: terminating with uncaught exception of type std::out_of_range: stoi: out of range
std::stoi("2147483648"); // 2147483647 == INT_MAX (int型の最大値)

try {
  std::stoi("2147483648");
} catch (const std::out_of_range& e) {
  puts(e.what()); // "stoi: out of range"
  puts("オーバーフローが発生しました");
}

オーバーフローとアンダーフローの正確な判別を行いたい場合には、C言語のstrto~系関数を用いる必要があります。

参考: 【C言語】strtol関数

特殊な形式の数値を変換する

16進数や指数表記の数字を変換することも可能です。また文字列中の先頭空白文字は変換時に無視されます。

std::stoi("9kg");    // 9 (末尾文字は無視される)
std::stod("\t\n 8"); // 8 (先頭の空白は無視される)
std::stod("1e3");    // 1000 (指数表記からの変換)
std::stod("0x02");   // 2 (16進数からの変換)
広告