Fgetc (stdin)

aminskee

Grünschnabel
Liebe Freunde,

ich habe ein kleines Problem und ich komme nicht weiter... Ich bitte euch um Hilfe!

Es geht darum, dass ich eine Funktion in main() aufrufen soll, aber ich weiss ich nicht wo genau dass kommt
ich habe schon 4stunden verbracht ,kein erfolg

Die Funktion liest das nächste Zeichen als ein unsigned char aus dem Stream Stream und gibt dessen Wert zurück, umgewandelt in einen int. Wenn ein End-of-File-Bedingung oder Lesefehler auftritt, wird EOF auf -1 gestellt.
C++:
#include <stdio.h>

void dumpStdinLine()
{
  char tempChar;
  do
  {
    tempChar = fgetc(stdin);
  } while ( (tempChar != EOF) && (tempChar != '\n') );
}

int main()
{
  int a1, a2, a3, b;
  while ( b != 3 )
  {
    printf("Geben Sie drei ganze Zahlen ein.\n");
    b = scanf("%d %d %d", &a1, &a2, &a3);
    printf("b == %d\n", b);
  }
  return 0;
}
 
Zuletzt bearbeitet von einem Moderator:
Hi

bitte beschreib genauer, was du vorhast.
Ich verstehs so nicht.

...
EOF kann nicht auf -1 gestellt werden, EOF ist nämlich immer -1
fgetc macht das, was du beschrieben hast.
Einen char einlesen und zurückgeben. Bei Ende/Fehler EOF (also -1) zurückgeben.

Und was hat der gezeigte Code damit zu tun?
 
Vielen Dank für die Antwort

Das ist die Aufgabe, ich habe alles bis Punkt 5 gelöst.

Der Code wurde vom Professor gegeben

2. Erläutert den Programmablauf, in Prosa oder als Diagramm. Was gibt scanf für einen Wert zurück, der in b gespeichert wird?

3. Probiert dann, was passiert, wenn ihr etwas anderes eingebt – Kommazahlen, oder Zeichen. (strg+c bzw. ctrl+c wird in der Folge hilfreich sein.)

4. Recherchiert, überlegt und erklärt mir, warum dieser Effekt auftritt. (Sucht zB bei Google mit Wör- tern wie „scanf“, „while“, „loop“, „wrong input“, „infinite“, etc)

5. Schaut euch jetzt die Funktion dumpStdinLine an. Recherchiert unbekannte Befehle, und erläutert, was die Funktion macht und wie sie das tut.

6. Wo in main() in der Schleife muss diese Funktion aufgerufen werden, um obiges Problem zu besei- tigen? Testet es. (Ich will aber auch eine Erklärung haben.)

Vielen dank Für eure Hilfe!!
 
Du hast schon 4 Stunden mit dem Problem verbracht?
Du musst den Funktionsaufruf doch einfach nur nach dem printf() setzen:

C++:
#include <stdio.h>
 
void dumpStdinLine()
{
  char tempChar;
  do
  {
    tempChar = fgetc(stdin);
  } while ( (tempChar != EOF) && (tempChar != '\n') );
}
 
int main()
{
  int a1, a2, a3, b;
  while ( b != 3 )
  {
    printf("Geben Sie drei ganze Zahlen ein.\n");
    b = scanf("%d %d %d", &a1, &a2, &a3);
    printf("b == %d\n", b);
    dumpStdinLine();
  }
  return 0;
}

Lg
 
Ah, wieder mal das scanf-Phänomen :rolleyes:

Zuerst zwei allgemeine Sachen über scanf:
a) Das scanf was von der Tastatur einliest weißt du ja sicher.
Für die folgenden Erklärungen zuerst etwas detaillierter:

Es gibt eine Art Tastenspeicher für die Tastatur, in dem eben die eingegeben Buchstaben/Ziffern
etc. nach dem Drücken reinkommen. Auch die Entertaste (=Zeilenwechsel) und so sind dabei,
nicht nur die "sichtbaren" Buchstaben.

