1

string::find の実装に少し問題があります。

入力は、次の可能な例で構成される長い文字列です: input = "one_thousand_and_fifty_one"。

私の問題は、複数の「and」を含む入力文字列では、最初の and のみが削除され、他のものは削除されないことです。

これはこれまでの私のコードで、「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);
        }
    }

編集:「and」を含む入力内の他の単語は「千」だけであることを忘れていたので、これは特殊なケースです。

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

コードには (少なくとも) 他に 2 つのものが必要です。1 つ目は文字列の文字列全体を処理するループandで、2 つ目は既にチェック済みのものをスキップする機能です。

また、文字列がで始まる可能性に対処したい場合もありますが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文字列の先頭にあることに偏執的であり、Michael は文字列の末尾(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 に答える