2013-11-01 31 views
8

Với bản nâng cấp gần đây của tôi lên Mac OS X 10.9, thư viện C++ chuẩn mặc định đã thay đổi từ libstdC++ thành libC++. Kể từ đó tôi quan sát hành vi bất ngờ của toán tử stringstream >> (double) được ghi lại trong ví dụ mã dưới đây.Sự khác biệt giữa toán tử của istream >> (double & val) giữa libC++ và libstdC++

Tóm lại, libC++ dường như có vấn đề với việc trích xuất các giá trị kép từ chuỗi khi giá trị kép được theo sau bởi một chữ cái.

Tôi đã kiểm tra tiêu chuẩn (2003) nhưng tôi không thể tìm thấy bất kỳ thông tin cụ thể nào nếu việc trích xuất có hiệu quả trong trường hợp này hay không.

Vì vậy, tôi sẽ biết ơn bất kỳ đầu vào nào cho dù đây là lỗi trong libC++ hoặc libstdC++.

#include <sstream> 
#include <iostream> 

using namespace std; 

void extract_double(const string & s) 
{ 
    stringstream ss; 
    double d; 

    ss << s; 
    ss >> d; 
    if(!ss.fail()) 
    cout << "'" << ss.str() << "' converted to " << d << endl; 
    else 
    cout << "'" << ss.str() << "' failed to convert to double" << endl; 
} 

int main() 
{ 
    extract_double("-4.9"); 
    extract_double("-4.9 X"); 
    extract_double("-4.9_"); 
    extract_double("-4.9d"); 
    extract_double("-4.9X"); 
} 

Biên dịch mã với c++ --stdlib=libc++ streamtest.cxx cho

'-4.9' converted to -4.9 
'-4.9 X' converted to -4.9 
'-4.9_' converted to -4.9 
'-4.9d' failed to convert to double 
'-4.9X' failed to convert to double 

Biên dịch mã với c++ --stdlib=libstdc++ streamtest.cxx cho

'-4.9' converted to -4.9 
'-4.9 X' converted to -4.9 
'-4.9_' converted to -4.9 
'-4.9d' converted to -4.9 
'-4.9X' converted to -4.9 

phiên bản Compiler là

$ c++ --version 
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn) 
Target: x86_64-apple-darwin13.0.0 
Thread model: posix 
+0

Địa phương là 'C' trong cả hai trường hợp. –

Trả lời

2

Có vẻ như libstdC++ là đúng và libC++ là sai, theo 22.4.2.1.2 của tiêu chuẩn (2011).

Ở giai đoạn 2,

Nếu nó [nhân vật - nm] không được loại bỏ, sau đó kiểm tra được thực hiện để xác định xem c được phép là nhân vật tiếp theo của một lĩnh vực đầu vào của specifier chuyển đổi trở lại bởi Giai đoạn 1 ["% g" trong trường hợp này - nm]. Nếu vậy, nó được tích lũy.

%g trình chuyển đổi không chấp nhận d hoặc X ký tự, ký tự không được tích lũy. Nó không bị hủy bỏ (hoặc chỉ có thể loại bỏ các ký tự phân cách nhóm). Do đó, Giai đoạn 2 phải kết thúc tại thời điểm này.

Sau đó, ở giai đoạn 3 ký tự tích lũy được chuyển đổi.

Dường như libC++ tích lũy sai dX ở giai đoạn 2, sau đó cố gắng chuyển đổi chúng và điều này không thành công.

+0

Tôi đã báo cáo sự cố với những người libC++. Xem lỗi [17782] (http://llvm.org/bugs/show_bug.cgi?id=17782) –

+0

Chỉ xuất hiện nếu ký tự sau là 'A' .. 'F', 'I', 'N' , 'P' và 'X' (và các ký tự tương tự trong chữ thường) –

+0

@MarshallClow: OK, A đến F và X có thể xuất hiện trong các số thập lục phân và chúng thực sự xuất hiện trong phần có liên quan của tiêu chuẩn, vì vậy có thể xem nơi mọi thứ đã đi sai nếu đó là những thủ phạm duy nhất. Nhưng làm thế nào tôi, N và P đến chơi? –

Các vấn đề liên quan