2010-10-07 6 views
5

std::istream den Prototyp hat istream& read (char* s, streamsize n) die tatsächliche Anzahl der gelesenen Bytes durch den Aufruf istream::gcount(), auch die Gültigkeit der istream von ios::good bekannt sein. Kann erhalten werden solldas Design von std :: istream Verstehen :: read

Ich diskutierte die Implementierung einer anderen Stream-Klasse, die ich versuchte, mit einem Kollegen von mir zu schreiben, wo ich sagte, dass ich diesem Design folgen könnte; aber er sagte, anstatt den Benutzer gcount jedes Mal zu haben, könnte man Prototyp wie dieses istream& read (char* s, streamsize n, size_t &bytes_read) gelesen haben, so dass es in einem einzigen Anruf überkommen wird und das ehemalige ist unbeholfener. Ich war nicht in der Lage, std 's Design Wahl zu verteidigen. Was ist die wahre Begründung hinter istream::read?

+0

Meinst du 'size_t & bytes_written'? Und es sollte wahrscheinlich 'streamsize & bytes_written' (oder vielleicht' chars_read') sein. –

+0

@James: Ja, danke! Bytes und Zeichen sind auch _here_, da 'sizeof' das gleiche ist. – legends2k

Antwort

4

Ich nehme an, es ist, weil C++ normalerweise eine Schnittstelle erzwingt, die nicht von jedem benötigt wird. Wenn Sie read benötigen, um einen Parameter zu akzeptieren, der einige Leute nicht interessiert, dann verursacht es zusätzliche Programmierarbeit (deklariert ein extra int als Parameter übergeben). Es speichert auch immer die gelesenen Bytes, unabhängig davon, ob sich der Client interessiert oder nicht (einige Clients kümmern sich vielleicht nur darum, dass das Lesen fehlgeschlagen ist, wie durch die eof/fail-Bits angezeigt).

Mit einer separaten Methode trennen Sie die Schnittstelle für verschiedene Informationen, die möglicherweise benötigt werden oder nicht.

0

std::istream hat den Prototyp istream& read (char* s, streamsize n) die tatsächliche Anzahl der gelesenen Bytes sollte durch den Aufruf istream::gcount(), auch die Gültigkeit des istream aus ios::good bekannt geworden ist.

istream::read(char* s, streamsize n) liest einen unformatierten Datenblock (ohne NULL Terminierung) der Größe n in das Array bei s. Auch wenn s ein Zeiger auf char ist, können Sie istream::read verwenden, um binäre Daten zu lesen. Zum Beispiel könnten Sie ein istream haben, die die Werte eines Arrays von Doppel hält (unter der Annahme, dass die endianness korrekt ist):

unsigned int count; 
input.read(reinterpret_cast<char*>(&count), sizeof(count)); 
double* data = new double[count]; 

for (unsigned int i = 0; i < count; ++i) 
    input.read(reinterpret_cast<char*>(data[i]), sizeof(double)); 

istream::gcount() gibt die Anzahl der Bytes im letzten istream::read Aufruf gelesen. In diesem Fall sehen wir, dass die Größe von count sich wahrscheinlich von der Größe eines double unterscheidet. Daher könnten wir istream::gcount() nicht verwenden, um die Größe des ersten Elements im data Array anzugeben.

+0

@CashCow Hat die richtige Lösung zu den Einschränkungen von' istreamream_read'. Ich kann nicht updaten, weil ich nicht mindestens 15 Reputationspunkte habe (ich bin immer noch ein Stack Overflow n00b). –

+0

Meine eigentliche Frage war, warum müssen wir 'gcount' nennen; Statt wie folgt kann der Aufrufer eine Verweisvariable übergeben, die durch 'read' auf die Anzahl der tatsächlich gelesenen Bytes gesetzt wird (die kleiner oder gleich' streamsize n' sein kann), anstatt dass der Aufrufer gcount aufruft jedes Mal. – legends2k

+0

Es erscheint vorzuziehen, die Anzahl der Bytes zurückzugeben, die als @CashCow mit 'istream :: readsome' gelesen werden. Wie @Mark B erklärt, wird vermieden, dass ein extra int deklariert werden muss, um als Referenz zu übergeben. Eine andere Option ist das Übergeben eines Zeigers an die Variable, die auf 'NULL' voreingestellt ist, was verwendet werden kann, um die tatsächliche Anzahl gelesener Bytes zu ignorieren:' istream & read (char * s, streamsize n, streamsize * bytesRead = NULL) '. Ich weiß jedoch nicht, ob es einen wesentlichen Vorteil gegenüber istream :: readsome bietet. –

2

Versuchen Sie den Befehl readsome stattdessen

streamsize readsome (char* buf, streamsize num); 

buf ist Ihr Puffer und num ist die Anzahl der Bytes, die Sie lesen möchten, höchstens die Anzahl der verfügbaren Bytes im Puffer, natürlich.

Der Rückgabewert ist die Anzahl der tatsächlich gelesenen Bytes.

Um eine Datei zu Ende lesen können Sie Schleife:

char buf[BUF_SIZE] 
streamsize bytesRead; 
do 
{ 
    bytesRead = instr.readsome(buf, BUF_SIZE); 
    // do stuff with the bytes you read, if any 
} while (bytesRead == BUF_SIZE); 
0

Als Antwort auf die ursprüngliche Frage, mit Anrufen Fehlerprüfung zu einem beliebten Programmierstil wurde als C war jung, aber es ging bald aus der Mode nach. Was passiert, sind kleine Dinge, die nicht sehr falsch sind, aber dennoch fast immer nur ein wenig unterlegen sind, bis sie von der Gemeinschaft ausgerufen und als schlecht bezeichnet werden. Dieser Code hat das Pech davor geschrieben worden zu sein, bevor dieses kleine Anti-Muster weit diskutiert wurde.

Als Antwort auf die Lösung von Cash Cow, denke ich, dass es einen Fehler gibt. Wenn Sie auf IO warten und genügend Zeichen haben, um den Puffer teilweise zu füllen, kehrt die Funktion zurück und die while-Schleife wird beendet, bevor die Datei vollständig gelesen wurde. Seine Lösung würde also wahrscheinlich korrekt laufen, wenn sie über die reine RAW geschrieben würde, würde aber nicht über gepufferte EA laufen.

Die richtige Lösung wäre natürlich, die While-Schleife zu beenden, wenn das EOF-Flag gesetzt ist. Ich bin mir im Moment nicht sicher, was die beste Antwort ist, wenn badbit eingestellt ist, aber Sie sollten wahrscheinlich auch mit diesem Fall umgehen.

Ich würde zustimmen, dass Readsome ist eine gute Alternative zu lesen, obwohl.

Edit: Manchmal Readsome ist nicht verfügbar (einige VC++ - Versionen). In diesem Fall ist das Lesen nicht unbrauchbar.

Verwandte Themen