2014-02-09 6 views
5

Ich arbeite durch ein Buch über C++ und es behandelt nur string::npos, um zu überprüfen, ob eine Zeichenposition in einer Zeichenfolge vorhanden ist. Ich verstehe nicht, wie dieser Mechanismus möglicherweise wissen könnte, auf welche Saite ich mich beziehe! Dieser spezifische Code zählt die Anzahl der Vorkommen einer Teilzeichenfolge.Woher weiß string :: npos, auf welchen String ich mich beziehe?

Code:

for (int i=cats.find("cat",0);i!=string::npos;i=cats.find("cat",i)) { 
    ++catCount; 
    ++i; 
} 

Ich verstehe, dass es um die Schleife beim ersten Auftreten des Wortes beginnt, Inkrementieren des Zählers jedes zweimal durch die gleiche Teilkette zu vermeiden passieren Zählen, und dann am Ende von jeder Schleife springt der Zähler zu der Position des nächsten Auftretens der Teilkette. Die Schleife wird beendet, wenn der Zähler nicht als Zeichenindex für die Zeichenfolge existiert.

Die Zeichenfolge heißt cats though, und "cats" ist nirgendwo in "string :: npos" zu finden, also wie weiß ich, dass das die Variable ist, nach der ich suche? Ist es einfach, weil das die letzte Variable war, die .find() aufgerufen wurde?

Danke!

+1

Es ist nur eine Konstante, die 'find' zurückgibt, wenn es nicht finden kann, wonach es sucht. – chris

+1

'find()' gibt den Wert 'npos' zurück, der als statischer Datenmember von' std :: string' gespeichert wird, wenn er die Zeichenkette nicht finden kann. – 0x499602D2

+1

Und ich nehme an, "static data member" bedeutet hier dasselbe wie in anderen OO-Sprachen, das heißt, dass derselbe Wert zurückgegeben wird, wenn von irgendwo im Programm darauf zugegriffen wird und keine Instanz des Objekts sein muss vorhanden für den Wert, auf den zugegriffen und manipuliert werden soll? –

Antwort

8

Wenn find nicht finden kann, was Sie suchen, wird ein Sentinel-Wert std::string::npos zurückgegeben. Es besteht keine Notwendigkeit, etwas über die Saite selbst zu wissen. Sie müssen nur einen Wert zurückgeben, der kein gültiger Index sein kann.

Zum Beispiel könnte es so umgesetzt werden:

static const size_t npos = std::numeric_limits<size_t>::max(); 

size_t string::find(...) 
{ 
    // if we didn't find it... 
    return npos; 
} 

Auch sollten Sie keine int werden mit dem Rückgabewert zu speichern, wie es nicht ist, was find zurückkehrt. Was ist, wenn Sie eine sehr lange Zeichenfolge haben und der zurückgegebene Index>numeric_limits<int>.max() ist? Nun, Sie haben ein undefiniertes Verhalten aufgerufen.

+0

Also muss ich nach string :: npos suchen, bevor ich find() auf einer anderen Zeichenkette aufruft, da dies eine statische Eigenschaft ist, richtig? –

+1

@JS Um festzustellen, ob 'find()' einen gültigen Index zurückgegeben hat, sollten Sie den Rückgabewert überprüfen, um zu sehen, ob er den Wert 'std :: string :: pos' nicht zurückgegeben hat. Es gibt keine zwingende Aktion, die aufgrund der 'statischen' Natur von' npos' ausgeführt werden muss. 'find()' gibt einfach einen speziellen Wert zurück, wenn die Zeichenfolge nicht gefunden werden kann, und um zu wissen, ob ein gültiger Index zurückgegeben wurde, müssen Sie überprüfen, ob der Rückgabewert * nicht * der spezielle Wert ist. – 0x499602D2

+1

