2013-03-19 65 views
6

我遞歸調用一個函數作爲參數傳遞一個子字符串,該字符串始終從當前字符串的開始位置開始。如果我使用C,我可以將指針傳遞給字符串的第一個位置,然後將必要的長度傳遞給該字符串的第一個位置。不過,我想用類string來達到相同的結果。可能嗎?如果我使用const,編譯器是否足夠聰明,可以自行進行優化?更妙的是,有沒有一種方法可以自行檢查編譯器是否實際上創建了參數副本或傳遞了引用?如何通過引用傳遞子字符串?

我的問題是在寫了下面的代碼,通過poj上的問題Alphacode上的測試之後,一旦有人使用atoi而不是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

我看不到任何地方你的函數修改參數。使用'const std :: string&'。 – chris 2013-03-19 02:00:58

+1

請參閱['boost :: string_ref'](http://www.boost.org/libs/utility/doc/html/string_ref.html)。 – ildjarn 2013-03-20 19:05:21

回答

6

不能使用std::string用於此目的,但你可以很容易地使一類自己的保存一對迭代器(開始和結束)到另一個字符串或C風格的char *和大小。使用C++ 11(因爲您標記了它),您甚至應該能夠創建用戶定義文字語法來創建新類型的字符串。

2

您可以使用自己的包裝類,像這樣的:

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; 
} 

而且像這樣使用,例如用於創造獨特的子字符串set

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

爲什麼索引操作符返回一個const引用?爲什麼字符串引用成員是const? – renonsz 2017-09-20 08:57:32

+0

@renonsz提供的解決方案允許在沒有任何字符串複製的情況下擁有子字符串實例。所以不允許修改RefString來保持可能的兄弟RefStrings不被修改。 – k06a 2017-09-20 12:14:42