EOF für while Schleife funzt nicht wie es soll?
-
Hi, bin noch totaler Anfänger und habe jetzt die Aufgabe bekommen, ein Programm zu schreiben in dem man beliebig viele Zahlen hintereinander eintippt und dann mit Strg + D (unter Linux) abschließt. Die Erkennung des EOF soll mithilfe von scanf erkannt werden. Anschließend soll das Programm dann den Mittelwert ausspucken. Das mit dem Mittelwert ist natürlich kinderleicht, bei der Aufgabe geht es um die Verwendung von scanf und EOF.
Mein Programm sieht aus wie folgt:#include <stdio.h>
int main(){
int a = 0; //Eingabe
float b = 0; //Summe
float c = 0; //Zähler
while(scanf("%d", &a) != EOF){
scanf("%d", &a);
b = b + a;
c++;
printf("a = %d\n", a);
printf("b = %f\n", b); //Ausgabe um zu prüfen was schief läuft.
printf("c = %f\n", c);
}
printf("Der Mittelwert ist %f.\n", b/c);
return 0;
}Das Problem: das Programm erkennt nur jede zweite Eingabe. Wieso?
Ich als gestandener Anfänger verstehe wirklich nicht, wieso das Programm nur jede zweite Eingabe erkennt. Wie lässt sich das am einfachsten umschreiben? (nicht vergessen: das EOF soll mithilfe von scanf erkannt werden.)
-
Das Problem: das Programm erkennt nur jede zweite Eingabe. Wieso?
Deshalb:
while(scanf("%d", &a) != EOF){ // ^^^^^ Eins scanf("%d", &a); // ^^^^^^ Zwei
-
1. Gibt es Code-Tags hier:
2. Zweitens wird dies deutlich kommuniziert:
Admin vor langer Zeit in einer weit, weit entfernten Galaxis schrieb:
Wenn du Source Code postest, dann bitte mit Code-Tags versehen.
Bilderbuchlandung bereits hingelegt.
3. Du machst zweimal
scanf
und wunderst dich dann, dass du die Zahlen zweimal eingeben musst? Weißt du überhaupt, was die Funktion macht?float
für einen Zähler ist eine ganz miese Idee. Besser istunsigned long long
.
5. Wenn ich dem Program was anderes als Dezimalziffern gebe, hängt sich der Prozess auf. Du solltest den Input lieber als Reihe von Strings einlesen und dann parsen, so kannst du auch Bufferüberläufe verhindern.
Kurz: man kann das Program hierauf runterbrechen:
#include <stdio.h> int main(void) { int cur_input=0; unsigned long long number_of_inputs=0; int overall_input=0; while(scanf("%d",&cur_input)!=EOF) { overall_input+=cur_input; ++number_of_inputs; } printf("Der Mittelwert ist %f.\n",(float)overall_input/number_of_inputs); return 0; }
Behebt das Problem Nummer 5 nicht, aber was soll's.
-
dachschaden schrieb:
1. Gibt es Code-Tags hier:
2. Zweitens wird dies deutlich kommuniziert:
Admin vor langer Zeit in einer weit, weit entfernten Galaxis schrieb:
Wenn du Source Code postest, dann bitte mit Code-Tags versehen.
Bilderbuchlandung bereits hingelegt.
3. Du machst zweimal
scanf
und wunderst dich dann, dass du die Zahlen zweimal eingeben musst? Weißt du überhaupt, was die Funktion macht?float
für einen Zähler ist eine ganz miese Idee. Besser istunsigned long long
.
5. Wenn ich dem Program was anderes als Dezimalziffern gebe, hängt sich der Prozess auf. Du solltest den Input lieber als Reihe von Strings einlesen und dann parsen, so kannst du auch Bufferüberläufe verhindern.
Kurz: man kann das Program hierauf runterbrechen:
#include <stdio.h> int main(void) { int cur_input=0; unsigned long long number_of_inputs=0; int overall_input=0; while(scanf("%d",&cur_input)!=EOF) { overall_input+=cur_input; ++number_of_inputs; } printf("Der Mittelwert ist %f.\n",(float)overall_input/number_of_inputs); return 0; }
Behebt das Problem Nummer 5 nicht, aber was soll's.
Zu 1. und 2. : sorry, dass ich nicht nach posts von vor langer zeit in einer weit, weit entfernten galaxie suche, bevor ich ein super simples problem schildere. dass der code so nicht mehr ganz so sexy aussieht ist mir schon aufgefallen, aber aus zeitgründen hab ich das trotzdem so reingestellt. bei so nem kleinen code ist das schließlich nocht zu verkraften.
3. ich bitte vielmals um vergebung, dass ich nicht auf die idee gekommen bin, dass das scanf in der bedingung ebenfalls gelesen und ausgeführt wird, oh großer allmächtiger meister! meine fresse, doch nicht gleich so aggro. hat nen grund dass ich sagte ich sei ein totaler anfänger.
4. k, danke für den tipp merk ich mir, float reicht mir für mein einfaches programm bisher. (das long long dann aber nur wenn ich mit zahlen größer als 32 bit arbeite oder?)
5. mehr als dezimalzahlen muss es auch nicht können.
Der Code ist ja schön und gut, für mich als Anfänger hätte aber bereits Bashars Kommentar gereicht, einfach das zweite scanf entfernen und fertig.
Nächstes Mal so Angaben wie "bin noch totaler Anfänger" und "wie kann man das am einfachsten umschreiben" mehr bedeutung schenken, dazu noch halb so unhöflich und deine Kommentare würden einem Noob vermutlich helfen.
@Bashar vielen Dank, problem gelöst
-
Fronox1 schrieb:
Zu 1. und 2. : sorry, dass ich nicht nach posts von vor langer zeit in einer weit, weit entfernten galaxie suche
Der Hinweis ist GELB UNTERLEGT auf der ersten Seite zu finden. Das kann jeder sehen. Jeder.
Fronox1 schrieb:
bevor ich ein super simples problem schildere. dass der code so nicht mehr ganz so sexy aussieht ist mir schon aufgefallen, aber aus zeitgründen hab ich das trotzdem so reingestellt. bei so nem kleinen code ist das schließlich nocht zu verkraften.
Nein, damit kommst du nicht davon.
Wenn du genau so schlampig dabei bist, deinen Code zu präsentieren, sind wir genauso schlampig, dir zu helfen. So einfach ist das. Dass wir das trotzdem machen, zeigt, wie tolerant unsereins doch ist.Fronox1 schrieb:
3. ich bitte vielmals um vergebung, dass ich nicht auf die idee gekommen bin, dass das scanf in der bedingung ebenfalls gelesen und ausgeführt wird, oh großer allmächtiger meister! meine fresse, doch nicht gleich so aggro. hat nen grund dass ich sagte ich sei ein totaler anfänger.
War ich aggressiv? Nein.
War ich sarkastisch? Vielleicht. Aber wenn du bereits Funktionen in deinem Code verwendest, geht man einfach davon aus, dass du weißt, was du tust.Wie ich hier bereits gelesen habe: Code ist Logik pur. Du musst ganz genau wissen, wann du welches Zeichen an welche Stelle setzt.
Fronox1 schrieb:
4. k, danke für den tipp merk ich mir, float reicht mir für mein einfaches programm bisher. (das long long dann aber nur wenn ich mit zahlen größer als 32 bit arbeite oder?)
Das ist einfach ein Schutzmechanismus. Wenn du eine Weile programmierst, lernst du einfach, Benutzereingaben nicht zu vertrauen und diese so gut zu überprüfen wie möglich. Wenn dein Programm beispielsweise in einer sicherheitsrelevanten Umgebung verwendet wird, könnte ein Angreifer bis 2^32-1 Ausführungen gehen und dann einen Überlauf provozieren, und dann eine Division durch 0 ausführen lassen. Bei 2^64 kann er lange genug zählen, bis es dem Admin vielleicht auffällt. Und selbst, wenn dein Programm nicht Teil einer sicherheitskritischen Infrastruktur ist, gehört es einfach zum guten Ton, sicheres Programmieren zu lernen.
Fronox1 schrieb:
Nächstes Mal so Angaben wie "bin noch totaler Anfänger" und "wie kann man das am einfachsten umschreiben" mehr bedeutung schenken, dazu noch halb so unhöflich und deine Kommentare würden einem Noob vermutlich helfen.
Nein, du bist einfach faul, dass du weder Google noch die Suchfunktion bemühst, deinen Code nicht vernünftig postet, und mit Sarkasmus nicht zurechtkommst. Aber wenn es dir in Zukunft hilft, diese Anfängerfehler zu vermeiden, war mein Post nicht unnütz.
Siehe auch.Schönen Sonntag noch.
-
Fronox1 schrieb:
4. k, danke für den tipp merk ich mir, float reicht mir für mein einfaches programm bisher. (das long long dann aber nur wenn ich mit zahlen größer als 32 bit arbeite oder?)
Ich denke, Du brauchst in Deinem Programm keine Fließkommazahlen. Einfach int statt float nehmen, sollte für Dein Problem vollauf genügen, außer natürlich beim Divisionsergebnis zum Schluss.
-
Wenn dein Programm beispielsweise in einer sicherheitsrelevanten Umgebung verwendet wird, könnte ein Angreifer bis 2^32-1 Ausführungen gehen und dann einen Überlauf provozieren, und dann eine Division durch 0 ausführen lassen. Bei 2^64 kann er lange genug zählen, bis es dem Admin vielleicht auffällt. Und selbst, wenn dein Programm nicht Teil einer sicherheitskritischen Infrastruktur ist, gehört es einfach zum guten Ton, sicheres Programmieren zu lernen.
Alter was nimmst du wenn du nicht hier postest? Er will nur bisschen einlesen mit scanf.