C++で`std::string`を数値に変換するテクニック:`std::atof` 関数を超えた方法とは


  • 変換に失敗した場合は、0.0 を返します。
  • 変換に成功した場合は、変換された浮動小数点数値を返します。
  • 浮動小数点リテラル、指数表記、科学的記数法を含む、様々な形式の文字列を受け付けます。
  • 文字列 str を解析し、それに含まれる浮動小数点数値を double 型に変換します。

構文

double std::atof(const char* str);

引数

  • str: 変換対象の文字列を含む C 形式の文字列ポインタ。

戻り値

  • 変換に失敗した場合は、0.0 を返します。
  • 変換に成功した場合は、変換された浮動小数点数値を double 型で返します。

#include <iostream>
#include <cstdlib>

int main() {
  const char* str = "12.34";
  double value = std::atof(str);

  std::cout << "変換された値: " << value << std::endl;

  return 0;
}

この例では、文字列 "12.34" を std::atof 関数に渡して、浮動小数点数値 12.34 に変換し、結果をコンソールに出力しています。

注意点

  • 変換結果が double 型の範囲を超える場合は、オーバーフローが発生し、errno 変数に ERANGE が設定されます。
  • 変換対象の文字列は、有効な浮動小数点数値形式でなければなりません。そうでない場合は、変換に失敗し、0.0 が返されます。
  • std::atof は C 言語の atof 関数と互換性があり、同じ引数と戻り値を持っています。

std::string からの変換

std::string オブジェクトを std::atof 関数に直接渡すことはできません。std::string オブジェクトを C 形式の文字列に変換してから、std::atof 関数に渡す必要があります。

std::string str = "56.78";
const char* c_str = str.c_str();
double value = std::atof(c_str);

この例では、std::string オブジェクト str の C 形式の文字列ポインタ c_str を取得し、それを std::atof 関数に渡して、浮動小数点数値 56.78 に変換しています。

C++ 標準ライブラリには、std::atof 以外にも、文字列と数値の変換を行う様々な関数があります。

  • std::stod: 文字列を倍精度浮動小数点数値に変換
  • std::stof: 文字列を単精度浮動小数点数値に変換
  • std::stoull: 文字列を符号なし長整数に変換
  • std::stol: 文字列を長整数に変換
  • std::stoi: 文字列を整数に変換

これらの関数は、それぞれ異なる型への変換に対応しており、std::atof と同様に、std::string オブジェクトを含む様々な種類の文字列から変換を行うことができます。



文字列から浮動小数点数値への変換

#include <iostream>
#include <cstdlib>

int main() {
  const char* str1 = "12.34";
  const char* str2 = "-56.78";
  const char* str3 = "1.23e2";

  double value1 = std::atof(str1);
  double value2 = std::atof(str2);
  double value3 = std::atof(str3);

  std::cout << "str1 から変換された値: " << value1 << std::endl;
  std::cout << "str2 から変換された値: " << value2 << std::endl;
  std::cout << "str3 から変換された値: " << value3 << std::endl;

  return 0;
}

出力

str1 から変換された値: 12.34
str2 から変換された値: -56.78
str3 から変換された値: 123

std::string オブジェクトからの変換

#include <iostream>
#include <cstdlib>
#include <string>

int main() {
  std::string str1 = "34.56";
  std::string str2 = "-78.90";
  std::string str3 = "2.34e3";

  const char* c_str1 = str1.c_str();
  const char* c_str2 = str2.c_str();
  const char* c_str3 = str3.c_str();

  double value1 = std::atof(c_str1);
  double value2 = std::atof(c_str2);
  double value3 = std::atof(c_str3);

  std::cout << "str1 から変換された値: " << value1 << std::endl;
  std::cout << "str2 から変換された値: " << value2 << std::endl;
  std::cout << "str3 から変換された値: " << value3 << std::endl;

  return 0;
}

出力

str1 から変換された値: 34.56
str2 から変換された値: -78.9
str3 から変換された値: 2340

エラー処理

#include <iostream>
#include <cstdlib>
#include <string>

int main() {
  const char* str1 = "12.34";
  const char* str2 = "abc";

  double value1 = std::atof(str1);
  double value2 = std::atof(str2);

  std::cout << "str1 から変換された値: " << value1 << std::endl;

  if (std::atof(str2) == 0.0) {
    std::cout << "str2 の変換に失敗しました。" << std::endl;
  }

  return 0;
}

出力

str1 から変換された値: 12.34
str2 の変換に失敗しました。
#include <iostream>

int main() {
  double value1 = 12.34;
  double value2 = -56.78;
  double value3 = 1.23e2;

  std::string str1 = std::to_string(value1);
  std::string str2 = std::to_string(value2);
  std::string str3 = std::to_string(value3);

  const char* c_str1 = str1.c_str();
  const char* c_str2 = str2.c_str();
  const char* c_str3 = str3.c_str();

  double convertedValue1 = std::atof(c_str1);
  double convertedValue2 = std::atof(c_str2);
  double convertedValue3 = std::atof(c_str3


std::stod 関数

std::stod 関数は、std::atof 関数と同様に、文字列を double 型の浮動小数点数値に変換するために使用されます。

構文

double std::stod(const char* str, char** endptr);

引数

  • endptr: 変換が終了した文字列ポインタを格納するポインタ。
  • str: 変換対象の文字列を含む C 形式の文字列ポインタ。

戻り値

  • 変換に失敗した場合は、0.0 を返します。
  • 変換に成功した場合は、変換された浮動小数点数値を double 型で返します。

std::atof との違い

  • std::stod 関数は、std::atof 関数よりも精度が高く、より正確な変換結果を得ることができます。
  • std::stod 関数は、変換が終了した位置を endptr 引数に格納します。これにより、部分文字列の変換や、文字列の一部が浮動小数点数値でない場合の処理が容易になります。

#include <iostream>
#include <cstdlib>

int main() {
  const char* str = "12.34567890123456789";
  char* endptr;

  double value = std::stod(str, &endptr);

  std::cout << "変換された値: " << value << std::endl;
  std::cout << "変換が終了した位置: " << *endptr << std::endl;

  return 0;
}

出力

変換された値: 12.345678901234568
変換が終了した位置: e

std::stringstream クラス

std::stringstream クラスは、文字列ストリームを操作するためのテンプレートクラスです。文字列ストリームを使用して、文字列を浮動小数点数値に変換することもできます。

#include <iostream>
#include <sstream>

int main() {
  std::string str = "56.789";
  double value;

  std::stringstream ss(str);
  ss >> value;

  std::cout << "変換された値: " << value << std::endl;

  return 0;
}

出力

変換された値: 56.789

手動解析

浮動小数点数値形式を解析して、手動で変換することもできます。これは、複雑な形式の浮動小数点数値を扱う場合や、より詳細な制御が必要な場合に役立ちます。

#include <iostream>

int main() {
  const char* str = "123.45e-2";
  double value = 0.0;

  int sign = 1;
  double base = 0.0;
  double exponent = 0.0;

  bool is_exponent = false;
  bool is_fraction = false;

  for (int i = 0; str[i] != '\0'; ++i) {
    switch (str[i]) {
      case '-':
        sign *= -1;
        break;
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
        if (!is_exponent) {
          base = base * 10.0 + (str[i] - '0');
        } else {
          exponent = exponent * 10.0 + (str[i] - '0');
        }
        break;
      case '.':
        is_fraction = true;
        break;
      case 'e':
      case 'E':
        is_exponent = true;
        break;
      default: