buffer[res]=0;

#3008543
Lesenswert?

Soweit ist mir das klar ...

1
char buffer[1024];
2

3
res = read(fd, buffer, sizeof(buffer));
4
buffer[res]=0;
5
printf("%s", buffer);


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| | | | | | | | | | | ... | | | | | | |

???
#3008601
Lesenswert?

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...
#3008742
Lesenswert?

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.
#3008753
Lesenswert?

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
#3008780
Lesenswert?

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 ...

1
if (res < 0) {
2
  res = 0;
3
}

???
#3008882
Lesenswert?

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.
#3008922
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren