2013-09-24 83 views
6

Tôi đang sử dụng boost::lexical_cast<std::string>(double) để chuyển đổi chuỗi thành chuỗi kép, tạo luồng byte tuần tự JSON, nghĩa là (ở phía trên) được phân tích bằng .NET.Đảm bảo bất biến cục bộ của tăng :: lexical_cast <>

Tôi có thể buộc .NET sử dụng InvariantCulture để phân tích cú pháp, do đó trả về kết quả có thể dự đoán được trên mọi ngôn ngữ có thể.

Tuy nhiên, tôi không thể tìm thấy bảo đảm này trong tài liệu boost::lexical_cast. Tôi đã thử nó một chút, và nó hoạt động theo cùng một cách cho các miền địa phương khác nhau được thiết lập. Nhưng, tôi không thể chắc chắn chỉ từ vài bài kiểm tra, tôi thiếu một cái gì đó trong tài liệu, hoặc điều này không thể được bảo đảm ở tất cả, và tôi phải sử dụng cái gì khác?

EDIT: Tôi đã tìm thấy sự cố.

std::locale::global(std::locale("Czech")); 
std::cout << boost::lexical_cast<std::string>(0.15784465) << std::endl; 

trả về 0,15784465 và điều đó là không mong muốn. Tôi có thể buộc boost::lexical_cast<> không nhận thức được ngôn ngữ không?

Trả lời

5

Tôi có thể buộc tăng cường :: lexical_cast <> không biết địa phương không?

Không, tôi không nghĩ điều đó là có thể. Điều tốt nhất bạn có thể làm là gọi

std::locale::global(std::locale::classic()); 

để đặt ngôn ngữ toàn cục thành ngôn ngữ "C" là boost::lexical_cast dựa vào ngôn ngữ toàn cầu. Tuy nhiên, vấn đề là nếu một nơi nào khác trong mã địa phương toàn cầu được thiết lập để một cái gì đó khác trước khi gọi boost::lexical_cast, sau đó bạn vẫn có cùng một vấn đề. Vì vậy, một giải pháp mạnh mẽ sẽ là imbue một stringstream như vậy, và bạn có thể luôn luôn chắc chắn rằng công trình này:

std::ostringstream oss; 
oss.imbue(std::locale::classic()); 
oss.precision(std::numeric_limits<double>::digits10); 
oss << 0.15784465; 
+4

Về cơ bản, vấn đề là miền địa phương C++ không phải là thuộc tính có tính chất tôn trọng RAII. – MSalters

1

Một giải pháp tốt hơn cho vấn đề này là sử dụng một boost::locale thay vì một std :: locale như ngôn ngữ globale. Từ documentation:

Thiết lập miền địa phương toàn cầu có tác dụng phụ xấu ... nó ảnh hưởng thậm chí printf và các thư viện như boost :: lexical_cast cho định dạng không chính xác hoặc không mong muốn. Trong thực tế, nhiều thư viện của bên thứ ba bị hỏng trong một tình huống như vậy. Không giống như thư viện bản địa hóa chuẩn, Boost.Locale không bao giờ thay đổi định dạng số cơ bản, ngay cả khi nó sử dụng phụ trợ nội địa hóa dựa trên std, do đó, theo mặc định, các số luôn được định dạng bằng ngôn ngữ kiểu C. Định dạng số địa phương yêu cầu các cờ cụ thể.

Ngôn ngữ bản địa yêu cầu bạn chỉ định rõ ràng khi bạn muốn định dạng số là nhận biết miền, phù hợp hơn với các quyết định thư viện gần đây như std :: money_put.

+0

Bạn sẽ sử dụng điều này như thế nào với boost :: lexical_cast? – Managarm

+0

boost :: lexical_cast sử dụng ngôn ngữ toàn cầu. boost :: locale library tạo ra các ngôn ngữ với cải thiện hành vi định dạng số (trong số các cải tiến khác). Vì vậy, chỉ cần thiết lập miền địa phương globale cho một miền địa phương tăng, và nó tăng :: lexical_cast sẽ áp dụng hành vi tự động. Nếu điều đó không rõ ràng, hãy cho tôi biết, tôi sẽ làm một ví dụ. – Spacemoose

+0

Đó là đủ cho tôi :) cảm ơn bạn! – Managarm