Im Normalfall verarbeitet scanf den Inhalt von diesem Tastaturspeicher und leert ihn dann
(zumindest den verarbeiteten Teil), weil das ja schon ins Programm eingelesen wurde.
Wenn der Speicher am Anfang leer ist (nichts gedrückt) wird gewartet,
bis genug drin ist (bis Enter gedrückt wurde).

b) Der Rückgabewert von scanf im Programm ist die Anzahl
der erfolgreich eingelesenen Variablen.
Wenn man also drei %d, also drei int, einliest, bekommt man im Idealfall den Returnwert 3.


Zur Frage 2 (auch wenn du sie schon hast) (was ist Frage 1?):
Drei Zahlen werden eingelesen.
Wenn der Benutzer was Falsches eingibt (keine Zahlen, zu wenig...)
ist der Returnwert nicht 3, dann wird mit der Schleife alles wiederholt.
Er muss solange eingeben, bis er eine richtige Eingabe macht.
(dumpStdinLine wird derzeit nicht verwendet.)

Das ist zumindest der Sinn vom Programm.
Ganz zutreffen tuts ja nicht...deswegen die weiteren Fragen.

Frage 3 und 4:
Wenn man jetzt was Falsches eingibt, erwartet man folgenden Ablauf:
-scanf holt sich den Inhalt des Tastaturspeichers.
-Tastaturspeicher wird geleert.
-scanf merkt, dass es keine 3 Zahlen sind
-Schleife wird wiederholt
-Zweites scanf findet einen leeren Tastaturspeicher und wartet auf eine neue Eingabe

In Wirklichkeit wird der Speicher mit der falschen Eingabe vom scanf aber nicht geleert.
Nur bei richtiger Eingabe wird geleert.
scanf merkt: Falsche Eingabe, Schleife Wiederholen
scanf merkt: Falsche Eingabe (=gleiche Eingabe wie vorher), Schleife Wiederholen
scanf merkt: Falsche Eingabe (=gleiche Eingabe wie vorher), Schleife Wiederholen
...
Und der Benutzer kann nie mehr richtige Zahlen eingeben.
Der Inhalt des Tastaturspeichers befriedigt alle scanf bis in alle Ewigkeit
(oder bis zum Programm-beenden).

Frage 5 und 6:
fgets bedient sich natürlich beim gleichen Tastaturspeicher wie scanf.
Es liest nur immer genau ein Zeichen (einen Tastendruck) ein
und nimmt den auch sicher vom Speicher raus.

dumpStdinLine liest jetzt alles vom T.speicher raus, bis ein Enterdruck drin war
(oder bis fgetc einen Fehler meldet).

Wenn man das direkt nach dem scanf macht (vor dem eventuell kommenden nächsten scanf)
wird eine eventuell übriggelassene Eingabe im T.speicher dadurch rausradiert.
Und wenn scanf nichts übrig gelassen hat
(wenn die Eingabe in Ordnung war) machts auch nichts.


So, komplett verwirrt? :p
 
Vielen Dank ,

So Einfach ja ,aber wie funktioniert ?
ich bin nicht darauf gekommen da ich mir es schwer vorgestellt habe .

Danke Dir .

Lg

HI ,

wenn ich Zeichen eingebe ,b wird auf null gesetzt und ich kann nur einmal was eingeben .
also ist nicht richtig was du sagst !!

LG
 
Zuletzt bearbeitet von einem Moderator:
Vielen Dank .
nicht schlecht sehr nett und gut von dir !!echt Super erklärt.

also Frage 1 ist nichts besonders:

1. Ladet euch von ISIS dreiZahlen.c runter, schaut euch den Code an, kompiliert und testet es. Beachtet die Funktion dumpStdinLine vorerst nicht (sie wird ja auch nicht aufgerufen). Gebt erst zum Testen tatsächlich nur ganze Zahlen ein.

ich zeige dir mal meine Antwort ,also es gibt viele sprach-Fehler , die korrigiere ich noch




2 - Scanf liefert die zahl der eingegebene zahlen ,besser gesagt liefert die zahl der Additionale Parametern in diesem fall ist 3

