3

文字列で一連の検索を行っていますが、行のどこかで文字列の 1 つが失われ、一連の検索が失敗するはずです。

位置が std::string::npos に達すると、そこにとどまると予想していましたが、そうではありません。std::string::npos を std::string.find に渡すと、最初から検索が再開されるようです

std::string str("frederick");
std::string::size_type pos = str.find("der",std::string::npos);
TS_ASSERT_EQUALS(pos, std::string::npos); // FAIL, 3 is returned

文字列の終わりを示すために使用されないのはなぜですか?

更新:意図は、一連の文字列を順番に検索し、最後に結果を確認することです

pos = str.find(string1, pos)
pos = str.find(string2, pos)
pos = str.find(string3, pos)
if (pos != std:string::npos)
{ // All strings found
4

7 に答える 7

10

スペックを見ると、実装にバグがあるのではないかと思います。

basic_string::findによって制御されるすべての要素に対して、およびxposなどの最低位置を返す必要があります。pos <= xposxpos + str.size() <= size()at(xpos + I) == str.at(I)Istr

basic_string::npos-1は符号なし型に変換されるため、その符号なし型で表現できる最大数である必要があります。<=のxpos最初の部分でさえ満たすことができず、失敗時に戻らなければならない他の位置がないことを考えると、私が見る限り、2番目のパラメーターとして渡されたときの唯一の有効な戻り値です。nposxposfindnposnposbasic_string::findnpos

于 2009-06-18T10:05:43.113 に答える
4

string::find() と string::copy() を比較してください。(N2798 では、21.3.7.2 および 21.3.6.7、686/687 ページ) 両方とも位置引数を取ります。まだ string::copy だけが「Requires: pos <= size()」句を持っています。したがって、string::find はpos <= size() を必要としません。

その時点から、チャールズ・ベイリーは正しい論理を持っています。有効な戻り値の範囲を見ると、要求に一致する唯一の戻り値が string::npos であることが明らかになります。返されるその他の値は string::npos より小さく、21.3.7.2/1 で失敗します。


N2798=08-0308 より、著作権 ISO/IEC:

21.3.7.2basic_string::find [string::find]

size_type find(const basic_string<charT,traits,Allocator>& str, size_type pos = 0) const;

xpos1 効果:可能であれば、次の条件の両方が得られるように、最下位の位置を決定します。 —pos <= xposおよびxpos + str.size() <= size(); —によって制御される文字列のtraits::eq(at(xpos+I), str.at(I))すべての要素。2 戻り値:関数が のそのような値を決定できる場合。それ以外の場合は、 を返します。3 備考: を使用します。Istrxposxposnpostraits::eq()

于 2009-06-18T10:54:30.597 に答える
3

この状況では、無料の関数 std::search を使用する方が簡単であることに気付くかもしれません。例えば

std::string::const_iterator iter = str.begin();

iter = std::search( iter, str.end(), string1.begin(), string1.end() );
iter = std::search( iter, str.end(), string2.begin(), string2.end() );
iter = std::search( iter, str.end(), string3.begin(), string3.end() );
于 2009-06-18T10:53:25.640 に答える
3

std::string::nposは の有効な引数ではありませんstd::string::find

標準での の定義は、開始位置ではなく、可能な戻り値としてfindのみ言及しています。npos

于 2009-06-18T09:56:07.063 に答える
1

次のパスを渡すと、動作は未定義になりますnpos

[更新]
STLドキュメント(とにかく私が見つけることができる2つの複製)はstring::npos、の有効な値としてではなく、可能な戻り値としてのみ言及していますpos。後者は検索を開始するインデックスです。

ただし、以下のコメントも参照してください(私は、ISO標準の専門家ではありません。私が持っているドキュメントに基づいて、期待を制限しています)。

STL実装は通常、明らかに範囲外の値を使用します((など(size_type)-1)。これがパラメーターとしてどのように処理されるかは明確に述べられていないため、その動作には依存しません。 [/ update]

したがって、0から開始し、pos != npos呼び出しのたびに次のことを確認する必要があります。

 pos = str.find(string1, 0)
 if (pos != std:string::npos)
   pos = str.find(string2, pos)
 if (pos != std:string::npos)
   pos = str.find(string3, pos)

 if (pos != std:string::npos)
 { 
   // All strings found
 }
于 2009-06-18T10:05:17.407 に答える
0

find の 2 番目の引数として std::string::npos を渡すことは、「文字列内の std::string::npos 位置以降で検索を開始する」ことを意味します。

明らかに、これは意図したものではありません。

編集:

これは、最初に意図したことを行う可能性があります。

string s;
string::size_type pos;

if ((pos = s.find(s1)) != string::npos && (pos = s.find(s2, pos)) != npos && 
    (pos = s.find(s3,pos)) != string::npos)
{
    // okay
}

私はそれをテストしていませんが、うまくいくはずです。

于 2009-06-18T09:54:00.737 に答える
0

文字列の長さを開始位置として使用する必要があります。

于 2009-06-18T09:54:40.517 に答える