Ich habe gerade getan, was scheint, ein gemeinsamer Neuling zu sein Fehler :
Zuerst lesen wir eines von vielen Tutorials , das so aussieht:
%Vor%Zweitens versuchen wir, etwas Ähnliches in unserem Code zu verwenden, das ungefähr so lautet:
%Vor%Drittens ist der Neuling-Entwickler durch irgendeine kryptische Compiler-Fehlermeldung perplex.
Das Problem ist, dass ifstream const * char
als Konstruktor-Argument verwendet.
Die Lösung lautet convert std :: string in const * char .
Nun, das wirkliche Problem ist, dass für einen Neuling "file.txt" oder ähnliche Beispiele in fast allen Tutorials sehr ähnlich aussehen wie ein std :: string.
Also, ist "mein Text" eine std :: string, eine c-string oder ein * char, oder hängt das vom Kontext ab?
Können Sie Beispiele geben, wie "mein Text" je nach Kontext unterschiedlich interpretiert würde?
[Edit: Ich dachte, das obige Beispiel hätte es offensichtlich gemacht, aber ich hätte trotzdem deutlicher werden sollen: Was ich meine, ist der Typ einer beliebigen Zeichenkette in Anführungszeichen, zB "meinDateiname.txt", nicht die Bedeutung des Wortes 'string'.]
Danke.
Also, ist "string" eine std :: string, eine c-string oder ein * char, oder hängt das vom Kontext ab?
const char *
(oder const char []
, um genau zu sein). "C-String" bezieht sich normalerweise auf dieses Zeichen, insbesondere ein Zeichen-Array mit einem Null-Terminator. std::string
eine Convenience-Klasse, die eine rohe Zeichenfolge in ein Objekt umschließt. Dadurch können Sie vermeiden, dass Sie (unsaubere) Zeigerarithmetik und Speicherumverteilungen selbst durchführen müssen. char *
(oder const char *
). char *
implizit in std::string
umwandeln, weil letztere einen Konstruktor dafür hat. std::string
explizit in ein const char *
konvertieren, indem Sie die Methode c_str()
verwenden. Danke an Clark Gaebel für den Hinweis auf const
ness und auf jalf und GMan für die Erwähnung, dass es tatsächlich ein Array ist.
"myString"
ist ein String-Literal und hat den Typ const char[9]
, ein Array von 9 Konstanten char
. Beachten Sie, dass es genug Platz für den Nullabschluss hat. Also "Hi"
ist ein const char[3]
und so weiter.
Das ist so ziemlich immer richtig, ohne Zweideutigkeit. Bei Bedarf wird jedoch ein const char[9]
in ein const char*
zerfallen, das auf sein erstes Element zeigt. Und std::string
hat einen impliziten Konstruktor, der ein const char*
akzeptiert. So, während es immer als ein Array von Char beginnt, kann es die anderen Typen werden, wenn Sie es benötigen.
Beachten Sie, dass String-Literale die einzigartige Eigenschaft haben, dass const char[N]
auch in char*
zerfallen kann, aber dieses Verhalten ist veraltet. Wenn Sie versuchen, die zugrunde liegende Zeichenfolge auf diese Weise zu ändern, haben Sie ein nicht definiertes Verhalten. Es ist einfach keine gute Idee.
Die rechte Seite von =
enthält ein (rohes) Zeichenfolgenliteral (i.a. eine nullterminierte Bytekette). Sein effektiver Typ ist array of const char
.
Das =
ist hier ein schwieriges Pony: Es findet keine Zuweisung statt. Die std::string
-Klasse hat einen Konstruktor, der einen Zeiger auf char als Argument verwendet, und dieser wird aufgerufen, um ein temporäres std::string
zu erzeugen, und dies wird benutzt, um das Objekt% co_de zu kopieren (mit dem copy ctor von std::string
) % des Typs file
.
Dem Compiler ist es freigestellt, den copy ctor zu entfernen und die Datei direkt zu instanziieren.
Beachten Sie jedoch, dass std::string
nicht dasselbe ist wie eine nullterminierte Zeichenfolge im C-Stil. Es ist nicht einmal erforderlich, Null-terminiert zu sein.
Die std:string
-Klasse hat einen ctor, der ein std::ifstream
akzeptiert und das String-Literal, das an es übergeben wird, verfällt zu einem Zeiger auf das erste Element der Zeichenkette.
Beachten Sie Folgendes: const char *
bietet (fast nahtlose) Konvertierung von C-Style-Strings. Sie müssen die Signatur der Funktion nachsehen, um zu sehen, ob Sie eine std::string
oder eine const char *
übergeben (letzteres wegen impliziter Konvertierungen).
Also, ist "string" ein
std::string
, ein c-String oder einchar*
, oder hängt das vom Kontext ab?
Das hängt ganz vom Kontext ab. :-) Willkommen in C ++.
Eine C-Zeichenfolge ist eine Null-terminierte Zeichenfolge, die fast immer mit der char*
identisch ist.
Abhängig von den Plattformen und Frameworks, die Sie verwenden, könnte das Wort "string" noch mehr Bedeutung haben (z. B. wird es auch für QString
in Qt oder CString
in MFC verwendet).
Die C ++ - Standardbibliothek bietet eine std :: string-Klasse zum Verwalten und Darstellen von Zeichenfolgen. Es kapselt die Speicherverwaltung und wird meistens als C-String implementiert; aber das ist ein Implementierungsdetail. Es bietet auch Manipulationsroutinen für allgemeine Aufgaben.
Der std :: string-Typ wird immer so sein (er hat zum Beispiel keinen Konvertierungsoperator für char *, deshalb haben Sie die c_str () -Methode), aber er kann initialisiert oder durch ein C zugewiesen werden -Zeichen (char *).
Auf der anderen Seite, wenn Sie eine Funktion haben, die eine std :: string oder eine const std :: string & amp; Als Parameter können Sie eine C-Zeichenfolge (char *) an diese Funktion übergeben, und der Compiler erstellt für Sie eine std :: -Zeichenfolge. Das wäre eine unterschiedliche Interpretation je nach Kontext, wie Sie es nennen.
Weder C noch C ++ haben einen integrierten String-Datentyp.
Wenn der Compiler während der Kompilierung feststellt, dass double-quoted -Strings implizit referenziert sind (siehe Code unten), wird der String selbst im Programmcode / text gespeichert und erzeugt even Zeichen-Array:
Also, was Sie haben, ist const char * für dieses konstante statische Zeichen-Array.
%Vor%Während der Programmausführung, wenn das Steuerelement eine öffnende Klammer findet, erzeugt es "text", den char * -Zeiger, im Stapel und ein konstantes Array von 6 Elementen (einschließlich des Null-Terminators '\ 0' am Ende) in static Speicherbereich. Wenn die Steuerung die nächste Zeile findet (char * text="Hello";), wird die Startadresse des 6-Elemente-Arrays "text" zugewiesen. In der nächsten Zeile (return text;) gibt es "text" zurück. Mit der schließenden Klammer verschwindet "text" vom Stapel, aber das Array befindet sich immer noch im statischen Speicherbereich.
Sie müssen keinen Rückgabetyp const machen. Wenn Sie jedoch versuchen, den Wert im statischen Array mit einem nicht konstanten char * zu ändern, erhalten Sie während der Laufzeit immer noch einen Fehler, da das Array konstant ist. Also ist es immer gut, die Rückkehr konstant zu machen, um sicherzustellen, dass es nicht durch nicht konstante Zeiger verwiesen werden kann.
Wenn der Compiler jedoch doppelt zitierte Strings findet, die explizit als Array bezeichnet werden, nimmt der Compiler an, dass der Programmierer (intelligent) damit umgehen wird. Siehe das folgende falsche Beispiel:
%Vor%Während der Kompilierung prüft der Compiler den Text in Anführungszeichen und speichert ihn so, wie er im Code enthalten ist, um das generierte Array während der Laufzeit zu füllen. Außerdem berechnet er die Array-Größe, in diesem Fall wiederum als 6.
Während des Programmablaufs wird mit der offenen Klammer das Array "text []" mit 6 Elementen im Stack erstellt. Aber keine Initialisierung. Wenn der Code gefunden wird (char text []="Hello";), wird das Array initialisiert (mit dem Text im kompilierten Code). Also Array ist jetzt auf dem Stapel. Wenn der Compiler (return text;) findet, gibt er die Startadresse des Arrays "text" zurück. Wenn der Compiler die schließende Klammer findet, verschwindet das Array vom Stapel. Also keine Möglichkeit, es durch den Rückkehrzeiger zu beziehen.
Die meisten Standard-Bibliotheksfunktionen verwenden immer noch nur char * (oder const char *) Parameter.
Die Standard-C ++ - Bibliothek hat eine mächtige Klasse namens string zum Manipulieren von Text. Die interne Datenstruktur für Zeichenfolge ist Zeichenfelder. Die Standard-C ++ - String-Klasse wurde entwickelt, um alle Low-Level-Manipulationen von Zeichen-Arrays, die zuvor vom C-Programmierer benötigt wurden, zu erledigen (und zu verbergen). Beachten Sie, dass std :: string eine Klasse ist:
So oft wie möglich sollte es std::string
bedeuten (oder eine Alternative wie wxString
, QString
usw., wenn Sie ein Framework verwenden, das solche liefert. Manchmal haben Sie keine andere Wahl als zu verwenden eine NULL-terminierte Bytefolge, die Sie aber im Allgemeinen möglichst vermeiden möchten.
Letztendlich gibt es einfach keine klare, eindeutige Terminologie. So ist das Leben.
Um den richtigen Wortlaut zu verwenden (wie im C ++ - Standard), ist string eine der Varianten von std :: basic_string (einschließlich std :: string) aus Kapitel 21.3 "String-Klassen" ( wie in C ++ 0x N3092), während das Argument von ifstreams Konstruktor ist NTBS (Null-terminierte Byte-Sequenz)
Um zu zitieren, C ++ 0x N3092 27.9.1.4/2.
basic_filebuf * open (const char * s, ios_base :: openmode mode);
...
öffnet nach Möglichkeit eine Datei, deren Name die NTBS s ist