std :: string to float or double


98

मैं कन्वर्ट करने के लिए कोशिश कर रहा हूँ std::stringकरने के लिए float/double। मैंने कोशिश की:

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

लेकिन यह हमेशा शून्य देता है। कोई और तरीका?


3
Overengineer के आग्रह का विरोध कुछ पहले से ही एक दशक पहले किया गया था।
हैवी

1
क्या आप वाकई इसे सही तरीके से आउटपुट कर रहे हैं? यह शून्य उपज नहीं करना चाहिए
litb - Johannes Schaub

1
इसके अतिरिक्त, आपको एटॉफ़ करने की आवश्यकता नहीं है, यह पहले से ही एक डबल रिटर्न करता है।
अल्बर्टोपील

मुझे यकीन है। डीबगर मुझे 0. दिखाता है और परिणाम 0. प्लेटफ़ॉर्म: लिनक्स है।
मैक्स फ्राइ

13
क्या आप सुनिश्चित हैं कि आपके पास सही लोकेल स्थापित है? "0,6" या सेटलोकाले (LC_NUMERIC, "C") की कोशिश करें;
जोहान्स शाउब -

जवाबों:


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

क्या यह मेरे लिए है, यह एक स्ट्रिंग को डबल में बदलने के लिए एक वैध C ++ सिंटैक्स है।

आप इसे स्ट्रीस्टस्ट या बूस्ट :: लेक्सिकल_कास्ट के साथ कर सकते हैं, लेकिन वे एक प्रदर्शन दंड के साथ आते हैं।


अहा आपके पास एक Qt प्रोजेक्ट है ...

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

अतिरिक्त ध्यान दें:
यदि इनपुट डेटा ए है const char*, QByteArray::toDoubleतो तेज़ होगा।


7
बढ़ावा देना :: lexical_cast स्ट्रीमिंग है।
टिम जू

1
मैं आमतौर पर नहीं कह सकता कि वे एक प्रदर्शन दंड के साथ आते हैं, मुझे लगता है। इस बारे में सोचें कि क्या होता है जब आपके पास पहले से ही एक Cin >> num ;; उपयोगकर्ता को बहुत जल्दी टाइप करना होगा (rly jon skeet like) कभी भी ध्यान दें कि मिलीसेकेंड lexical_cast धीमा है :) ने कहा, मेरा मानना ​​है कि ऐसे कार्य हैं जहां lexical_cast सिर्फ बहुत अधिक प्रदर्शन बेकार है:
जोहान्स स्काउब - litb

3
इस समाधान के लिए, एटॉफ़ के सामने :: क्या करता है? वहां होने की क्या जरूरत है?
शिवाबुध

4
@ श्रीश्री क्योंकि मैं यह सुनिश्चित करना चाहता हूं कि मैं वैश्विक नामस्थान से एटॉफ़ फ़ंक्शन का उपयोग करूं।
टिम फेयर

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>। सी स्ट्रिंग्स के लिए कुछ नई विशेषताएं भी हैं। देख<stdlib.h>


4
मुझे यह समाधान पसंद है, लेकिन ऐसा प्रतीत होता है कि यह केवल C ++ 11 से है। इसलिए मेरे एसडीके पर उपलब्ध नहीं है।
pamplemousse_mk2

यह जानना शानदार है कि C ++ मानक समिति ने इसे जोड़ा। ostringstreamअपने आप में टाइप करने के लिए बहुत लंबा था, अकेले इस्तेमाल करते हैं ..
bobobobo

4
फ़्लोट्स के लिए (जैसा कि मैंने "सी ++ स्ट्रिंग टू फ्लोट" टाइप करके Google में पाया गया प्रश्न के रूप में पूछा गया), व्यक्ति को std :: stof का उपयोग करना चाहिए।
.तिने

1
बस ध्यान दें कि यह अपवाद फेंक सकता है: std :: अमान्य_argument (यदि रूपांतरण विफल रहा है) std :: out_of_range (यदि सीमा से बाहर है)
जेसन

3
खरीदार सावधान रहें, वर्तमान स्थान पर निर्भर करता है।
nmr

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;
}

