Frage

Im folgenden C ++ Code, erkennen ich, dass gcount() eine größere Zahl zurückkehrt, als ich wollte, weil getline() die endgültigen Newline-Zeichen verbraucht sie aber nicht an den Eingangsstrom senden.

Was ich immer noch nicht verstehe, ist die Ausgabe des Programms, though. Für die Eingabe "Test \ n", warum ich "est \ n" erhalten? Wie kommt mein Fehler der wirkt sich zuerst Zeichen des Strings, anstatt das Hinzufügen unerwünschten Müll auf das Ende? Und wie kommt die Ausgabe des Programms ist es im Widerspruch zu der Art und Weise des String im Debugger sieht ( „Test \ n“, wie ich erwarten würde)?

#include <fstream>
#include <vector>
#include <string>
#include <iostream>

using namespace std;

int main()
{
    const int bufferSize = 1024;
    ifstream input( "test.txt", ios::in | ios::binary );

    vector<char> vecBuffer( bufferSize );
    input.getline( &vecBuffer[0], bufferSize );
    string strResult( vecBuffer.begin(), vecBuffer.begin() + input.gcount() );
    cout << strResult << "\n";

    return 0;
}
War es hilfreich?

Lösung

Ich habe dupliziert auch dieses Ergebnis, Windows Vista, Visual Studio 2005 SP2.

Wenn ich herausfinden, was zum Teufel passiert ist, ich werde diesen Beitrag aktualisieren.

Bearbeiten : Okay, da gehen wir. Das Problem (und die verschiedenen Ergebnisse sind die Menschen immer) sind aus dem \ r. Was passiert, ist, dass Sie input.getline rufen und das Ergebnis in vecBuffer setzen. Die Funktion getline abstreift die \ n, lässt aber die \ r statt.

Sie übertragen dann die vecBuffer auf eine String-Variable, aber die gcount Funktion von Eingang verwenden, das heißt, Sie werden ein Zeichen zu viel bekommen, weil die Eingangsgröße den \ n noch enthält, und die vecBuffer nicht.

Das resultierende strResult ist:

-       strResult   "Test"
        [0] 84 'T'  char
        [1] 101 'e' char
        [2] 115 's' char
        [3] 116 't' char
        [4] 13 '␍'  char
        [5] 0   char

So dann „Test“ gedruckt wird, von einem Wagenrücklauf gefolgt (setzt den Cursor wieder am Anfang der Zeile), ein Null-Zeichen (das T überschreibt), und schließlich die \ n, die korrekt die Cursor setzen auf die neue Linie.

So können Sie entweder die \ r Streifen aus, oder eine Funktion schreiben, die die String-Länge direkt von vecBuffer bekommt, für Null-Zeichen zu überprüfen.

Andere Tipps

ich Tommys Problem auf einem Windows XP Pro Service Pack 2-System mit dem SP2 Visual Studio 2005 mit kompilierten Code dupliziert habe (eigentlich heißt es „Version 8.0.50727.879“) als Konsolenprojekt gebaut.

Wenn meine test.txt Datei nur „Test“ enthält und eine CR, spuckt das Programm aus „est“ (man beachte das führende Leerzeichen) bei der Ausführung.

Wenn ich eine wilde Vermutung nehmen hätte, würde ich sagen, dass diese Version der Implementierung hat einen Bug, wo es das Windows-Newline-Zeichen behandelt wie sollte es in Unix behandelt werden (wie ein „nach vorne unterwegs gleiche Zeile“Zeichen), und dann wischt sie das erste Zeichen aus Teil der nächsten Aufforderung oder etwas zu halten.


Update: mit ihm ein wenig nach dem Spielen, ich bin sicher, dass ist, was los ist. Wenn Sie bei strResult im Debugger anschauen, werden Sie sehen, dass es eine Dezimalzahl 13 Wert am Ende kopiert. Das ist CR, die in Windows-Land ist ‚\ n‘, und überall sonst ist „an den Anfang der Zeile zurückgeben“. Wenn ich stattdessen Konstruktor ändern zu lesen:

string strResult (vecBuffer.begin (), vecBuffer.begin () + input.gcount () - 1);

... (so dass der CR nicht kopiert wird), dann druckt es aus "Test" wie man erwarten würde.

Ich bin mir ziemlich sicher, dass die T tatsächlich geschrieben zu werden und dann überschreibt. Das Ausführen des gleichen Programms in einem rxvt Fenster (Cygwin) den erwarteten Ausgang. Sie können ein paar Dinge tun. Wenn Sie den ios loszuwerden :: binary in Ihrem geöffneten wird es \ r \ n \ n AutoConvert zu und die Dinge funktionieren wie erwartet.

Sie können auch Ihre Textdatei im Binär-Editor, indem Sie auf dem kleinen Pfeil nach unten auf dem Datei-Dialog der Taste zum Öffnen öffnen und die Auswahl offen mit ...-> Binär-Editor. Damit können Sie auf die Dateien suchen und bestätigt, dass es in der Tat hat \ r \ n und nicht nur \ n.

Edit: I umgeleitet, die Ausgabe in eine Datei und schreibt aus:

Test\r\0\r\n

Der Grund, Sie werden immer die \ 0 ist, dass gcount zurückgibt 6 (6 Zeichen aus dem Strom entfernt wurden), aber der Endbegrenzer ist nicht auf den Puffer kopiert, ein ‚\ 0‘ ist, statt. wenn Sie die Zeichenfolge bauen, sagen Sie es tatsächlich die ‚\ 0‘ aufzunehmen. std :: string hat kein Problem mit den eingebetteten 0 und gibt es als gefragt. Einige Schalen sind Ausgeben offenbar ein Leerzeichen und die T überschrieben wird, während andere nichts tun und die Ausgabe sieht in Ordnung, aber es ist wahrscheinlich immer noch falsch, weil es die eingebettete ‚\ 0‘ hat

cout << strResult.c_str() << "\n";

Ändern der letzten Zeile wird dies auf der \ 0 zu stoppen und erhalten auch die Ausgabe erwartet.

testete ich den Code von Visual Studio 2005 SP2 unter Windows XP Pro SP3 (32-Bit), und alles funktioniert.

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