2010-10-08 45 views
15

Với chuỗi sau, "Hi ~+ and ^*. Is ^* still flying around ~+?"C++ thay thế nhiều chuỗi trong một chuỗi trong một lần chạy đơn

Tôi muốn thay thế tất cả các lần xuất hiện của "~+""^*" với "Bobby" và "Danny", do đó chuỗi trở thành:

"Hi Bobby and Danny. Is Danny still flying around Bobby?"

Tôi không muốn gọi hàm Boost thay thế hai lần để thay thế các lần xuất hiện của hai giá trị khác nhau.

+0

Chuỗi đến từ đâu? – JoshD

+0

Như chúng ta biết 'O (n) + O (n)' vẫn là 'O (n)', động lực * thực * ở đây là gì? – Arun

+1

Chuỗi/dữ liệu thực tế có khả năng là 100 GB kích thước, được xử lý từng bước và trong khi gọi thay thế hai lần vẫn là O (n), n là khá lớn. –

Trả lời

0

Tăng chuỗi_algo không có hàm replace_all. Bạn có thể sử dụng nó.

+0

Cảm ơn Matthew, nhưng điều đó chỉ mất một giá trị để được chuyển đổi và tôi sẽ cần phải gọi nó hai lần. Tôi đang cố gắng để tìm ra nó có một cách để cung cấp cho bản chất một bản đồ, nếu bạn tìm thấy x1 thay thế với y1 và x2 với y2 và như vậy và quét trên chuỗi chỉ xảy ra một lần. –

0

Tôi khuyên bạn nên sử dụng thư viện Định dạng tăng cường. Thay vì ~+^*, bạn sử dụng %1%%2%, v.v., có hệ thống hơn một chút.

Ví dụ từ các tài liệu:.

cout << boost::format("writing %1%, x=%2% : %3%-th try") % "toto" % 40.23 % 50; 
    // prints "writing toto, x=40.230 : 50-th try" 

Cheers & hth,

- Alf

+0

Cảm ơn gợi ý Alf, tuy nhiên tôi không có quyền kiểm soát dữ liệu đầu vào nên đề xuất của bạn sẽ không hoạt động. Tôi phải xử lý nội dung và thay đổi các giá trị bên trong như được chỉ định bởi người dùng đã gọi mã. –

5

tôi quản lý để thực hiện các chức năng thay thế được yêu cầu sử dụng Boost.Iostreams. Cụ thể, phương pháp tôi đã sử dụng là luồng lọc sử dụng cụm từ thông dụng để khớp với những gì cần thay thế. Tôi không chắc chắn về hiệu suất trên các tệp có kích thước gigabyte. Bạn sẽ cần phải kiểm tra nó tất nhiên. Dù sao, đây là mã số:

#include <boost/regex.hpp> 
#include <boost/iostreams/filter/regex.hpp> 
#include <boost/iostreams/filtering_stream.hpp> 
#include <iostream> 

int main() 
{ 
    using namespace boost::iostreams; 

    regex_filter filter1(boost::regex("~\\+"), "Bobby"); 
    regex_filter filter2(boost::regex("\\^\\*"), "Danny"); 

    filtering_ostream out; 
    out.push(filter1); 
    out.push(filter2); 
    out.push(std::cout); 

    out << "Hi ~+ and ^*. Is ^* still flying around ~+?" << std::endl; 

    // for file conversion, use this line instead: 
    //out << std::cin.rdbuf(); 
} 

Các bản in trên "Hi Bobby and Danny. Is Danny still flying around Bobby?" khi chạy, giống như mong đợi.

Thật thú vị khi xem kết quả hiệu suất, nếu bạn quyết định đo lường.

Daniel

Chỉnh sửa: Tôi chỉ nhận ra rằng regex_filter nhu cầu để đọc toàn bộ chuỗi ký tự vào bộ nhớ, làm cho nó khá vô dụng cho đầu vào gigabyte cỡ. Oh well ...

0

Tôi khuyên bạn nên sử dụng std :: map. Vì vậy, bạn có một bộ thay thế, vì vậy làm:

