2017-08-11 12 views
8

Tôi đang viết trình phân tích cú pháp C++ cho tệp tùy chọn tùy chỉnh cho một ứng dụng. Tôi có một vòng lặp đọc các dòng dưới dạng option=value từ một tệp văn bản nơi value phải được chuyển đổi thành double. Trong giả nó như sau:Làm thế nào để chuyển đổi std :: string_view để tăng gấp đôi?

while(not EOF) 
    statement <- read_from_file 
    useful_statement <- remove whitespaces, comments, etc from statement 
    equal_position <- find '=' in useful_statement 
    option_str <- useful_statement[0:equal_position) 
    value_str <- useful_statement[equal_position:end) 
    find_option(option_str) <- double(value_str) 

Để xử lý tách chuỗi và đi xung quanh để chức năng, tôi sử dụng std::string_view vì nó tránh sao chép quá mức và nêu rõ mục đích của việc xem các phân đoạn của một std::string tồn tại trước đó. Tôi đã làm tất cả mọi thứ đến mức mà std::string_view value_str trỏ đến phần chính xác của useful_statement có chứa giá trị tôi muốn trích xuất, nhưng tôi không thể tìm ra cách để đọc một số double từ một số std::string_view.

Tôi biết về std::stod không hoạt động với std::string_view. Nó cho phép tôi viết

double value = std::stod(std::string(value_str)); 

Tuy nhiên, điều này là xấu xí vì nó chuyển đổi thành một chuỗi mà không thực sự cần thiết, và mặc dù nó sẽ có lẽ không tạo sự khác biệt đáng chú ý trong trường hợp của tôi, nó có thể là quá chậm nếu người ta phải đọc một số lượng lớn các con số từ một tập tin văn bản.

Mặt khác, atof sẽ không hoạt động vì tôi không thể đảm bảo một trình kết thúc vô hiệu. Tôi có thể hack nó bằng cách thêm \0 vào useful_statement khi xây dựng nó, nhưng điều đó sẽ làm cho mã gây nhầm lẫn cho người đọc và làm cho nó quá dễ dàng để phá vỡ nếu mã được thay đổi/refactored.

Vì vậy, cách thức sạch sẽ, trực quan và hợp lý để thực hiện việc này là gì?

+1

Bạn có hài lòng với việc sử dụng tăng không? Tôi nghĩ bạn có thể làm điều này với 'boost :: convert (stringview);'. Tôi đã nhận nó ra khỏi đây ... nhận xét cuối cùng trên trang https://github.com/boostorg/convert/issues/29 –

+1

Tìm tốt. Đó có thể là 'boost :: convert (stringview, stringview.length())', mặc dù. Nó chắc chắn là sạch hơn so với chuyển đổi thành một chuỗi và hy vọng nhanh hơn. Nhược điểm duy nhất là phụ thuộc bổ sung để tăng cường. – patatahooligan

+0

Tắt chủ đề: Rõ ràng đây là psuedocode, nhưng hãy cẩn thận trong cách bạn thực hiện "while (not EOF)". Điều nhỏ nhặt 'while (! Stream.eof())' có một vài gotchas khó chịu. – user4581301

Trả lời

10

Vì bạn đã đánh dấu câu hỏi của mình bằng C++ 1z, khi đó (theo lý thuyết) có nghĩa là bạn có quyền truy cập vào from_chars. Nó có thể xử lý của bạn chuyển đổi chuỗi sang số mà không cần bất cứ điều gì nhiều hơn một cặp const char* s:

double dbl; 
auto result = from_chars(&value_str[0], &value_str[0] + value_str.size(), dbl); 

Tất nhiên, điều này đòi hỏi rằng thư viện tiêu chuẩn của bạn cung cấp một thực hiện from_chars. Libstdc++ does not, cũng không phải does libc++. Hoặc Visual Studio, cho rằng vấn đề.

+0

'from_chars()' lấy một 'double &' không phải là 'double *'. Ngoài ra đó là một giao diện khó xử ... cho rằng không ai cung cấp nó, có lẽ đó là một cơ hội tốt để có nó mất một 'string_view' ... – Barry

+1

Điều này sẽ được chính xác những gì tôi đang tìm kiếm nếu nó đã được thực hiện. Tôi khuyên bạn nên thay đổi cuộc gọi thành 'from_chars (& value_str.front(), & value_str.back(), dbl) 'để dễ đọc, btw. @Barry: không có nhiều lý do để làm cho nó có 'string_view' Làm việc với' char * 'làm cho nó phổ quát và nó tầm thường để có được những từ' string_view'. – patatahooligan

+0

@Barry: Sẽ khó khăn hơn nếu 'basic_string_view' đảm bảo rằng các vòng lặp của nó là * con trỏ *. –

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