2013-03-28 31 views
15

Tôi đang sử dụng boost :: split để phân tích cú pháp một tệp dữ liệu. Tệp dữ liệu chứa các dòng như sau.Làm cách nào để sử dụng phân tách tăng để tách một chuỗi và bỏ qua các giá trị rỗng?

data.txt

1:1~15 ASTKGPSVFPLAPSS SVFPLAPSS -12.6 98.3  

Các khoảng trắng giữa các mục là tab. Mã tôi phải chia dòng trên là như sau.

std::string buf; 
/*Assign the line from the file to buf*/ 
std::vector<std::string> dataLine; 
boost::split(dataLine, buf , boost::is_any_of("\t "), boost::token_compress_on);  //Split data line 
cout << dataLine.size() << endl; 

Đối với dòng trên mã tôi sẽ nhận được một bản in ra 5, nhưng tôi nhận 6. Tôi đã cố gắng đọc qua các tài liệu hướng dẫn và giải pháp này dường như nó nên làm những gì tôi muốn, rõ ràng tôi thiếu cái gì đó. Cảm ơn!

Chỉnh sửa: Chạy vòng lặp như sau trên dataLine bạn nhận được thông tin sau.

cout << "****" << endl; 
for(int i = 0 ; i < dataLine.size() ; i ++) cout << dataLine[i] << endl; 
cout << "****" << endl; 


**** 
1:1~15 
ASTKGPSVFPLAPSS 
SVFPLAPSS 
-12.6 
98.3 

**** 
+0

giá trị được lưu trữ trong dataLine là gì? –

+0

[Tôi nhận được 5] (http://liveworkspace.org/code/1KMXAm$1), 'buf' của bạn chứa nội dung khác. –

+0

Có lẽ nó đã không sao chép chính xác vào trang này, bạn đã sao chép không đúng vào mã kiểm tra. Hãy để tôi xem về việc đảm bảo nó sao chép chính xác. – PhiloEpisteme

Trả lời

15

Mặc dù "dải phân cách liền kề được sáp nhập lại với nhau", nó có vẻ như các delimeters trailing làm cho vấn đề, vì ngay cả khi họ được đối xử như một, nó vẫn một delimeter.

Vì vậy, vấn đề của bạn không thể được giải quyết chỉ với split(). Nhưng may mắn là Boost String Algo có trim() and trim_if(), loại dải trắng hoặc khoảng cách từ đầu và cuối của chuỗi. Vì vậy, chỉ cần gọi trim() trên buf, như thế này:

std::string buf = "1:1~15 ASTKGPSVFPLAPSS SVFPLAPSS -12.6 98.3 "; 
std::vector<std::string> dataLine; 
boost::trim_if(buf, boost::is_any_of("\t ")); // could also use plain boost::trim 
boost::split(dataLine, buf, boost::is_any_of("\t "), boost::token_compress_on); 
std::cout << out.size() << std::endl; 

Câu hỏi này đã được hỏi: boost::split leaves empty tokens at the beginning and end of string - is this desired behaviour?

+0

Tôi đã tìm kiếm nhưng không thể tìm thấy câu hỏi trên. Xin lỗi cho repost. – PhiloEpisteme

7

tôi sẽ khuyên bạn sử dụng C++ String Toolkit Library. Thư viện này nhanh hơn nhiều so với Boost trong quan điểm của tôi. Tôi đã từng sử dụng Boost để chia nhỏ (aka tokenize) một dòng văn bản nhưng thấy thư viện này phù hợp hơn với những gì tôi muốn.

Một trong những điều tuyệt vời về strtk::parse là chuyển đổi mã thông báo thành giá trị cuối cùng của chúng và kiểm tra số lượng phần tử.

bạn có thể sử dụng nó như vậy:

std::vector<std::string> tokens; 

// multiple delimiters should be treated as one 
if(!strtk::parse(dataLine, "\t", tokens)) 
{ 
    std::cout << "failed" << std::endl; 
} 

--- phiên bản khác

std::string token1; 
std::string token2; 
std::string token3: 
float value1; 
float value2; 

if(!strtk::parse(dataLine, "\t", token1, token2, token3, value1, value2)) 
{ 
    std::cout << "failed" << std::endl; 
    // fails if the number of elements is not what you want 
} 

tài liệu trực tuyến cho thư viện: String Tokenizer Documentation Liên kết với các mã nguồn: C++ String Toolkit Library

+0

Tôi có thể xem xét chuyển sang STL trong tương lai cho các nhu cầu của mình, nhưng hiện tại tôi có rất nhiều mã sử dụng boost. – PhiloEpisteme

+14

Tôi cũng có một số lượng sử dụng mã đáng kinh ngạc. Tôi đã sử dụng tokenizer tăng quá. Tôi chuyển chức năng đặc biệt này thành strtk vì tốc độ. Thêm vào tốc độ thêm khả năng chuyển đổi mã thông báo thành các con số khi đang di chuyển và nó không có trí tuệ để tôi chuyển đổi. – DannyK

1

hàng đầu và khoảng trống ở cuối được cố tình để lại một mình bởi boost::split bởi vì nó không biết nếu nó có ý nghĩa hay không. Giải pháp là sử dụng boost::trim trước khi gọi boost::split.

#include <boost/algorithm/string/trim.hpp> 

.... 

boost::trim(buf); 
+1

Trước khi gọi điện thoại? Thông thường bạn chia và sau đó cắt các thẻ, phải không? – Nick

+0

@Nick: Điều đó sẽ phụ thuộc. Trong câu hỏi ban đầu, người dùng đã tách các tệp được phân tách bằng tab, vì vậy cắt tỉa trước là chính xác. –

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