3- Der Programm kommt zum Abstürzt ,oder unendliche Schliefe mit der eingegeben Ausgaben ,da die variablen a1,a2,a3 sind als Integer deklariert ,und können keine Kommazahlen, oder Zeichen enthalten und in unsere Programm wird mit Scanf über kommondozeilen neue werte zu den variablen a1.a2,a3 zugewiesen ,und die wie davor erklärt worden , von Typ Integer sein sollen

4- Es ist logisch so ein Effekt aufzutreten :

- wir haben ein while-schleife die abhängig von dem wert von b , und wir wissen das b enthält die zahl der Additionale Parametern in Scanf 3
- Aber unsere Scanf wird uns keine wert liefern ,da wir versuchen falsche Parametern-Typ einzugeben , Kommazahlen "Float", oder Zeichen"Char"

Fazit
Damit als Einwandfrei laufen soll ,muss die eingegebene Parametern ,von Typ Integer sein.

5 - Hier sind Kommentare zu diese Methode( Funktion ) hinzugefügt

// eine Funktion wird uns keine Ergebnis liefern da es als Void definiert ist

void dumpStdinLine()
{

/* Eine Variable vom Typ char ,kann Zeichen enthalten 0...9 , Sonderzeichen, Buchstaben /*

char tempChar;


// do-while Schleife wird trotz der boolesche Bedingung ein mal durchlaufen

do
{

/* Hier wird zu unsere Variabel tempChar mit der vordefinierte Funktion fgetc zugewiesen.

int fgetc(FILE *); ---->

Gibt uns das Zeichen derzeit auf die durch den internen Datei-Position Indikator (Zeiger)für den angegebenen Stream in unsere Fall "stdin" Standardeingabe. Die interne Datei Stellungsanzeige wird dann durch ein Zeichen vorgerückt, um zum nächsten Zeichen zeigen.

Die Funktion fgetc hat als Parameter der vordefinierte Standard stream stdin, damit werden die Datenströme zu unsere Variabel tempChar zugewiesen . /*




tempChar = fgetc(stdin);

/*Die Datenströme soll durch die Wille-schleife erfolgen solange unsere boolesche Bedingung Wahr ist in diesem Fall haben wir zwei AND verknüpfte Bedingungen :

Die Erste Bedingung ist (tempChar != EOF) , mit der vordefinierte EOF " #define EOF (-1) " ,

es wird ein symbolische Konstante definiert mit dem wert -1
und damit ist EOF für den Compiler implizit ein int. Nehmen wir eine 16-Bit-Umgebung an, dann hat EOF den Wert 0xFFFF, und wenn dieser Fall eintritt, erhält c von getchar den Wert 0xFF. Für den Vergleich gibt es nun zwei Möglichkeiten:

Ist c ein unsigned char, stellt 0xFF den Wert 255 dar, der in den Integer 255 (0x00FF) umgewandelt wird – der Vergleich mit EOF schlägt fehl.

Ist c jedoch ein signed char, dann stellt 0xFF den Wert -1 dar, der in den Integer -1 (0xFFFF) zurück gewandelt wird – der Vergleich mit EOF funktioniert.

(tempChar != EOF) ,Dann soll es heissen dass kein Fehler beim Konvertierungen geben soll .

Die zweite bedingung (tempChar != '\n') ist sehr einfach zu erklären ,unsere variabel darf kein zeilenumbruch enthalten also unsere variabel kann nur eine kette von zeichen enthalten hier ist ein String-Form gemeint. */

} while ( (tempChar != EOF) && (tempChar != '\n') );
}

Die Funktion liest das nächste Zeichen als ein unsigned char aus dem Stream Stream und gibt dessen Wert zurück, umgewandelt in einen int. Wenn ein End-of-File-Bedingung oder Lesefehler auftritt, EOF wird also -1 zurückgeben.
 
Zu allem, was bei meinem Beitrag oben unklar ist, bitte nachfragen.

Deine Antworten würd ich so jedenfalls nicht abgeben.
Teilweise sehr durcheinander/nicht themenbezogen, teilweise falsch.

Mit 16bit etc. hat das Ganze überhaupt nichts zu tun.
Und -1 von 32bit bleibt auch bei 16bit -1
Das, was du meinst, ist signed/unsigned.
 
Zurück