3 Stimmen

Warum gibt std::string.find(text,std::string:npos) nicht npos zurück?

Ich mache eine Reihe von Suchvorgängen in einer Zeichenfolge, und irgendwann wird eine der Zeichenfolgen übersehen, und meine Reihe von Suchvorgängen sollte fehlschlagen.

Ich hatte erwartet, dass die Position, sobald sie std::string::npos erreicht hat, dort bleiben würde, aber das ist nicht der Fall. Die Übergabe von std::string::npos an std::string.find scheint die Suche wieder am Anfang zu beginnen

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

Warum wird es nicht als Ende der Zeichenkette verstanden?

Aktualisieren: Die Absicht ist, nach einer Reihe von Zeichenfolgen zu suchen und das Ergebnis am Ende zu überprüfen

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

10voto

CB Bailey Punkte 693084

Wenn ich mir die Spezifikation ansehe, denke ich, dass es einen Fehler in Ihrer Implementierung geben könnte.

basic_string::find sollte die niedrigste Position zurückgeben xpos tal que pos <= xpos y xpos + str.size() <= size() y at(xpos + I) == str.at(I) für alle Elemente I kontrolliert von str .

basic_string::npos ist -1 in einen vorzeichenlosen Typ konvertiert und muss daher die größte Zahl sein, die durch diesen vorzeichenlosen Typ darstellbar ist. Da keine andere Position xpos kann sogar den ersten Teil von npos <= xpos y find muss zurückkehren npos bei Misserfolg, soweit ich das sehen kann npos ist der einzige gültige Rückgabewert für basic_string::find im Vorbeigehen npos als zweiten Parameter.

4voto

MSalters Punkte 166675

Vergleichen Sie string::find() und string::copy() (in N2798 sind das 21.3.7.2 und 21.3.6.7, Seiten 686/687) Beide benötigen ein Positionsargument. Doch nur string::copy hat eine "Requires: pos <= size()"-Klausel. Folglich kann string::find pas require pos <= size().

Von diesem Punkt an hat Charles Bailey die richtige Logik. Schaut man sich den Bereich der gültigen Rückgabewerte an, so wird deutlich, dass der einzige Rückgabewert, der den Anforderungen entspricht, string::npos ist. Jeder andere Rückgabewert ist kleiner als string::npos und führt zum Scheitern von 21.3.7.2/1.


Aus N2798=08-0308, Copyright ISO/IEC:

21.3.7.2 basic_string::find [string::find]

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

1 Effekte: Bestimmt die niedrigste Position xpos wenn möglich so, dass beide der folgenden Bedingungen erfüllt sind: - pos <= xpos y xpos + str.size() <= size(); - traits::eq(at(xpos+I), str.at(I)) für alle Elemente I der Zeichenkette, die von str . 2 Rücksendungen: xpos wenn die Funktion einen solchen Wert ermitteln kann für xpos . Andernfalls wird npos . 3 Bemerkungen: Verwendet traits::eq() .

3voto

James Hopkin Punkte 13389

std::string::npos ist kein gültiges Argument für std::string::find .

Die Definition von find im Standard wird nur erwähnt npos als möglichen Rückgabewert, nicht als Startposition.

3voto

CB Bailey Punkte 693084

Sie werden feststellen, dass die freie Funktion std::search in dieser Situation einfacher zu verwenden ist. z.B.

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() );

1voto

peterchen Punkte 39679

Das Verhalten ist undefiniert, wenn Sie npos :

[Update]
Die STL-Dokumentation (die beiden Reproduktionen, die ich finden konnte) erwähnt string::npos nur als möglicher Rückgabewert, nicht als gültiger Wert für pos . Letzteres ist der Index, in dem die Suche beginnt.

Aber siehe auch die Kommentare unten (ich bin kein Experte für die ISO-Norm, ich beschränke meine Erwartungen auf der Grundlage der mir vorliegenden Unterlagen).

Die STL-Implementierung würde normalerweise einen Wert verwenden, der eindeutig außerhalb des Bereichs liegt (z. B. ( (size_type)-1) . Wie dies als Parameter gehandhabt wird, ist nicht eindeutig festgelegt, daher würde ich mich nicht auf dieses Verhalten verlassen. [/update]

Sie müssen also bei 0 beginnen und nach pos != npos nach jedem Aufruf zu finden:

 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
 }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X