std::map<std::string,std::string> replace; 
replace["~+"]=Bobby; 
replace["^*"]=Danny; 

Sau đó, bạn có thể đặt chuỗi thành một vector của chuỗi và kiểm tra xem nếu mỗi chuỗi xảy ra trong bản đồ và nếu nó thay thế nó, bạn muốn cũng cần phải loại bỏ bất kỳ dấu chấm câu nào từ cuối. Hoặc thêm chúng vào phần thay thế. Sau đó bạn có thể làm điều đó trong một vòng lặp. Tôi không chắc chắn nếu điều này thực sự hiệu quả hơn hoặc hữu ích hơn so với tăng mặc dù.

3

Tôi đã nhận thấy đã một năm kể từ khi hoạt động này, nhưng đối với những gì nó đáng giá. I came across an article on CodeProject hôm nay tuyên bố giải quyết vấn đề này - có thể bạn có thể sử dụng ý tưởng từ đó:

Tôi không thể xác minh tính chính xác của nó, nhưng có thể đáng xem.:)

Việc triển khai chắc chắn yêu cầu giữ toàn bộ chuỗi trong bộ nhớ, nhưng bạn có thể dễ dàng làm việc xung quanh (như với bất kỳ triển khai nào khác thực hiện thay thế) miễn là bạn có thể chia đầu vào thành khối và đảm bảo rằng bạn không bao giờ chia ở vị trí bên trong một biểu tượng sẽ được thay thế. (Một cách dễ dàng để làm điều đó trong trường hợp của bạn là để chia ở một vị trí nơi mà các char tiếp theo không phải là bất kỳ ký tự được sử dụng trong một biểu tượng.)

-

Có một lý do ngoài tầm hoạt động (mặc dù đó là một lý do đầy đủ trong cuốn sách của tôi) để thêm phương thức "ReplaceMultiple" vào thư viện chuỗi của một người: Chỉ cần thực hiện thao tác thay thế N lần là KHÔNG chính xác nói chung.

Nếu các giá trị được thay thế cho các ký hiệu không bị hạn chế, giá trị có thể được coi là các ký hiệu trong các hoạt động thay thế tiếp theo. (Có thể có những tình huống mà bạn thực sự muốn muốn điều này, nhưng chắc chắn có những trường hợp bạn không sử dụng. Biểu tượng lạ mắt làm giảm mức độ nghiêm trọng của sự cố, nhưng không giải quyết được vấn đề và "xấu xí" vì các chuỗi được định dạng có thể được người dùng xác định - và do đó không nên yêu cầu các ký tự lạ.)

Tuy nhiên, tôi nghi ngờ có lý do chính đáng. Thao tác "ReplaceMultiple" đơn giản không phải là (rõ ràng) được xác định rõ ràng nói chung.

Để xem điều này, hãy xem xét điều này có thể có nghĩa là để "thay thế 'aa' bằng '!' và 'baa' với '?' trong chuỗi 'abaa' "? Là kết quả 'ab!' hoặc 'a?' - hoặc là một sự thay thế bất hợp pháp?

Có thể yêu cầu ký hiệu là "không có tiền tố", nhưng trong nhiều trường hợp không thể chấp nhận được. Nói rằng tôi muốn sử dụng điều này để định dạng một số văn bản mẫu. Và nói rằng mẫu của tôi là dành cho mã. Tôi muốn thay thế "§table" bằng tên bảng cơ sở dữ liệu chỉ được biết khi chạy. Sẽ rất khó chịu nếu bây giờ tôi không thể sử dụng "§t" trong cùng một mẫu. Kịch bản lệnh có thể là một cái gì đó hoàn toàn chung chung, và một ngày nào đó tôi gặp khách hàng thực sự sử dụng "§" trong tên bảng của mình ... có khả năng làm cho thư viện mẫu của tôi thay vì ít hữu dụng hơn.

Một giải pháp tốt hơn có thể là sử dụng trình phân tích cú pháp đệ quy thay vì chỉ thay thế các chữ cái. :)

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