Hallo Leute!
Ich habe ein Problem mit der Funktion gets();
Ich möchte einen Taschenrechner programmieren, der zunächst einmal die
Anfangszahl einliest und anschließend diese Zahl und zusätzlich den
eingegebenen Operator zu einem Ergebnis errechnet, bis das "=" 2x
gedrückt wird.
So solls aussehen:
Eingabe Startzahl: 833
833+3 RETURN drücken
=836-4 RETURN drücken
=832*2 RETURN drücken
=1664/4 RETURN drücken
=416== RETURN drücken
ENDE
Das Ganze möchte ich mit der Funktion gets() machen. Das Problem ist
aber, dass der Cursor nicht beim Aufruf von gets() anhält, sondern das
Programm einfach weiterläuft, ohne dass ich eine Eingabe getätigt habe.
Hier mein Codeschnipsel:
1
#include<stdio.h>
2
3
intmain(void)
4
{
5
floatAnfangszahl;
6
charOperator_und_Zahl[20];
7
8
printf("Anfangszahl eingeben: ");
9
scanf("%f",&Anfangszahl);
10
printf("= %.7f\n",Anfangszahl);
11
gets(Operator_und_Zahl);//Hier sollte der Cursor stehen bleiben, damit ich meine Eingabe tätigen kann
Das Problem ist an dieser Stelle nicht gets, sondern scanf.
scnaf liest zwar das \n mit ein, stellt es aber wieder in die
EingabeQueue zurück, da es für die Eingabe hier
scanf("%f",&Anfangszahl);
nicht gebraucht wurde.
Dann kommt gets zu Zug und findet als allererstes das Return vor,
welches bei der Eingabe der Zahl übrig blieb.
Mischen von getch(), scanf() und gets() ist meistens eine schlechte
Idee. Man verliert sehr schnell den Überblick, welche Zeichen noch in
der Eingabe auf Bearbeitung warten und welche nicht.
Übrigens: gets ist in C eine "Funktion non grata".
man sollte sie NIE benutzen. Dass sie in C noch vorhanden ist, hat
historische Ursachen.
gets: ein definitives NO-NO
fegts: die Funktion der Wahl
(Da du auf einem Taschenrechner bist, kann es natürlich sein, dass du
kein fgets zur Verfügung hast. Solche Umgebungen sind meist ein wenig
eigen. Aber du solltest auf jeden Fall feststellen ob du fgets hast und
wenn ja gleich wieder vergessen, jemals von einer Funktion gets gehört
zu haben. Oder die C-Götter mögen dich mit einer 10 Jahre andauernden
Kretze bestrafen. gets ist für mehr vom Benutzer verursachte Abstürze,
Progamm-Cracker-eien und sonstige lausige Fehler in C Programmen
verantwortlich, als irgendeine andere Funktion)
Ok danke erstmal für die schnelle Hilfe.
Ich werde es dann wohl mit scanf() machen. Nun aber noch eine Frage:
Ich habe ja oben in meinem Beispiel den Ablauf des Programms gezeigt.
Wie kann ich sozusagen Zwei unterschiedliche Eingaben mit scanf()
trennen?
Die Erste Eingabe wäre ja das Rechenzeichen (sprich, welche Operation
ausgeführt werden soll). Die zweite Eingabe wäre dann die Zahl, mit der
das gewünschte Rechenzeichen arbeiten soll.
Vielen Dank!
der_lord schrieb:
> Ich werde es dann wohl mit scanf() machen. Nun aber noch eine Frage:
Das war die falsche Entscheidung :-)
fgets wäre es gewesen, zusammen mit einem Auftrennen der Eingabe in
deinem Programm.
Robuste Eingabe erhält man praktisch nur mit der Methode:
Die Eingabe des Benutzers wird immer erst als ein String eingelesen.
Das Programm analysiert dann String um die Einzelteile der Eingabe
zu bestimmen.
Es gibt zwar seit dem letzten C-Standard so etwas wie "regular
Expressions" in der Formatanweisung, aber
1) kenn ich mich damit wenig aus
2) halte ich die selbst-Aufdröselmethode immer noch für besser,
da sie einem bessere Fehlermeldungen im Falle eines Falles
erlaubt
> Ich habe ja oben in meinem Beispiel den Ablauf des Programms gezeigt.> Wie kann ich sozusagen Zwei unterschiedliche Eingaben mit scanf()> trennen?
Da du noch am Anfang stehst, ist ein sauberes Stringparsen
wahrscheinlich noch zu schwierig für dich. Daher
> Die Erste Eingabe wäre ja das Rechenzeichen (sprich, welche Operation> ausgeführt werden soll). Die zweite Eingabe wäre dann die Zahl, mit der> das gewünschte Rechenzeichen arbeiten soll.
Man kann bei scanf auch mehrere 'Formatieranweisungen' geben
double Zahl1, Zahl2;
char Zeichen;
scanf( "%f%c%f", &Zahl1, &Zeichen, &Zahl2 );
Eine Eingabe von
833+78
wird von scanf dann in
Zahl1 = 833
Zeichen = '+'
Zahl2 = 78
aufgedröselt.
Jetzt habe ich das Problem, dass scanf() anscheinend falsch mit den
float-Werten rechnet.
Gebe ich zum Beispiel:
491.00000+2 ein, so kommt als Ergebnis 490 raus.
Hier nun der etwas veränderte Code:
scanf rechnet überhaupt nicht.
Aber in solchen Fällen, in denen man eine Benutzereingabe auswerten
will, ist es IMMER eine extrem gute Idee, sich erst mal das was das
Programm überhaupt eingelesen hat ganz einfach ausgeben zu lassen.
Denn viel öfter als man denkt, liest das Programm nicht das ein, was der
Programmierer sich vorstellt.
1
scanf("%f",&Anfangszahl);
2
printf("= %.7f",Anfangszahl);
3
scanf("%c%f",&Operator,&Zahl);
4
5
printf("Eingelesen: #%c# %f\n",Operator,Zahl);
Ich habe auch vor und hinter das Operator-Zeichen in der Ausgabe ein
Sonderzeichen (in dem Fall #) eingefügt, damit ich in der Ausgabe auch
Leerzeichen oder sonstige nicht-darstellbare Zeichen erkennen kann.
ich gebe ein:
Anfangszahl: 4
Dann erscheint in der Konsole:
4.0000000
dann gebe ich
+6 ein, dann stimmt das Ergebnis.
Es erscheint
10.0000000
Gebe ich jetzt aber erneut einen Wert zur Addition ein, dann stimmt der
Wert nicht.
10.0000000+3
dann kommt als Ergebnis
7.0000000
der_lord schrieb:
> ich gebe ein:>> Anfangszahl: 4>> Dann erscheint in der Konsole:>> 4.0000000>>> dann gebe ich> +6 ein, dann stimmt das Ergebnis.> Es erscheint> 10.0000000>> Gebe ich jetzt aber erneut einen Wert zur Addition ein,
aha.
Wir sind also im 2.ten Durchlauf durch die while Schleife.
Hast du dir auch ausgeben lassen, was da dann eingelesen wurde.
> dann stimmt der> Wert nicht.>> 10.0000000+3> dann kommt als Ergebnis> 7.0000000
Ist doch richtig!
4 + 3 ergibt 7
(Du änderst ja nie deine Anfangszahl, rechnest aber immer Anfangszahl +
Zahl)
Hallo Leute!
Es geht immer noch nicht :( Hatte gestsern keine Zeit mehr
weiterzuprogrammieren.
Ich finde den Fehler einfach nicht....Das Programm fragt zwar nach der
Anfangszahl, rechnet aber danach nicht mit den Werten weiter und gibt
bei der printf-Anweisung nichts aus...
Hier mein Code:
der_lord schrieb:
> Ich finde den Fehler einfach nicht....Das Programm fragt zwar nach der> Anfangszahl, rechnet aber danach nicht mit den Werten weiter und gibt> bei der printf-Anweisung nichts aus...
Dann befolge den vorher schon gegebenen Rat:
Wenn dir nicht klar ist, was im Programm warum abgeht, dann verschaffe
dir Klarheit, indem du ins Programm printf Anweisungen einbaust, die dir
sagen was wann und warum passiert.
> do> {> scanf("%c%f",&Operator,&Zahl);
printf( "Op: %c Zahl: %f\n", Operator, Zahl );
> switch(Operator)> {> case '+':
printf( "Berechne Addition: %f + %f\n", Anfangszahl, Zahl
);
> Anfangszahl = Anfangszahl+Zahl;> printf("= %.7f",Anfangszahl);> break;> case '-':
printf( "Berechne Subtraktion: %f - %f\n", Anfangszahl,
Zahl );
> Anfangszahl = Anfangszahl+Zahl;> printf("= %.7f",Anfangszahl);> break;
default:
printf( "Unbekannter Operator: %c\n", Operator );
> }> }while(Operator!='=')>
Jetzt fange ich mal schrittweise an das Programm zu verstehen...Ich habe
das Ganze jetzt erstmal Schritt-für-Schritt aufgefädelt.
Nun möchte ich mir lediglich den Operator und die Zahl ausgeben lassen,
die ich vorher eingegeben habe...Und das funktioniert schon mal nicht.
1
#include<stdio.h>
2
3
intmain(void)
4
{
5
floatAnfangszahl=0;
6
floatZahl=0;
7
charOperator;
8
9
printf("Anfangszahl eingeben");
10
scanf("%f",&Anfangszahl);
11
printf("= %f",Anfangszahl);
12
scanf("%c%f",&Operator,&Zahl);
13
14
printf("Operator:%c Zahl:%f",Operator,Zahl);
15
system("pause");
16
return0;
17
}
Woran liegt es, dass bei "Operator" nichts ausgegeben wird und die
Variable "Zahl" in der printf-Anweisung richtig ausgegeben wird?
Können mit scanf die beiden Parameter doch nicht einfach hintereinander
eingelesen werden?!
Danke!
Tja, wenn du wenigstens den Rückgabewert von scanf()
prüfen würdest, wüsstest du, ob das Einlesen überhaupt
geklappt hat.
Außerdem kann man ein char auch mit %d ausgeben und sieht dann
den ASCII-Code; das hilft bei komischen Werten mehr
(Steuerzeichen, Leerzeichen etc..
Das Verhalten hängt natürlich auch von deiner Eingabe ab, die
hier niemand sieht.
der_lord schrieb:
> Woran liegt es, dass bei "Operator" nichts ausgegeben wird
Doch.
Es wird etwas ausgegeben :-)
Dieser
scanf("%c%f",&Operator,&Zahl);
schnappt sich für Operator den Return, der beim vorhergehenden scanf
übrig geblieben ist :-)
Dass deine Zahl trotzdem richtig kommt, liegt daran, dass du
wahrscheinlich irgendwas in der Art "+67" eingibst. Und ein + ist ein
gültiger Anfang für eine Zahl. Gib als Antwort auf den 2.ten scanf mal
"*8" ein und du wirst sehen, dass Zahl nicht deiner Eingabe entspricht.
Vielleicht verstehst du jetzt langsam, warum robuste Eingabe praktisch
immer über den Weg fgets/sscanf führt :-)
Aber probiers mal so:
printf("Anfangszahl eingeben");
scanf("%f",&Anfangszahl);
printf("= %f",Anfangszahl);
scanf("\n%c%f",&Operator,&Zahl);
Hier wird dem 2.ten scanf aufgetragen, den \n der noch in der Eingabe
auf bBearbeitung wartet, einfach zu überlesen.
Schwer jetzt darauf was zu schreiben...
Ich weiß ehrlichgesagt nicht, wie ich dann mit dieser scanf-Anweisung
beide Werte "richtig" entgegennehmen lassen kann.
Ich gebe jetzt folgendes ein:
So sieht nun meine Ausgabe aus, wenn ich den Platzhalter %c mit %d
ersetze:
Hallo Leute!
Also ich habs jetzt soweit geschafft, allerdings springt er mir noch
nicht aus der Schleife, sobald ich ein "=" eingebe....
Woran liegt das? Die Ausführ-Bedingung für die Schleife ist doch,
solange die Eingabe ungleich "=" ist.Oder?
Hier mein Code:
Diese Zeile erfordert zwei Eingaben, d.h. nur mit dem '=' wird scanf
noch nicht beendet.
scanf("\n%c%f",&Operator,&Zahl);
Gib einfach mal "= 0" ein anstatt nur '='.