@JS: Nein. Wie @ 0x499602D2 sagte, handelt es sich einfach um einen Sentinel-Wert, d. H. Um einen Wert von find, mit dem Sie feststellen können, ob die gesuchte Zeichenfolge gefunden wurde. Die Tatsache, dass es statisch ist, ist irrelevant. Wenn 'find' nicht finden kann, was Sie suchen, gibt es' npos' zurück, so dass Sie jetzt wissen, dass dies nicht der Fall ist. Wenn es etwas anderes als 'npos' zurückgibt, wissen Sie, dass es sich um einen gültigen Index für Ihre Zeichenfolge handelt. –

5

find gibt std::string::size_type zurück. std::string::npos ist eine Konstante dieses Typs, die zurückgegeben wird, wenn der Wert nicht gefunden werden kann.

Beachten Sie, dass std::string::size_type ein unsigned Wert ist, und int signiert ist. Wenn std::string::npos nicht als int dargestellt werden kann, ist die Konvertierung von std::string::npos zu int undefiniertes Verhalten.

So sollten Sie wirklich nicht den Rückgabewert von std::string::find in einem int speichern. Stattdessen sollten Sie es in einer oder in C++ 11 Verwendung auto speichern. baisc_string<char>size_type ist std::size_t, wie die meisten anderen Spezialisierungen.

+0

@ douglaso.moen 'basic_string' hat einen nicht spezifizierten' size_type': Sie sagen 'std :: basic_string ' hat einen 'size_type', spezifiziert durch den Standard? – Yakk

+0

@ Douglaso.moen Ich habe eine Reihe von Gründen, Ihnen zu widersprechen. Erstens, [Live-Code] (http://ideone.com/ON7MWS). Zweitens, der aktuelle Entwurf Standard 21.4/5 Klassenvorlage basic_string [basic.string] erwähnt explizit einen 'size_type' und' std :: string' ** ist ** 'std :: basic_string '. Es gibt so etwas wie 'std :: string :: size_type' und es ist' std :: size_t'. Wenn ich mich irre, können Sie bitte ein Zitat geben? – Yakk

3

Er weiß nicht, was Zeichenfolge, die Sie sich beziehen, npos ist nur ein statisches const Element, das den Maximalwert darstellbaren und stellt in diesem Fall und eror darstellt, wenn wir auf das, was cppreference aussehen sagt über std::basic_string::npos:

static const size_type npos = -1; 

Dies ist ein spezieller Wert, der dem maximalen Wert entspricht, der durch den Typ size_type dargestellt werden kann.Die genaue Bedeutung hängt vom Kontext ab, wird aber normalerweise entweder als Ende des String-Indikators von den Funktionen verwendet, die einen String-Index erwarten, oder als Fehlerindikator für die Funktionen, die einen String-Index zurückgeben.

, die die Definition passt für npos im draft C++ standard in Abschnitt 21.4Vorlage Klasse basic_string Absatz :

static const size_type npos = -1; 

, die ein bisschen ungerade ist seit seit size_typeunsigned ist aber ist aufgrund der integralen Umrechnungsregeln in Abschnitt 4.7Integral Umrechnungen die sagt:.

Wenn der Zieltyp nicht signiert ist, der sich ergebende Wert der am wenigsten unsigned integer kongruent mit der Source-Ganzzahl ist (modulo 2 n, wobei n die Anzahl von Bits verwendet, um den Typ ohne Vorzeichen darzustellen) [. ..]

garantiert, dass -1 in den größten vorzeichenlosen Wert konvertiert wird. Es kann einfacher sein, den Wortlaut aus dem Entwurf der C99-Standard zu sehen, mit dem es heißt:

Andernfalls, wenn der neue Typ unsigned ist, wird der Wert durch wiederholte umgewandelte Hinzufügen oder einer mehr als der Maximalwert subtrahieren das kann im neuen Typ dargestellt werden, bis der Wert im Bereich des neuen Typs liegt.

was gibt uns MAX + 1 -1 die MAX ist.

Verwandte Themen