2013-03-19 24 views
6

Tôi gọi đệ quy một hàm truyền qua làm đối số một chuỗi con luôn bắt đầu từ đầu chuỗi hiện tại đến vị trí. Nếu tôi đang sử dụng C, tôi có thể chuyển con trỏ đến vị trí đầu tiên của chuỗi và sau đó là độ dài cần thiết. Tuy nhiên, tôi muốn đạt được kết quả tương tự bằng cách sử dụng lớp string. Có thể không? Nếu tôi sử dụng const, trình biên dịch có đủ thông minh để tự thực hiện tối ưu hóa không? Thậm chí tốt hơn, là có một cách để kiểm tra của riêng tôi cho dù trình biên dịch thực sự làm cho một bản sao của đối số hoặc vượt qua một tham chiếu?Tôi làm cách nào để chuyển chuỗi con theo tham chiếu?

Câu hỏi của tôi được thúc đẩy sau khi đã viết mã sau đây vượt qua các bài kiểm tra về sự cố Alphacode trên poj, khi ai đó sử dụng atoi thay vì atof.

#include <iostream> 
#include <algorithm> 
#include <map> 
#include <vector> 
#include <string> 

using namespace std; 

map<string, int> cache; 

bool valid_character_number(string a) { 
    return 0 < stoi(a.substr(a.size() - 2, 2)) && stoi(a.substr(a.size() - 2, 2)) <= 26; 
} 

bool zero_last_digit(string a) { 
    return a[a.size() - 1] == '0'; 
} 
bool zero_before_last_digit(string a) { 
    return a[a.size() - 2] == '0'; 
} 

int decodings(string a) { 
    if (a.size() == 0) 
     return 1; 
    if (a.size() == 1) { 
     if (zero_last_digit(a)) 
      return 0; 
     else 
      return 1; 
    } 
    if (cache.find(a) != cache.end()) 
     return cache[a]; 

    if (zero_last_digit(a) && valid_character_number(a)) 
     return cache[a] = decodings(a.substr(0, a.size() - 2)); 
    else if (valid_character_number(a) && !zero_before_last_digit(a)) 
     return cache[a] = decodings(a.substr(0, a.size() - 1)) + decodings(a.substr(0, a.size() - 2)); 
    else 
     return cache[a] = decodings(a.substr(0, a.size() - 1)); 
} 

int main() { 
    string input; 
    while (true) { 
     cin >> input; 
     if (input.size() == 1 && stoi(input) == 0) 
      return 0; 
     cout << decodings(input) << endl; 
    } 

    return 0; 
} 
+0

Tôi không thể nhìn thấy bất cứ nơi nào các hàm của bạn sửa đổi tham số. Sử dụng 'const std :: string &'. – chris

+1

Xem ['boost :: string_ref'] (http://www.boost.org/libs/utility/doc/html/string_ref.html). – ildjarn

Trả lời

6

Bạn không thể sử dụng std::string cho mục đích này, nhưng bạn có thể dễ dàng thực hiện một lớp học riêng của bạn chứa một cặp lặp (bắt đầu và kết thúc) vào chuỗi khác, hoặc một C-style char * và kích cỡ. Với C++ 11 (kể từ khi bạn gắn thẻ nó), bạn thậm chí có thể tạo một cú pháp ngữ nghĩa do người dùng định nghĩa để tạo các chuỗi kiểu mới của bạn.

2

Bạn có thể sử dụng lớp wrapper của riêng bạn như thế này một:

struct RefString 
{ 
    RefString(const std::string & s, int i, int l) : s(s), i(i), l(l) {} 

    const char & operator [] (int x) const { 
     return s[i+x]; 
    } 

    size_t length() const { 
     return l; 
    } 

    bool operator < (const RefString & s2) const { 
     return s.compare(i, l, s2.s, s2.i, s2.l) < 0; 
    } 

private: 
    const std::string & s; 
    int i; 
    int l; 
}; 

std::ostream & operator << (std::ostream &stream, const RefString & ms) { 
    for (int i = 0; i < ms.length(); i++) 
     stream << ms[i]; 
    return stream; 
} 

Và sử dụng nó như thế này, ví dụ để tạo set của chuỗi con độc đáo:

std::string s = "hello"; 
std::set<RefString> st; 
for (int i = 0; i < s.length(); i++) 
for (int j = i; j < s.length(); j++) 
    st.insert(RefString(s, i, j-i+1)); 
+0

Tại sao toán tử chỉ mục trả về tham chiếu const? Và tại sao là thành viên tham chiếu chuỗi const ở tất cả? – renonsz

+0

@renonsz giải pháp được cung cấp cho phép có trường hợp chuỗi con mà không cần sao chép chuỗi. Vì vậy, nó không được phép sửa đổi RefString để giữ cho anh chị em có thể RefStrings không sửa đổi. – k06a

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