std :: stringからfloatまたはdouble


98

に変換しようとしstd::stringていfloat/doubleます。私は試した:

std::string num = "0.6";
double temp = (double)atof(num.c_str());

ただし、常にゼロを返します。他の方法は?


3
10年前にすでに判明している何かを過剰設計するという衝動に抵抗します。
haavee 2009年

1
正しく出力しますか?ゼロにならないはずです
Johannes Schaub-litb '18 / 06/18

1
さらに、atofをキャストする必要はありません。すでにdoubleを返します。
AlbertoPL 2009年

私は確信しています。デバッガーが0を表示します。結果は0です。プラットフォーム:Linux。
Max Frai

13
正しいロケールがインストールされていますか?"0,6"またはsetlocale(LC_NUMERIC、 "C");を試してください。
ヨハネスシャウブ-litb 2009年

回答:


125
std::string num = "0.6";
double temp = ::atof(num.c_str());

私のためにそれをします、それは文字列をdoubleに変換する有効なC ++構文です。

stringstreamまたはboost :: lexical_castでそれを行うことができますが、これらにはパフォーマンスのペナルティが伴います。


Ahha Qtプロジェクトがあります...

QString winOpacity("0.6");
double temp = winOpacity.toDouble();

エクストラノート:
入力データがある場合はconst char*QByteArray::toDoubleより高速になります。


7
boost :: lexical_castはストリーミングしている。
TimW 2009年

1
彼らがパフォーマンスのペナルティを伴うと一般的に言うことはできないと思います。直前にcin >> num;があるとどうなるか考えてみてください。ユーザーは、ミリ秒のlexical_castの方が遅いことに注意するために、非常にすばやく入力する必要があります(rly jon skeetのように):)とは言っても、lexical_castがパフォーマンスを吸いすぎているタスクがあると
思い

3
このソリューションでは、atof()の前の::は何をしますか?そこには何が必要ですか?
sivabudh 2010

4
@ShaChrisグローバル名前空間のatof関数を確実に使用したいからです。
TimW、

1
現在のロケールに依存
nmr

104

標準ライブラリ(C ++ 11)は、以下の機能を備えていますstd::stod

std::string  s  = "0.6"
std::wstring ws = "0.7"
double d  = std::stod(s);
double dw = std::stod(ws);

一般に、他のほとんどの基本的なタイプについては、を参照してください<string>。C文字列にもいくつかの新機能があります。見る<stdlib.h>


4
私はこのソリューションが好きですが、それはC ++ 11からのみであるようです。そのため、私のSDKでは利用できません。
pamplemousse_mk2 2013年

C ++標準委員会がこれを追加したことを知るのは素晴らしいことです。ostringstreamそれ自体が一人で利用してみましょう、あまりにも長いアウト型にした...
bobobobo

4
floatの場合(googleで「c ++ string to float」と入力して見つけた質問で尋ねたように)、std :: stofを使用する必要があります。
エティエンヌ2014

1
これが例外をスローする可能性があることに注意してください:std :: invalid_argument(変換に失敗した場合)std :: out_of_range(範囲外の場合)
Jason Doucette

3
バイヤーは注意してください、現在のロケールに依存します。
nmr 2017年

29

語彙のキャストはとてもいいです。

#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>

using std::endl;
using std::cout;
using std::string;
using boost::lexical_cast;

int main() {
    string str = "0.6";
    double dub = lexical_cast<double>(str);
    cout << dub << endl;
}

おかげで動作します。しかし、それは私にとっての質問です。なぜ私のコードが機能しないのですか。
Max Frai

2
@Johannes Schaub:ADLに基づくと、彼もそうかもしれませんが、使用定義と実際に使用している定義により、膨大な数のstd要素がスコープに含まれる可能性があります。さらに、lexical_castはめちゃくちゃ遅いので、+ 1はありません。

