ฉันกำลังพยายามแปลงstd::string
เป็นfloat/double
ไฟล์. ฉันเหนื่อย:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
แต่จะส่งกลับศูนย์เสมอ วิธีอื่น ๆ ?
ฉันกำลังพยายามแปลงstd::string
เป็นfloat/double
ไฟล์. ฉันเหนื่อย:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
แต่จะส่งกลับศูนย์เสมอ วิธีอื่น ๆ ?
คำตอบ:
std::string num = "0.6";
double temp = ::atof(num.c_str());
สำหรับฉันมันเป็นไวยากรณ์ C ++ ที่ถูกต้องในการแปลงสตริงเป็นคู่
คุณสามารถทำได้ด้วย stringstream หรือ boost :: lexical_cast แต่สิ่งเหล่านี้มาพร้อมกับการลงโทษด้านประสิทธิภาพ
อ่าฮะคุณมีโครงการ Qt ...
QString winOpacity("0.6");
double temp = winOpacity.toDouble();
หมายเหตุพิเศษ:
หากข้อมูลของท่านเป็นconst char*
, QByteArray::toDouble
จะเร็วขึ้น
Standard Library (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>
ostringstream
ในตัวมันเองก็ยาวเกินไปที่จะพิมพ์ออกมานับประสาอะไรกับ ..
คำศัพท์น่ารักมาก
#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;
}
try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
catch ( boost::bad_lexical_cast const& err )
เพื่อตรวจจับข้อยกเว้น
คุณสามารถใช้ 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");
ใช่ด้วยการร่ายคำศัพท์ ใช้ stringstream และ << โอเปอเรเตอร์หรือใช้ Boost พวกเขาได้ติดตั้งไปแล้ว
เวอร์ชันของคุณเองอาจมีลักษณะดังนี้:
template<typename to, typename from>to lexical_cast(from const &x) {
std::stringstream os;
to ret;
os << x;
os >> ret;
return ret;
}
คุณสามารถใช้การร่ายเสริมคำศัพท์:
#include <boost/lexical_cast.hpp>
string v("0.6");
double dd = boost::lexical_cast<double>(v);
cout << dd << endl;
หมายเหตุ: boost :: lexical_cast จะแสดงข้อยกเว้นดังนั้นคุณควรเตรียมพร้อมที่จะจัดการเมื่อคุณส่งค่าที่ไม่ถูกต้องให้ลองส่งสตริง ("xxx")
หากคุณไม่ต้องการลากบูสต์ทั้งหมดให้ไป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
$
ทำไม atof () ไม่ทำงาน ... คุณอยู่บนแพลตฟอร์ม / คอมไพเลอร์อะไร
ฉันมีปัญหาเดียวกันใน Linux
double s2f(string str)
{
istringstream buffer(str);
double temp;
buffer >> temp;
return temp;
}
มันได้ผล.
double myAtof ( string &num){
double tmp;
sscanf ( num.c_str(), "%lf" , &tmp);
return tmp;
}
คำตอบนี้กำลังสำรองข้อมูล litb ในความคิดเห็นของคุณ ฉันมีความสงสัยอย่างยิ่งว่าคุณไม่ได้แสดงผลอย่างถูกต้อง
ฉันเคยมีสิ่งเดียวกันเกิดขึ้นกับฉันครั้งหนึ่ง ฉันใช้เวลาทั้งวันในการพยายามหาสาเหตุว่าทำไมฉันถึงได้รับค่าที่ไม่ถูกต้องเป็น int 64 บิตเพียงเพื่อจะพบว่า printf ไม่สนใจไบต์ที่สอง คุณไม่สามารถส่งค่า 64 บิตไปยัง printf ได้เหมือนกับ int
วิธี C ++ 11 คือการใช้ std :: stod และ std :: to_string ทั้งสองทำงานใน Visual Studio 11
เหตุใดจึงatof()
ไม่ทำงานในคำถามเดิม: ความจริงที่ว่ามันเป็นสองเท่าทำให้ฉันสงสัย โค้ดไม่ควรคอมไพล์โดยไม่มี#include <stdlib.h>
แต่ถ้ามีการเพิ่ม cast เพื่อแก้คำเตือนการคอมไพล์แสดงว่าatof()
ไม่ถูกต้อง หากคอมไพลเลอร์ถือว่าatof()
ส่งกลับ int การแคสต์จะแก้คำเตือนการแปลง แต่จะไม่ทำให้ค่าที่ส่งคืนถูกรับรู้ว่าเป็นสองเท่า
#include <stdlib.h>
#include <string>
...
std::string num = "0.6";
double temp = atof(num.c_str());
ควรทำงานโดยไม่มีคำเตือน
แทนที่จะลาก Boost เป็นสมการที่คุณสามารถเก็บสายของคุณ (ชั่วคราว) เป็นและการใช้งานchar[]
sprintf()
แต่แน่นอนว่าถ้าคุณใช้ Boost อยู่แล้วมันก็ไม่ใช่ปัญหามากเกินไป
คุณไม่ต้องการ Boost lexical_cast สำหรับ string <-> floating point กรณีการใช้งานชุดย่อยดังกล่าวเป็นชุดเดียวที่การเพิ่มประสิทธิภาพอย่างต่อเนื่องนั้นแย่กว่าฟังก์ชันรุ่นเก่า - และโดยพื้นฐานแล้วพวกเขาจะเน้นความล้มเหลวทั้งหมดที่นั่นเนื่องจากผลการปฏิบัติงานของตัวเองแสดงประสิทธิภาพ SLOWER 20-25X เมื่อเทียบกับการใช้ sscanf และ printf สำหรับการแปลง
Google ด้วยตัวคุณเอง boost :: lexical_cast สามารถจัดการบางอย่างเช่นการแปลง 50 รายการและหากคุณยกเว้นรายการที่เกี่ยวข้องกับจุดลอยตัว #s ดีหรือดีกว่าเป็นทางเลือกที่ชัดเจน (ด้วยข้อดีเพิ่มเติมของการมี API เดียวสำหรับการดำเนินการทั้งหมด) แต่นำมาซึ่งการลอยตัวและเหมือนเรือไททานิกชนภูเขาน้ำแข็งในแง่ของประสิทธิภาพ
ฟังก์ชัน str-> double แบบเก่าโดยเฉพาะสามารถทำ 10,000 parses ในบางอย่างเช่น 30 ms (หรือดีกว่า) lexical_cast ใช้เวลาประมาณ 650 ms ในการทำงานเดียวกัน
ปัญหาของฉัน:
โซลูชันของฉัน (ใช้ฟังก์ชัน 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 ... ใช้เวลานานพอสมควรในการแก้ปัญหานี้ และฉันยังมีความรู้สึกว่าฉันไม่รู้จักการแปลสตริงและสิ่งต่างๆมากพอ ...