धन्यवाद, यह काम करता है .. लेकिन यह मेरे लिए एक सवाल है: मेरा कोड क्यों काम नहीं कर रहा है।
मैक्स फ्राइ

2
@ जोहान्स शॉब: एडीएल के आधार पर, उनके पास और साथ ही साथ उपयोग किए जाने वाले डिफिनेट्स और जो वह वास्तव में उपयोग कर रहे हैं, शायद बहुत से एसटीडी तत्वों के दायरे में लाएंगे। इसके अलावा lexical_cast बिलकुल धीमा है, इसलिए मुझसे कोई +1 नहीं है।

बढ़ावा देने की एक अच्छी सुविधा :: lexical_cast त्रुटि से निपटने है। यदि रूपांतरण विफल हो जाता है, तो एक अपवाद फेंक दिया जाता है:try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
सेमजोन मोसेिंगर

अधिक सटीक catch ( boost::bad_lexical_cast const& err )होने के लिए, अपवाद को पकड़ने के लिए उपयोग करें।
सेमजोन मोसेिंगर

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");

उह, तो आपको लगता है कि बढ़ावा :: lexical_cast एक भयानक इंटरफ़ेस है, है ना? StefanB के जवाब को देखो! बूस्ट वही करता है।
kirsche40

@ kirsche40 उन लोगों के लिए एक अच्छे विकल्प की तरह लगता है, जिनके पास पहले से ही बूस्ट के साथ निर्भरता नहीं है (केवल एक एसटीडी को बदलने के लिए बूस्ट के साथ लिंक करना): स्ट्रिंग टू नंबर्स थोड़ा ओवरकिल है!)
जीन-फिलिप जॉडोन

@ JEan-Phillippe Jodiun मैंने अब डिलीट की गई टिप्पणी का जवाब दिया, जहां किसी ने बूस्ट की सिफारिश की। मुझे पता है कि बूस्ट ओवरकील है। वैसे, कुछ समय के लिए अब बूस्ट का उपयोग "नए" संकलक तक सीमित है। पुराने प्रोजेक्ट बूस्ट का उपयोग नहीं कर सकते हैं। उदाहरण के लिए ASIO C ++ 11- std :: addressof जैसी सुविधाओं पर भारी निर्भर करता है, जो इसे C ++ 98 / C ++ 03 संकलक के लिए पूरी तरह से बेकार बना देता है। IMHO, जब परियोजना शुरू हुई तो
बूस्टर

10

हाँ, एक शाब्दिक कलाकारों के साथ। एक स्ट्रिंगस्ट्रीम और << ऑपरेटर का उपयोग करें, या बूस्ट का उपयोग करें, वे पहले ही इसे लागू कर चुके हैं।

आपका अपना संस्करण ऐसा दिख सकता है:

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;

नोट: बढ़ावा :: लेक्सिकल_कास्ट अपवाद को फेंकता है ताकि जब आप अमान्य मान पास करें तो इससे निपटने के लिए तैयार रहें, पासिंग स्ट्रिंग का प्रयास करें ("xxx")


5

यदि आप सभी को बढ़ावा देने में नहीं खींचना चाहते हैं, तो इसके साथ जाओ - यह पहले strtod(3)से <cstdlib>ही एक डबल लौटाता है।

#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
$

क्यों एटॉफ़ () काम नहीं करता ... आप किस प्लेटफॉर्म / कंपाइलर पर हैं?


एक stringstream का उपयोग को बढ़ावा देने की आवश्यकता नहीं होगी
jalf

आपकी विधि शून्य भी है। लिनक्स।
मैक्स फ्राई

3

लिनक्स में मुझे यही समस्या थी

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
अमान्य उत्तर, आप कैसे जानते हैं कि संख्या में संग्रहीत मूल्य वास्तव में एक वैध फ्लोटिंग पॉइंट संख्या है? आप sscanf के रिटर्न प्रकार की जांच नहीं करते हैं, एक एमएस कोडिंग शैली की तरह लगता है।

1

यह उत्तर आपकी टिप्पणियों में प्रकाशित है। मुझे गहरा संदेह है कि आप परिणाम को ठीक से प्रदर्शित नहीं कर रहे हैं।

