Frage

Ich verbrachte etwa 4 Stunden gestern versucht, dieses Problem in meinem Code zu beheben. Ich vereinfacht das Problem auf das Beispiel unten.

Die Idee ist, eine Zeichenkette in einem string mit std :: Enden enden zu speichern, ist es dann später abrufen und auf die ursprüngliche Zeichenfolge vergleichen.

#include <sstream>
#include <iostream>
#include <string>

int main( int argc, char** argv )
{
    const std::string HELLO( "hello" );

    std::stringstream testStream;

    testStream << HELLO << std::ends;

    std::string hi = testStream.str();

    if( HELLO == hi )
    {
        std::cout << HELLO << "==" << hi << std::endl;
    }

    return 0;
}

Wie Sie wahrscheinlich erraten kann, der obige Code, wenn sie ausgeführt wird alles nicht ausdrucken.

Obwohl, wenn ausgedruckt, oder sah im Debugger (VS2005), hallo und hallo identisch aussehen, ihre .length () in der Tat unterscheidet sich von 1. Das ist, was ich vermute, verursacht die „==“ Operator Scheitern.

Meine Frage ist, warum. Ich verstehe nicht, warum std :: Ende ein unsichtbares Zeichen hallo zu String hinzugefügt, so dass hallo und HALLO unterschiedliche Längen, obwohl sie identische Inhalte haben. Darüber hinaus ist diese unsichtbaren Zeichen, das nicht mit Boost-trim getrimmt bekommen. Wenn Sie jedoch strcmp verwenden .c_str () der beiden Strings zu vergleichen, der Vergleich korrekt funktioniert.

Der Grund, warum ich std :: verwendet endet in erster Linie, weil ich Probleme in der Vergangenheit mit stringHalte Müll Daten am Ende des Stromes hatte. std :: Ende gelöst, dass für mich.

War es hilfreich?

Lösung

std::ends fügt ein Null-Zeichen in den Strom. Abrufen der Inhalte als std::string wird, dass die Null-Zeichen erhalten und eine Zeichenfolge mit dem Null-Zeichen an den jeweiligen Positionen erstellen.

So in der Tat ein std :: string kann eingebettete Nullzeichen enthalten. Die folgenden std :: string Inhalt sind anders:

ABC
ABC\0

Eine binäre Null ist keine Leerzeichen. Aber es ist auch nicht bedruckbar, so dass Sie es nicht sehen (es sei denn, Ihr Terminal zeigt es speziell).

Im Vergleich strcmp verwendet, wird der Inhalt eines std::string als C-String interpretieren, wenn Sie .c_str() passieren. Es wird sagen:

  

Hmm, Zeichen vor dem ersten \0 (abschließende Nullzeichen) sind ABC , so dass ich nehme es die Zeichenfolge ABC

Und so wird es keinen Unterschied zwischen den beiden oben sehen. Sie dieses Problem wahrscheinlich mit:

std::stringstream s;
s << "hello";
s.seekp(0);
s << "b";
assert(s.str() == "b"); // will fail!

Die Assertion wird fehlschlagen, da die Sequenz, die das string verwendet immer noch die alten ist, das „Hallo“ enthält. Was du getan hast ist das Überschreiben nur das erste Zeichen. Sie wollen, dies zu tun:

std::stringstream s;
s << "hello";
s.str(""); // reset the sequence
s << "b";
assert(s.str() == "b"); // will succeed!

Auch diese Antwort lauten: Wie ein ostringstream wiederzuverwenden

Andere Tipps

std::ends ist einfach ein Null-Zeichen. Traditionell mit einem Null (ascii 0) Zeichen abgeschlossen werden, Streicher in C und C ++, jedoch stellt sich heraus, dass std::string nicht wirklich diese Sache erfordert. Wie auch immer Ihr Codepunkt Schritt durch Punkt wir ein paar interessante Dinge zu sehen los:

