was ich nicht verstehe:
> buffer[res]=0; <
Wen 'res' die gelesenen Elemente sind, schreibt das an die
Postion eine '0'?
|h|a|l|l|o| |w|o|r|l|d|0| | | | | | | | | | | ... | | | | | | |
???
Hallo,
> buffer[res]=0;
der Aufruf read liefert im Erfolgsfall die Anzahl der gelesenen Bytes.
Um dann den Puffer als Zeichenkette ausgeben zu können, muss am Ende ein
Null-Byte angehängt werden. Anderenfalls weiß printf nicht, wann der
Puffer zu Ende ist.
Gruss
Micha
Gefährlich. Bei einem I/O-Error oder EOF gibt read eine -1
zurück. Was dann passiert kann seht interessant werden ;)
Erst auf Fehler testen, dann erst res verwenden.
Die Implementierung ist auch nicht ganz richtig. Falls read() wirklich
so viele Bytes liest wie Buffer groß ist, schreibst du in der nächsten
Zeile über das Array hinaus.
besser wäre: res = read(fd, buffer, sizeof(buffer) - 1);
Henrik Wellschmidt schrieb:> Wen 'res' die gelesenen Elemente sind, schreibt das an die> Postion eine '0'?
Hallo Henrik,
zum Verständnis sind ein paar C-Grundlagen wichtig:
1. Die Zählung der Elemente des Arrays beginnt bei 0. Liest die Routine
res Zeichen ein, stehen die auf den Speicherstellen buffer[0] bis
buffer[res - 1]. buffer[res] ist die erste Speicherstelle nach den
eingelesenen Zeichen.
2. 0 und '0' sind zwei ganz verschiedene Dinge. 0 steht den numerischen
Wert 0 dar (0b00000000 bzw. 0x00). '0' ist die ASCII-Codierung der
Zeichens der Ziffer 0.
3. In C wird das Ende einer Zeichenketten (String) mit eine "Endemarke"
gekennzeichnet, und zwar steht an der letzten Stelle der numerische Wert
0. Die Zeichenfolge "Hello World!" besteht also tatsächlich aus {'H',
'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0}.
buffer[res]=0 erzeugt diese Endemarke.
Grüße
Stefan
PS: Du solltest in jedem Fall auch prüfen, ob res >= sizeof(buffer) ist.
buffer[sizeof(buffer)] ist die erste Speicherstelle hinter buffer, da
liegt mit Sicherheit was anderes...
dadada schrieb:> ja, besser. wird noch besser wenn du die {} weglaesst, und res=0; hinter> die if abfrage schreibst.dadada schrieb:> und > durch < ersetzt.
Du willst bei einem Fehler so tun, also ob EOF wäre? Das wird ja ein
tolles Programm.
Stefan Wagner schrieb:> PS: Du solltest in jedem Fall auch prüfen, ob res >= sizeof(buffer) ist.
Wenn das passiert, ist read() fehlerhaft und hat wahrscheinlich über den
Puffer hinausgeschrieben. Dann ist es also schon zu spät. Man kann
natürlich versuchen, das Programm noch geordnet abzubrechen, aber im
Prinzip kann man sich dann auf nichts mehr verlassen.
Henrik Wellschmidt schrieb:> Ahhh, verstehe :-D
Gewöhn Dir lieber leserliche, einheitliche und fehlervermeidende
Codeformatierung an. Das heißt: Immer Klammern setzen und jede Anweisung
in eine eigene Zeile:
1
res=read(fd,buffer,sizeof(buffer)-1);
2
3
if(res<0){
4
res=0;
5
}
6
7
buffer[res]=0;
8
printf("%s",buffer);
Damit passiert im Fehlerfall das gleiche wie wenn ein leerer String
gelesen wurde. Ob das ist was Du willst, musst Du wissen. Du könntest
den Fehler auch dem Benutzer melden, es später nochmal probieren, etc.
Fabian O. schrieb:>> res >= sizeof(buffer) ist.>> Wenn das passiert, ist read() fehlerhaft und hat wahrscheinlich über den> Puffer hinausgeschrieben.
res == sizeof(buffer) wäre im ursprünglichen Code möglich gewesen. Die
Abfrage res >= sizeof(buffer) war meinem "Sicherheitsbedürfnis"
("paranoid coding" :-) ) geschuldet.
Grüße
Stefan
Fabian O. schrieb:> Gewöhn Dir lieber leserliche, einheitliche und fehlervermeidende> Codeformatierung an. Das heißt: Immer Klammern setzen und jede Anweisung> in eine eigene Zeile:
Okay!
Mac schrieb:> Du willst bei einem Fehler so tun, also ob EOF wäre? Das wird ja ein> tolles Programm.
Was ist mit Mac seinem Einwand ...
Darf ich mich hier mal einmischen?
> res = read(fd, buffer, sizeof(buffer) - 1);>> if (res < 0) {> res = 0;> }
etwas Derartiges ist eine ganz schlechte Idee.
Alle Lesefunktionen sind in C so gestaltet, dass man mit ihrem
Rückgabewert unmittelbar die umgebende Schleife steuern kann, die den
Einlesevorgang solange wiederholt, bis keine Daten mehr da sind.
Etwas weiter ausgeholt:
Man sieht oft, durchaus auch in Lehrbüchern, Leseschleifen dieser
Gestalt (symbolische Schreibweise)
File = fopen( .... )
while( !feof( File ) )
{
read
process
}
fclose( File );
und genau das ist die Form, die man in C nicht macht!
Das Runtime System von C versucht nicht in die Zukunft zu sehen und das
eof zu erahnen.
Statt dessen ist ein eof Teil des Returnwertes des Read (wie auch immer
das dann bei der konkreten Lesefunktion aussieht). D.h. eof wird erst
dann erkannt, wenn ein Leseversuch gestartet wird und dieser Leseversuch
als ganzes schief geht. Zum Beispiel geht er schief, weil ein eof
aufgetreten ist. Er kann aber auch zb deswegen schief gehen, weil jemand
die CD aus dem Laufwerk genommen hat oder weil die Netzwerkverbindung
abgerissen ist oder .... Es gibt viele Möglichkeiten, warum ein
Leseversuch schief gehen kann, eof ist nur einer davon.
Die korrekte Art und Weise, wie man in C Files einliest, sieht dem
Prinzip nach so aus
File = fopen( .... )
while( read .... liefert keinen Fehler )
{
process
}
if( ! eof( File ) )
{
Fehlermeldung ausgeben: Irgendwas ist beim Lesen schief gelaufen
Eventuell Zusatzinformation für die Fehlerursache besorgen
}
fclose( File )
D.h. man zerstört sich NICHT den Returnwert vom read, sondern benutzt
ihn um damit die Schleife zu steuern. Meldet der read auf die Art einen
Fehler (in diesem konkreten Fall, in dem er einen negativen Wert
liefert. Andere read-Funktionen liefern was anderes), dann wird die
Schleife beendet und festgestellt, warum sie beendet wurde. War es, weil
eof aufgetreten ist, dann ist alles paletti, das File wurde komplett
gelesen. In allen anderen Fällen gab es irgendeinen Fehler, den man
gegebenenfalls weiter ergründen muss.
Und ich vergass:
Dafür gibt es auch eine typische Foren/Newsgroup Fehler-Anfrage.
Sie lautet: Warum wird in meinem Programm die letzte Eingabe
(Eingabezeile) doppelt bearbeitet?
Und noch ehe man den Code sieht, kann man seine 4 Buchstaben darauf
verwetten, dass man im Code genau diese Struktur
while( !feof( File ) )
{
read
process
}
finden wird. Das ist das typische Symptom dafür.