1

我的 string::find 实现有点问题。

输入是一个长字符串,由这个可能的示例组成:input = "one_thousand_and_fifty_one"。

我的问题似乎是,在一个包含多个“和”的输入字符串中,只有第一个和被删除,其他的不是。

到目前为止,这是我的代码,它找到“and”,但只删除“a”之前的字母不是“s”(表示“千”)。

string toKill = "and";

size_t andF = input.find(toKill);
    if (andF != string::npos) {
        if (input[(andF - 1)] != 's') {
            input.erase(andF, 4);
        }
    }

编辑:我忘了提到,输入中唯一包含“和”的另一个词是“千”,所以这是一个特例。

4

3 回答 3

3

试试这个:

string toKill = "and";
size_t andF = 0;

while ((andF = input.find(toKill, andF)) != string::npos) {
    if (andF == 0 || input[andF - 1] != 's') {
        input.erase(andF, 4);
    }
    else ++andF;
}
于 2012-06-09T03:27:46.497 回答
2

我会为此使用正则表达式(来自 boost、PCRE 或 C++11 标准)——但如果我必须自己做,我的代码看起来像这样:

string toKill = "and";
size_t pos = 0;
while( ( pos = s.find(toKill, pos) )!=std::string::n_pos )
{
  //Check it doesn't start with an additional letter
  if( pos!=0 && is_alpha(s[pos-1]) ) { pos++; continue; }
  //Check it doesn't end with an additional letter
  if( pos+toKill.size()!=s.size() && is_alpha(s[pos+toKill.size()]) { pos++; continue;}
  //Remove it and the trailing whitespace (or punctuation)
  s.erase(pos,toKill.size()+1);
}
于 2012-06-09T03:26:31.437 回答
2

您的代码中需要(至少)另外两件事。第一个是为字符串处理整个字符串的循环,and第二个是跳过已经检查过的字符串的能力。

您可能还想处理字符串可能以 开头的可能性and,尽管这不太可能:对您期望的内容保持自由,对您交付的内容保持具体。

以下代码将是一个很好的起点:

#include <iostream>
#include <string>

int main (void) {
    std::string inputStr = "one thousand and fifty one";
    std::string killStr = "and ";

    size_t startPos = 0;
    size_t andPos;
    while ((andPos = inputStr.find (killStr, startPos)) != std::string::npos) {
        if ((andPos == 0) || (inputStr[(andPos - 1)] != 's')) {
            inputStr.erase(andPos, killStr.length());
            startPos = andPos;
        } else {
            startPos = andPos + 1;
        }
    }

    std::cout << inputStr << '\n';
    return 0;
}

而且,由于我and对在字符串的开头有偏执,迈克尔正确地叫我不要在字符串的末尾处理它(a),你可以修改它这样做:

#include <iostream>
#include <string>
#include <cstring>

static bool endsWith (std::string s1, std::string s2) {
    size_t s1Len = s1.length();
    size_t s2Len = s2.length();
    if (s2Len > s1Len)
        return false;
    return (strcmp (s1.c_str() + s1Len - s2Len, s2.c_str()) == 0);
}

int main (void) {
    std::string inputStr = "and one thousand and fifty one thousand and";
    std::string killStr = "and ";

    size_t startPos = 0;
    size_t andPos;
    while ((andPos = inputStr.find (killStr, startPos)) != std::string::npos) {
        if ((andPos == 0) || (inputStr[(andPos - 1)] != 's')) {
            inputStr.erase (andPos, killStr.length());
            startPos = andPos;
        } else {
            startPos = andPos + 1;
        }
    }
    if (!endsWith (inputStr, "sand") && endsWith (inputStr, "and"))
        inputStr.erase (inputStr.length() - 3);

    std::cout << inputStr << '\n';
    return 0;
}

(a)如果我要成为一个书呆子,我最好把它做好:-)

于 2012-06-09T03:27:45.227 回答