boost :: lexical_castの優れた機能は、エラー処理です。変換が失敗した場合、例外がスローされますtry { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
SemjonMössinger

より正確には、を使用catch ( boost::bad_lexical_cast const& err )して例外をキャッチします。
SemjonMössinger2016

14

std :: stringstream:を使用できます。

   #include <sstream>
   #include <string>
   template<typename T>
   T StringToNumber(const std::string& numberAsString)
   {
      T valor;

      std::stringstream stream(numberAsString);
      stream >> valor;
      if (stream.fail()) {
         std::runtime_error e(numberAsString);
         throw e;
      }
      return valor;
   }

使用法:

double number= StringToNumber<double>("0.6");

ええと、あなたはboost :: lexical_castに恐ろしいインターフェースがあると思いませんか?stefanBの答えを見てください!Boostも同じです。
kirsche40 2014

@ kirsche40 Boostとの依存関係をまだ持っていない人にとっては良い代替手段のようです(std :: stringを数値に変換するためだけにBoostとリンクするのは少しやりすぎです!)
Jean-Philippe Jodoin 14

@ JEan-Phillippe Jodiun削除されたコメントに回答しました。誰かがBoostを推奨しました。ほとんどの場合、ブーストはやり過ぎです。ちなみに、しばらくの間、Boostの使用は「新しい」コンパイラに制限されています。古いプロジェクトはBoostを使用できません。たとえば、ASIOはstd :: addressofのようなC ++ 11機能に大きく依存しているため、C ++ 98 / C ++ 03コンパイラーにとってはまったく価値がありません。私見、プロジェクトが始まったとき、Boostは古いコンパイラバージョンに新しい「標準化された」機能を提供するつもりでした... :-(
kirsche40

10

はい、語彙キャストを使用します。文字列ストリームと<<演算子を使用するか、Boostを使用します。すでに実装されています。

独自のバージョンは次のようになります。

template<typename to, typename from>to lexical_cast(from const &x) {
  std::stringstream os;
  to ret;

  os << x;
  os >> ret;

  return ret;  
}

7

ブースト字句キャストを使用できます。

#include <boost/lexical_cast.hpp>

string v("0.6");
double dd = boost::lexical_cast<double>(v);
cout << dd << endl;

注:boost :: lexical_castは例外をスローするため、無効な値を渡した場合に対処できるように準備しておく必要があります。string( "xxx")を渡してみてください


5

すべてのブーストをドラッグしたくない場合は、strtod(3)fromを使用し<cstdlib>ます。すでにdoubleが返されます。

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

using namespace std;

int main()  {
    std::string  num = "0.6";
    double temp = ::strtod(num.c_str(), 0);

    cout << num << " " << temp << endl;
    return 0;
}

出力:

$ g++ -o s s.cc
$ ./s
0.6 0.6
$

atof()が機能しないのはなぜですか?どのプラットフォーム/コンパイラを使用していますか?



あなたのメソッドもゼロを返します。Linux。
Max Frai

3

Linuxでも同じ問題が発生した

double s2f(string str)
{
 istringstream buffer(str);
 double temp;
 buffer >> temp;
 return temp;
}

できます。


2
   double myAtof ( string &num){
      double tmp;
      sscanf ( num.c_str(), "%lf" , &tmp);
      return tmp;
   }

1
無効な回答、numに格納された値が実際に有効な浮動小数点数であることをどのようにして知るのですか?sscanfの戻り値の型をチェックしないと、MSコーディングスタイルのように見えます。

1

この答えはあなたのコメントでlitbをバックアップしています。結果が適切に表示されていないという深刻な疑いがあります。

まったく同じことが一度は起こりました。私は1日を費やして、なぜ64ビットのintに不正な値が入っているのかを理解するために費やしましたが、printfが2番目のバイトを無視していることを発見しただけです。64ビット値をそのintのようにprintfに渡すことはできません。


私は結果を確認するためにprintf関数を使用していないよ...と私はセットウィンドウの不透明度にその値を使用し、その値が0であるので、私の窓は、フルtrasparentです
マックスFrai

1

C ++ 11の方法は、std :: stodおよびstd :: to_stringを使用することです。どちらもVisual Studio 11で機能します。


1

なぜatof()元の質問で機能しないのかについて:それが2倍にキャストされるという事実は私を疑わしくします。コードはなし#include <stdlib.h>でコンパイルすべきではありませんが、キャストがコンパイル警告を解決するために追加された場合、atof()正しく宣言されません。コンパイラがatof()intを返すと想定している場合、キャストすると変換警告が解決されますが、戻り値がdoubleとして認識されません

#include <stdlib.h>
#include <string>

... 
  std::string num = "0.6";
  double temp = atof(num.c_str());

警告なしで動作するはずです。


0

Boostを方程式にドラッグするのではなく、文字列を(一時的に)として保持してchar[]を使用できますsprintf()

しかしもちろん、とにかくBoostを使用している場合は、それほど問題にはなりません。


0

とにかく、文字列<->浮動小数点のBoost lexical_castは必要ありません。このユースケースのサブセットは、以前の関数よりもブーストが一貫して悪い唯一のセットであり、基本的にはすべての障害をそこに集中させています。これは、独自のパフォーマンス結果が、そのような変換にsscanfやprintfを使用するよりも20-25倍遅いパフォーマンスを示しているためです。

自分でグーグル。boost :: lexical_castは50の変換のようなものを処理でき、浮動小数点数#を含む変換を除外すると、明らかな代替案と同じかそれ以上に優れています(これらすべての操作に対して単一のAPIを持つという追加の利点があります)。しかし、フロートを持ち込むと、パフォーマンスの点でタイタニック号が氷山を打つようになります。

古い専用のstr-> double関数は、すべて30ミリ秒(またはそれ以上)のような処理で10000パースできます。lexical_castが同じ処理を実行するには、650ミリ秒程度かかります。


ソースなし?私はそれを自分でググ:boost.org/doc/libs/1_55_0/doc/html/boost_lexical_cast/...
ブレイク

0

私の問題:

  1. ロケールに依存しない、2倍の文字列(小数点は常に「。」)
  2. 文字列変換が失敗した場合のエラー検出

私の解決策(Windows関数_wcstod_lを使用):

// string to convert. Note: decimal seperator is ',' here
std::wstring str = L"1,101";

// Use this for error detection
wchar_t* stopString;

// Create a locale for "C". Thus a '.' is expected as decimal separator
double dbl = _wcstod_l(str.c_str(), &stopString, _create_locale(LC_ALL, "C")); 

if (wcslen(stopString) != 0)
{
    // ... error handling ... we'll run into this because of the separator
}

HTH ...この解決策を得るのにかなり時間がかかりました。それでも、文字列のローカライズなどについては十分に理解していないと感じています...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.