मैं एक ही बार मेरे साथ ठीक वैसा ही हुआ था। मैंने पूरा दिन यह जानने में बिताया कि मुझे 64-बिट इंट में एक खराब मूल्य क्यों मिल रहा है, केवल यह पता लगाने के लिए कि प्रिंटफ दूसरी बाइट को अनदेखा कर रहा था। तुम सिर्फ एक int की तरह 64-बिट मान को printf में पास नहीं कर सकते।


मैं परिणाम देखने के लिए प्रिंटफ का उपयोग नहीं कर रहा हूं ... और मैं उस मूल्य का उपयोग विंडो अपारदर्शिता सेट करने के लिए करता हूं, और मेरी विंडो पूर्ण रूप से पारदर्शी है, इसलिए मान 0. है
मैक्स फ्रैरी

1

C ++ 11 तरीका std :: stod और std :: to_string का उपयोग करना है। दोनों विजुअल स्टूडियो 11 में काम करते हैं।


1

atof()मूल प्रश्न में काम क्यों नहीं किया जा रहा है: तथ्य यह है कि इसे दोगुना करने के लिए डाला जाता है मुझे संदेह करता है। कोड को बिना संकलित नहीं किया जाना चाहिए #include <stdlib.h>, लेकिन अगर संकलन संकलन को हल करने के लिए कलाकारों को जोड़ा गया था, तो atof()सही ढंग से घोषित नहीं किया गया है। यदि संकलक atof()एक इंट रिटर्न देता है, तो यह रूपांतरण चेतावनी को हल करेगा, लेकिन यह रिटर्न मान को दोहरे के रूप में मान्यता नहीं देगा ।

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

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

चेतावनियों के बिना काम करना चाहिए।


0

बूस्ट को समीकरण में खींचने के बजाय, आप अपने स्ट्रिंग (अस्थायी रूप से) को एक char[]और उपयोग के रूप में रख सकते हैं sprintf()

लेकिन निश्चित रूप से अगर आप वैसे भी बूस्ट का उपयोग कर रहे हैं, तो यह वास्तव में बहुत ज्यादा नहीं है।


0

आप स्ट्रिंग के लिए Boost lexical_cast नहीं चाहते हैं <-> फिर भी चल बिन्दु। उपयोग के मामलों का सबसेट एकमात्र सेट है, जिसके लिए लगातार बूस्ट फंक्शन पुराने कार्यों की तुलना में बदतर है- और उन्होंने मूल रूप से अपनी सभी विफलता को केंद्रित किया, क्योंकि उनके स्वयं के प्रदर्शन के परिणाम ऐसे रूपांतरणों के लिए sscanf और printf का उपयोग करने की तुलना में 20-25X SLOWER प्रदर्शन दिखाते हैं।

इसे खुद गूगल करें। बढ़ावा देना :: lexical_cast 50 रूपांतरणों की तरह कुछ को संभाल सकता है और यदि आप फ्लोटिंग पॉइंट को शामिल करते हैं तो यह # अच्छा विकल्प के रूप में अच्छा या बेहतर है (उन सभी कार्यों के लिए एकल एपीआई होने के अतिरिक्त लाभ के साथ)। लेकिन प्रदर्शन के लिहाज से टाइटन में एक हिमखंड से टकराने वाली नाव और उसकी तरह इसे लाएं।

पुराने, समर्पित str-> डबल फ़ंक्शंस सभी 30 परसेंट (या बेहतर) की तरह 10000 पर्स कर सकते हैं। वही काम करने के लिए lexical_cast 650 ms की तरह कुछ लेता है।


कोई स्रोत नहीं? मैंने खुद इसे googled किया: boost.org/doc/libs/1_55_0/doc/html/boost_lexical_cast/…
ब्लेक

0

मेरी समस्या:

  1. स्थानीय स्वतंत्र स्ट्रिंग को डबल (दशमलव विभाजक हमेशा '।')
  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 ... इस समाधान के लिए मुझे बहुत लंबा समय लगा। और मुझे अभी भी लग रहा है कि मैं स्ट्रिंग स्थानीयकरण और सामान के बारे में पर्याप्त नहीं जानता ...

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.