Tôi đang cố gắng chuyển đổi std::stringsang float/double. Tôi đã thử:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
Nhưng nó luôn trả về số không. Bất kỳ cách nào khác?
Tôi đang cố gắng chuyển đổi std::stringsang float/double. Tôi đã thử:
std::string num = "0.6";
double temp = (double)atof(num.c_str());
Nhưng nó luôn trả về số không. Bất kỳ cách nào khác?
Câu trả lời:
std::string num = "0.6";
double temp = ::atof(num.c_str());
Đối với tôi, nó là một cú pháp C ++ hợp lệ để chuyển đổi một chuỗi thành một chuỗi kép.
Bạn có thể làm điều đó với stringstream hoặc boost :: lexical_cast nhưng chúng đi kèm với hình phạt về hiệu suất.
Ahaha bạn có một dự án Qt ...
QString winOpacity("0.6");
double temp = winOpacity.toDouble();
Lưu ý thêm:
Nếu dữ liệu đầu vào là a const char*, QByteArray::toDoublesẽ nhanh hơn.
Thư viện Chuẩn (C ++ 11) cung cấp chức năng mong muốn với std::stod:
std::string s = "0.6"
std::wstring ws = "0.7"
double d = std::stod(s);
double dw = std::stod(ws);
Nói chung cho hầu hết các loại cơ bản khác, hãy xem <string>. Cũng có một số tính năng mới cho chuỗi C. Xem<stdlib.h>
ostringstreambản thân nó chỉ đơn giản là quá lâu để gõ ra, hãy để một mình sử dụng ..
Dàn diễn viên Lexical rất đẹp.
#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 )để bắt ngoại lệ.
Bạn có thể sử dụng 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;
}
Sử dụng:
double number= StringToNumber<double>("0.6");
Có, với một dàn diễn viên từ vựng. Sử dụng một chuỗi chuỗi và toán tử << hoặc sử dụng Boost, họ đã triển khai nó.
Phiên bản của riêng bạn có thể trông giống như sau:
template<typename to, typename from>to lexical_cast(from const &x) {
std::stringstream os;
to ret;
os << x;
os >> ret;
return ret;
}
Bạn có thể sử dụng tăng cường diễn viên từ vựng:
#include <boost/lexical_cast.hpp>
string v("0.6");
double dd = boost::lexical_cast<double>(v);
cout << dd << endl;
Lưu ý: boost :: lexical_cast ném ra ngoại lệ, vì vậy bạn nên chuẩn bị đối phó với nó khi bạn chuyển giá trị không hợp lệ, hãy thử chuyển chuỗi ("xxx")
Nếu bạn không muốn tăng tất cả, hãy chọn strtod(3)từ <cstdlib>- nó đã trả về một nhân đôi.
#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;
}
Kết quả đầu ra:
$ g++ -o s s.cc
$ ./s
0.6 0.6
$
Tại sao atof () không hoạt động ... bạn đang sử dụng nền tảng / trình biên dịch nào?
Câu trả lời này đang ủng hộ rất nhiều ý kiến của bạn. Tôi rất nghi ngờ rằng bạn không hiển thị kết quả đúng cách.
Tôi đã có một lần chính xác điều đó xảy ra với tôi. Tôi đã dành cả ngày để cố gắng tìm ra lý do tại sao tôi nhận được một giá trị xấu vào một int 64-bit, chỉ để phát hiện ra rằng printf đang bỏ qua byte thứ hai. Bạn không thể chỉ chuyển một giá trị 64-bit vào printf giống như một giá trị int.
Về lý do tại sao atof()không hoạt động trong câu hỏi ban đầu: thực tế là nó được chọn tăng gấp đôi khiến tôi nghi ngờ. Mã không nên biên dịch mà không có #include <stdlib.h>, nhưng nếu ép kiểu được thêm vào để giải quyết cảnh báo biên dịch, thì mã đó atof()không được khai báo chính xác. Nếu trình biên dịch giả sử atof()trả về một int, việc ép kiểu sẽ giải quyết cảnh báo chuyển đổi, nhưng nó sẽ không khiến giá trị trả về được nhận dạng là một giá trị kép.
#include <stdlib.h>
#include <string>
...
std::string num = "0.6";
double temp = atof(num.c_str());
nên hoạt động mà không có cảnh báo.
Thay vì kéo Boost vào phương trình, bạn có thể giữ chuỗi của mình (tạm thời) như một char[]và sử dụng sprintf().
Nhưng tất nhiên nếu bạn đang sử dụng Boost, nó thực sự không quá nhiều vấn đề.
Dù sao thì bạn cũng không muốn Boost lexical_cast cho chuỗi <-> dấu phẩy động. Tập hợp con các trường hợp sử dụng đó là tập hợp duy nhất mà mức tăng liên tục kém hơn các chức năng cũ hơn- và về cơ bản chúng tập trung tất cả lỗi của chúng vào đó, bởi vì kết quả hiệu suất của riêng chúng cho thấy hiệu suất CHẬM hơn 20-25 lần so với sử dụng sscanf và printf cho các chuyển đổi như vậy.
Google nó cho mình. boost :: lexical_cast có thể xử lý một số thứ như 50 chuyển đổi và nếu bạn loại trừ những chuyển đổi liên quan đến dấu phẩy động #s thì càng tốt hoặc tốt hơn như các lựa chọn thay thế rõ ràng (với lợi thế bổ sung là có một API duy nhất cho tất cả các hoạt động đó). Nhưng mang lại những chiếc phao nổi và nó giống như con tàu Titanic va vào một tảng băng trôi về mặt hiệu suất.
Các hàm kép str-> cũ, chuyên dụng đều có thể thực hiện 10000 phân tích cú pháp trong 30 ms (hoặc tốt hơn). lexical_cast mất khoảng 650 mili giây để thực hiện công việc tương tự.
Vấn đề của tôi:
Giải pháp của tôi (sử dụng hàm 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 ... tôi mất khá nhiều thời gian để đi đến giải pháp này. Và tôi vẫn có cảm giác rằng tôi không biết đủ về bản địa hóa chuỗi và những thứ ...