int main( int argc, char** argv )
{

Die Stringliteral "hello" ist ein traditionelles Null-terminierten String konstant. Wir kopieren das ganze in die std::string HALLO.

    const std::string HELLO( "hello" );

    std::stringstream testStream;

Wir setzen nun die string HALLO (einschließlich dem Hinter 0) in die stream, durch eine zweite Null gefolgt, die durch den Anruf dort gesetzt wird std::ends.

    testStream << HELLO << std::ends;

Wir extrahieren Sie eine Kopie von dem Zeug heraus, dass wir in die stream setzen (die Zeichenkette „Hallo“, und die beiden Nullabschluss).

    std::string hi = testStream.str();

Wir vergleichen dann die beiden Strings die operator == auf der std::string Klasse. Dieser Operator (wahrscheinlich) vergleicht die Länge der string Objekte - darunter wie immer viele Nullzeichen zurück. Beachten Sie, dass die std::string Klasse nicht die zugrunde liegende Zeichenarray erfordert mit einem abschließenden Null zu beenden - um es anders auszudrücken es die Zeichenfolge ermöglicht Null-Zeichen zu enthalten, so dass die ersten der beiden hinteren Nullzeichen als Teil der Zeichenfolge hi behandelt wird.

Da die beiden Saiten unterschiedlich in der Anzahl der hinteren Nullen sind, der Vergleich fehlschlägt.

    if( HELLO == hi )
    {
        std::cout << HELLO << "==" << hi << std::endl;
    }

    return 0;
}
  

Obwohl, wenn ausgedruckt oder betrachtete   im Debugger (VS2005), hallo und hallo   identisch aussehen, ihre .length () in   Tatsache unterscheidet sich von 1. Das ist, was ich bin   Erraten verursacht die „==“ Operator   zum Scheitern verurteilt.

Grund dafür ist, ist die Länge unterschiedlich von einem Null-Zeichen nachlauf.

  

Meine Frage ist, warum. ich nicht   verstehen, warum std :: Enden ist ein   unsichtbare Zeichen hinzugefügt, um Zeichenfolge   hallo, so dass hallo und HALLO verschiedene   Längen obwohl sie   identischer Inhalt. Darüber hinaus ist diese   unsichtbare Zeichen erhalten nicht   mit Boost-trim getrimmt. jedoch, wenn   Sie verwenden strcmp vergleichen .c_str () von   die beiden Strings, die Vergleichsarbeiten   richtig.

strcmp unterscheidet sich von std::string - es steht geschrieben in den frühen Tagen von hinten, wenn Strings mit null beendet wurden -. So, wenn es mit dem ersten hinteren null in hi wird es aufhört zu suchen

  

Der Grund, warum ich std :: verwendet endet in der   Erstens, weil ich Probleme hatte   in der Vergangenheit mit string   Haltemülldaten am Ende der   der Strom. std :: Ende gelöst, dass für   ich.

Manchmal ist es eine gute Idee, die zugrunde liegende Darstellung zu verstehen.

Du fügst ein NULL-Zeichen zu HALLO mit std :: Enden. Wenn Sie mit str hallo initialisieren () Sie entfernen die NULL-Zeichen. Die Saiten sind unterschiedlich. strcmp nicht std :: strings vergleichen, vergleicht es char * (es ist eine C-Funktion).

std :: Ende fügen einen Nullabschluss, (char) '\ 0'. Sie würden es mit den veralteten Strstream Klassen verwenden, den Nullabschluss hinzuzufügen.

Sie brauchen es nicht mit string, und in der Tat ist es Schrauben Dinge, weil der Nullabschluss nicht „der besondere Nullabschluss, die einen String endet“ ist zu string, zu string es ist nur ein Zeichen, das nullt Charakter . string nur fügt es, und das erhöht die Anzahl der Zeichen (in diesem Fall) zu sieben, und macht den Vergleich zu „Hallo“ fehlschlagen.

Ich denke, eine gute Möglichkeit zu haben, Zeichenfolge zu vergleichen ist std::find Methode zu verwenden. Mischen Sie keine C-Methoden und std::string ones!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top