2009-07-22 37 views
5

Tôi đang làm việc trên một số mã đang chuẩn hóa rất nhiều dữ liệu. Khi kết thúc xử lý, một số cặp key = "value" được ghi vào một tệp. .Triển khai báo giá thoát nhanh nhất?

Các "giá trị" một phần có thể là bất cứ điều gì, vì vậy tại thời điểm đầu ra các giá trị phải có bất kỳ dấu ngoặc kép nhúng thoát như \"

Ngay bây giờ, tôi đang sử dụng như sau:

outstream << boost::regex_replace(src, rxquotesearch, quoterepl); 
// (where rxquotesearch is boost::regex("\"") and quoterepl is "\\\\\"") 

Tuy nhiên, gprof cho thấy tôi đang chi tiêu hầu hết thời gian thực hiện của mình theo phương pháp này, vì tôi phải gọi nó cho mọi giá trị cho mỗi dòng.

Tôi tò mò nếu có cách nào nhanh hơn. không thể sử dụng std :: thay thế kể từ khi tôi thay thế một ký tự bằng hai.

Cảm ơn lời khuyên nào.

Trả lời

5

Nếu tốc độ là một mối quan tâm bạn nên sử dụng một chức năng viết tay để làm điều này. Chú ý việc sử dụng reserve() để cố gắng giữ cho bộ nhớ (tái) phân bổ ở mức tối thiểu.

string escape_quotes(const string &before) 
{ 
    string after; 
    after.reserve(before.length() + 4); 

    for (string::size_type i = 0; i < before.length(); ++i) { 
     switch (before[i]) { 
      case '"': 
      case '\\': 
       after += '\\'; 
       // Fall through. 

      default: 
       after += before[i]; 
     } 
    } 

    return after; 
} 
+0

bạn có nên đặt trước.length + 10% hay không? giả sử rằng có ít nhất một báo giá được nhúng, chúng tôi sẽ cần phát triển? – DeusAduro

+0

Vâng, hãy giả vờ với điều đó nếu cần. –

+0

Vì vậy, tôi rất tò mò về nhận xét tôi đã đăng bên dưới. Bất kỳ suy nghĩ tại sao điều này sẽ nhanh hơn xuất ra từng ký tự trực tiếp đến luồng trong vòng lặp for? – Joe

0

Đây là một triển khai sử dụng chuỗi :: tìm và chuỗi :: chèn, không chắc chắn nếu nó nhanh hơn, bạn sẽ phải tìm ra điều đó! Ở đây là:

std::string src = "hey there i have \" all \" over the f\"in pla\"ce\""; 
size_t n = 0; 
while ((n=src.find("\"",n)) != std::string::npos) 
{ 
    src.insert(n,"\\"); 
    n+=2; 
} 
std::cout << src << std::endl; 

nào in:

hey there tôi đã \ "tất cả \" qua f \ "trong pla \" ce \"

1

tôi Tôi không ngạc nhiên khi regex thực sự chậm chạp ở đây - bạn đang sử dụng một cái búa lớn, có mục đích chung để đập vào một cái đinh nhỏ bé, tất nhiên, nếu bạn cần phải làm điều gì đó thú vị hơn, thì regex có thể nhanh chóng đạt được lợi thế về mặt đơn giản.

Đối với một cách tiếp cận đơn giản/nhanh hơn, bạn có thể thử viết chuỗi thoát vào một bộ đệm riêng biệt một ký tự cùng một lúc. Sau đó, nó trở nên tầm thường để thêm thoát, và bạn không lãng phí bất kỳ thời gian tái phân bổ chuỗi hoặc các ký tự chuyển dịch. Khó khăn lớn nhất sẽ được quản lý kích thước của bộ đệm của bạn, nhưng bạn chỉ có thể sử dụng một vector cho rằng, và tái sử dụng cùng một vector cho mỗi chuỗi để tránh phân bổ lặp đi lặp lại. Hiệu suất đạt được sẽ phụ thuộc rất nhiều vào các chi tiết về cách thức hoạt động của vector, nhưng bạn luôn có thể luộc nó xuống các mảng thô và quản lý bộ nhớ thủ công nếu bạn cần.

Những thói quen có thể trông như thế này, nếu bạn sử dụng vector:

vector<char> buf; 
for(some_iterator it = all_the_strings.begin(); 
    it != all_the_strings.end(); ++it) 
{ 
    buf.clear(); 
    const string & str = *it; 
    for(size_t i = 0; i < str.size(); ++i) 
    { 
     if(str[i] == '"' || str[i] == '\\') 
      buf.push_back('\\'); 
     buf.push_back(str[i]); 
    } 
    buf.push_back('\0'); 

    // note: this is not guaranteed to be safe, see answer comments 
    const char * escaped = &buf[0]; 

    // print escaped string to file here... 
} 
+0

Với tối ưu hóa và phân bổ trước, véc-tơ phải nhanh như phần lớn thời gian (số lần không bắt buộc phải tăng). Bạn có khả năng nhanh hơn tôi, vì sự chuyển dịch đang diễn ra trong tôi. – DeusAduro

+1

Eek! '& buf [0]' không phải là ý tưởng hay nhất ... –

+0

Tôi có thể tin rằng nó có lẽ không phải là tốt nhất - bạn có thể giải thích tại sao và/hoặc đề xuất một giải pháp thay thế tốt hơn? – Charlie

2

Tôi sẽ không lấy chuỗi nguồn và tạo chuỗi đầu ra mới.
Tôi sẽ lặp qua chuỗi nguồn và in từng ký tự, nếu ký tự là một dấu ngoặc kép thì chỉ cần in một dấu "\" trước khi in.

+0

Thật thú vị, tôi lấy đoạn trích của John Kugelman và sử dụng nó thay vì viết trực tiếp vào dòng, và nó có thể đo chậm hơn lần đầu tiên xây dựng chuỗi tạm thời rồi viết toàn bộ chuỗi vào luồng. Không phải những gì tôi đã mong đợi ở tất cả! – Joe

+0

@Joe: Nó có ý nghĩa với tôi, bởi vì nó đòi hỏi N cuộc gọi đến chức năng đầu ra dòng, mà có lẽ có một chút logic bên trong nó. Nếu bạn xây dựng đầu ra trong một bộ đệm tạm thời, bạn có thể (nếu cần) giảm xuống một số lượng nhỏ các cuộc gọi phương thức và một vòng lặp nội bộ khá chặt chẽ, có vẻ hiệu quả hơn nhiều. Nếu tốc độ là những gì thực sự quan trọng ở đây, nó sẽ không nhanh hơn nhiều. – Charlie

+0

Chỉ cần đi để cho thấy bạn không biết cho đến khi bạn thực sự mã và nó cố gắng. Điều này "có thể" được nhanh hơn trên một máy tính hoặc trình biên dịch khác nhau, tất cả phụ thuộc vào chi phí in các ký tự đơn so với chuỗi hoàn chỉnh. – KPexEA

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