2013-03-19 108 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