Forum: PC-Programmierung buffer[res]=0;


von Welle 🧐 S. (w3llschmidt)


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

???

von Micha C. (Gast)


Lesenswert?

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

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

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.

von test (Gast)


Lesenswert?

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);

von Stefan W. (dl6dx)


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

von Welle 🧐 S. (w3llschmidt)


Lesenswert?

Danke für eure Antworten :-)

Das hilft mir weiter!

--

C hat echt Suchtpotential ...

von Welle 🧐 S. (w3llschmidt)


Lesenswert?

Besser?

1
res = read(fd, buffer, sizeof(buffer) -1);
2
             
3
if (res >=0) {
4
buffer[res]=0;
5
printf("%s", buffer)
6
}

von dadada (Gast)


Lesenswert?

ja, besser. wird noch besser wenn du die {} weglaesst, und res=0; hinter 
die if abfrage schreibst.

von dadada (Gast)


Lesenswert?

und > durch < ersetzt.

von Mac (Gast)


Lesenswert?

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.

von Welle 🧐 S. (w3llschmidt)


Lesenswert?

dadada schrieb:
> ja, besser. wird noch besser wenn du die {} weglaesst, und res=0; hinter
> die if abfrage schreibst.

Ahhh, verstehe :-D

1
res = read(fd, buffer, sizeof(buffer) -1);
2
             
3
if (res <0) res=0;
4
5
buffer[res]=0;
6
printf("%s", buffer);

Das '=' brauch ich auch nicht mehr? 0=0?

von Fabian O. (xfr)


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.

von Stefan W. (dl6dx)


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

von Welle 🧐 S. (w3llschmidt)


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
}

???

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


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.

von Welle 🧐 S. (w3llschmidt)


Lesenswert?

Daran hab ich erstmal n Abend zu knabbern :-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.