C: Scanf ignoriert Eingabe & benutzt Wert aus einer anderen Funktion
-
Hallo zusammen!
Ich versuche mich gerade an der einfach verketteten Liste, was bis zum Werteeintragen und -ausgeben auch wunderbar funktioniert. Nun möchte ich eine Funktion ' loeschen' hinzufügen, die den Inhalt (ein int-Wert) eines beliebigen Knotens löscht. Dazu soll ein int-Wert eingegeben, nacheinander mit den int-Werten der Liste verglichen und dann bei Übereinstimmung gelöscht werden.
Dabei stehe ich vor folgendem Problem: Aus dem (aufs Nötige reduzierten) Hauptprogramm heraus möchte ich also zwei verschiedene Unterprogramme ('einfuegen' und 'loeschen') aufrufen, in denen an jeweils einer Stelle int-Werte mittels scanf eingelesen werden sollen. In der ersten Funktion 'eingeben' (erstellt eine Liste aus Zahlen) funktioniert das auch. In der zweiten Funktion 'loeschen' wird aber beim Programmlauf das Einlesen (scanf("%i"),&kill) einfach übergangen und stattdessen die einzulesende Variable 'kill' mit dem zuletzt in die Liste eingetragenen Wert belegt.
(So könnte man zwar immer den zuletzt eingetragenen Wert löschen, jedoch entsteht bei mehrfachem Aufruf der Funktion eine Endlosschleife; zudem soll ja ein beliebiger Wert gelöscht werden können.)
Da die Funktionen keine Werte zurückliefern sollen, sind es "void"-Funktionen - trotzdem wird ein Wert aus der einen Funktion in der anderen weiterverwendet. Woran kann das liegen?Bei der Fehlersuche bin ich soweit gekommen:
Eingaben für die Liste werden in der ersten Fkt. jeweils unter '(*neuerKnoten).ziffer' abgelegt. Der Zeiger 'neuerKnoten' ist als globale Variable definiert, deshalb ist auch der Wert '(*neuerKnoten).ziffer' global - d.h. ja, in allen Funktionen- verfügbar. Aber wie genau und warum legt das Programm diesen Wert in 'kill' ab und übergeht deswegen gleichzeitig 'scanf("%i", &kill);'?Meine bisherigen Lösungsversuche: Google/Foren durchsucht nach Unterprogramm/Funktion/Werteübergabe u. ä., Bücher ("C" von Prinz/Kirch-Prinz,"Moderne C-Programmierung" von Schellong, "Programmieren lernen mit C" von Zeiner), Uni-Skript, C-Referenzen, Tutorials (Galileo Computing u. ä.) gelesen, andere Variablen-Typen ausprobiert (z. B. mit 'char'), Fehlerstelle im Code so weit möglich isoliert, Funktionstypen variiert und '0' zurückgegeben, Reihenfolge der Funktionen im Code verändert... ich beiße mir da seit Tagen die Zähne dran aus...
Kann mir jemand einen Hinweis geben, wie ich 'kill' mit dem jeweils neu einzutragenden Wert belegen kann?
Für Hilfe bin ich ohne Ende dankbar!
Grüße, Martin
Hier der Quellcode:
------------------------------------------#include<stdio.h>
#include<stdio.h>typedef struct knoten{
int ziffer;
struct knoten *next;
}knoten;struct knoten* anfang = 0;
struct knoten* ende = 0;
struct knoten* neuerKnoten;void eingeben(){
int eingabe;
printf("\n\nBitte Zahlen fuer die Liste eingeben, jeweils mit Enter bestaetigen und\nmit 'eof' beenden: \n");
while(scanf("%i",&eingabe) !=0){
neuerKnoten = malloc(sizeof(struct knoten));
(*neuerKnoten).ziffer = eingabe;
(*neuerKnoten).next = 0;if(anfang == 0){
anfang = neuerKnoten;
} /* Ende if */
else{
(*ende).next = neuerKnoten;
} /* Ende else */
ende = neuerKnoten;
} /* Ende while */} /* Ende Funktion eingeben */
void loeschen(){
int kill;printf("\n\n\nWelche Ziffer wollen Sie loeschen?\n");
scanf("%i", &kill);
printf("eingegeben: %i", kill);
/* hierhin soll die eigentliche Funktion:
die eingegebene Zahl 'kill' wird der
Reihe nach mit den Zahlen '*.ziffer'
aus der Liste verglichen und bei
Übereinstimmung gelöscht */} /* Ende Funktion loeschen */
int main(void){
eingeben();
loeschen();printf("\n\nBitte eine beliebige Taste druecken, um das Programm zu beenden.");
getch();
return 0;
}
-
Verwende für den Quellcode bitte die cpp-Tags, das sieht dann im Ergebnis so aus:
#include<stdio.h> typedef struct knoten{ int ziffer; struct knoten *next; }knoten; struct knoten* anfang = 0; struct knoten* ende = 0; struct knoten* neuerKnoten; void eingeben(){ int eingabe; printf("\n\nBitte Zahlen fuer die Liste eingeben, jeweils mit Enter bestaetigen und\nmit 'eof' beenden: \n"); while(scanf("%i",&eingabe) !=0){ neuerKnoten = malloc(sizeof(struct knoten)); (*neuerKnoten).ziffer = eingabe; (*neuerKnoten).next = 0; if(anfang == 0){ anfang = neuerKnoten; } /* Ende if */ else{ (*ende).next = neuerKnoten; } /* Ende else */ ende = neuerKnoten; } /* Ende while */ } /* Ende Funktion eingeben */ void loeschen(){ int kill; printf("\n\n\nWelche Ziffer wollen Sie loeschen?\n"); scanf("%i", &kill); printf("eingegeben: %i", kill); /* hierhin soll die eigentliche Funktion: die eingegebene Zahl 'kill' wird der Reihe nach mit den Zahlen '*.ziffer' aus der Liste verglichen und bei Übereinstimmung gelöscht */ } /* Ende Funktion loeschen */ int main(void){ eingeben(); loeschen(); printf("\n\nBitte eine beliebige Taste druecken, um das Programm zu beenden."); getch(); return 0; }2.: wieso hast du 2 mal hintereinander stdio.h inkludiert ? O.o
-
typisch scanf:
http://www.win-tux.de/c_005_001.htmMfG f.-th.
-
@DrakoXP:
War mein erster Beitrag in einem Forum überhaupt - sorry für das Format, werde in Zukunft die cpp-Tags verwenden. Was das doppelte Inkluden der stdio.h angeht: Eins davon sollte stdlib.h sein (für 'malloc'), der Fehler ist mir wohl beim Kopieren und Pasten unterlaufen.
@f.-th.:
Vielen Dank für den Link! Die mir bis hierhin unbekannte Funktion fflush(stdin) zum Entleeren des Tastaturpuffers ist ja theoretisch die Lösung des Problems. Ich programmiere unter XP mit der Umgebung Dev-C++, mal schauen, ob es unter den Voraussetzungen klappt. Ich sag dann später Bescheid.
Danke nochmal und Grüße
-
Ergebnis:
Eine Tastaturpufferentleerung unmittelbar nach 'scanf' (nach Zeile 15), wie sie im verlinkten Beispiel http://www.win-tux.de/c_005_001.htm angegeben ist, verändert nichts, ebensowenig wie eine Plazierung von 'fflush(stdin)' unmittelbar nach dem Ablegen des jeweiligen int-Werts in '(*neuerKnoten).ziffer' (nach Zeile 17).Es hat aber geholfen, 'fflush(stdin)' direkt vor dem 'scanf' in der Funktion 'loeschen' anzubringen, den Tastaturpuffer also direkt vor der erneuten Eingabe eines Wertes (entspricht im Programmlauf der Stelle, wo ich eine Eingabeaufforderung erwartet hatte, aber keine angeboten wurde) zu leeren. fflush() muss hier also nach Zeile 34 kommen. Es funktioniert!
In diesem Sinne: Vielen herzlichen Dank, f.-th.!
und Grüße, Martin
anbei der funktionierende Code:
-----------------------------#include<stdio.h> #include<stdlib.h> typedef struct knoten{ int ziffer; struct knoten *next; }knoten; struct knoten* anfang = 0; struct knoten* ende = 0; struct knoten* neuerKnoten; void eingeben(){ int eingabe; printf("\n\nBitte Zahlen fuer die Liste eingeben, jeweils mit Enter bestaetigen und\nmit 'eof' beenden: \n"); while(scanf("%i",&eingabe) !=0){ neuerKnoten = malloc(sizeof(struct knoten)); (*neuerKnoten).ziffer = eingabe; (*neuerKnoten).next = 0; if(anfang == 0){ anfang = neuerKnoten; } /* Ende if */ else{ (*ende).next = neuerKnoten; } /* Ende else */ ende = neuerKnoten; } /* Ende while */ } /* Ende Funktion eingeben */ void loeschen(){ int kill; printf("\n\n\nWelche Ziffer wollen Sie loeschen?\n"); fflush(stdin); scanf("%i", &kill); printf("eingegeben: %i", kill); /* hierhin soll die eigentliche Funktion: die eingegebene Zahl 'kill' wird der Reihe nach mit den Zahlen '*.ziffer' aus der Liste verglichen und bei Übereinstimmung gelöscht */ } /* Ende Funktion loeschen */ int main(void){ eingeben(); loeschen(); printf("\n\nBitte eine beliebige Taste druecken, um das Programm zu beenden."); getch(); return 0; }
-
Sorry, die Zeilenangaben eben bezogen sich auf den Beitrag von DrakoXP - im letzten Beitrag haben sich die Zeilen verschoben, fflush() muss vor Zeile 39 plaziert werden, siehe Code.
Grüße