rekursive Methode: scanf() macht was es will...



  • Hi,

    Ich habe ein kleines Programm zu schreiben (Uni) und alle Funktionen laufen.
    Alle? Nein. Alle bis auf meine "GUI".
    Allgemeines:
    -~1700 Postbezirke (Koordinatensystem 2D)
    - ich gebe einen Bezirk an und suche den nächsten nachbarn
    - ich reise() durch 20 Bezirke (Zufall) und starte bei einem bestimmten..

    zu meinem Problem:
    Ich frage in der rekursiven Methode eingabePruefen(), was der Benutzer eingeben hat bzw. was gemacht werden soll. Und verarbeite die Eingabe über switch().
    Beim ersten Aufruf funktioniert noch alles ganz normal:
    Die aufgeforderte Funktion wird aufgerufen und verrichtet ihren Dienst.
    Über das Break "springts" raus und die Methode ruft sich selber auf.
    Dann kommt das was ich nicht so ganz verstehe:
    Es überspringt scheinbar die scanf() Funktion und gibt direkt das unter default stehende raus.

    Was ich aber gar nicht verstehe:
    gibt man 'n' ein, so wird eine Funktion aufgerufen, welche auch ein scanf() verwendet. Dort "schalten sich" meine "Sicherungen" (im Sinne von falsche Eingabe) direkt ein (OHNE gewartet zu haben, was der Benutzer denn eingibt) und ich fliege raus (return 0;) Rufe ich die Funktion normal in der main() auf, gibts keine Probleme. Bei reise() und abfragen() nicht.....-.-
    Ich finde das Problem nicht.... 😕

    Was muss ich verändern, damit ich sicher gehen kann, dass scanf() auch funktioniert/wartet...?

    Danke schonmal 🙂

    Hier die eingabe Prüfen Methode:

    void eingabePruefen(int p){
    	char ein = '?';
    	int t = 1;
    	if(p){
    			p = 0;
    			printf("Ihre Eingabe, bitte: ");
    	}else{
    			printf("\nBitte waehlen sie erneut: ");
    	}
    	scanf("%c",&ein);
    	// Was hat der User eingegeben?
    
    			switch(ein){
    				case 'n':
    				case 'N':	if(abfragen() == 0)				// Gab es einen Fehler beim Abfragen nach einem Bezirk um den naechsten Nachbar zu finden
    								printf("\nEs gab einen Fehler beim Ermitteln des Startbezirkes.");
    							break;
    				case 'r':
    				case 'R':	if(reise() == 0)				//"Rundreise"
    								printf("\nEs gab einen Fehler beim Ermitteln des Startbezirkes.");
    							break;
    				case 'e':									// Beenden des Programms (algebraischer Bool-Wert [t])
    				case 'E':	printf("Auf Wiedersehen! \n\n");
    							t = 0;
    							break;
    				case '?':   printf("es gibt folgende Programmfunktion:\n"); // Bedienelemente erneut einblenden
    							printf("-  'n': Berechnung der/des naechsten Nachbars/n eines Bezirkes Ihrer Wahl\n");
    							printf("-  'r': Berechnung einer Route ueber den jeweils naechsten Nachbarn startend mit\n \tdem Bezirk M1_2EA\n");
    							printf("-  'e': Beenden des Programmes\n");
    							printf("-  '?': Funktionen erneut zeigen\n\n");
    							break;		
    				default:	printf("\nIhre Eingabe war leider inkorrekt."); // "falsche" Eingabe
    			}
    	if(t) eingabePruefen(0);
    }
    

    Dann habe ich noch die abfrage() Funktion, da die reise() Funktion sicher läuft

    int abfragen(){
    	char eingabe[10];
    	int index = 0;
    	char c = 'e';
    	printf("Moechten sie den Bezirk nach einem Namen oder einem Index auswaehlen? (N/I)");
    	scanf("%c",&c);
    		if(c == 'N' || c == 'n'){													// Eingabe nach Name
    			printf("Bitte geben Sie den Namen des Bezirks ein, von welchem der 'naechste Nachbar' gesucht werden soll: ");
    			scanf("%s",&eingabe);
    			int b = 1;																// "boolscher" Integer Wert
    			do{
    				if(strcmp(postbezirke[index], eingabe) == 0 )						// Suche nach dem Index des Bezirkes - strcmp() vergleicht zwei Strings...
    					b = 0;															// ...sind sie identisch setzt es den algebraischen Bool-Wert auf "false" -> Schleife bricht ab
    				else
    					index++;
    			}while(b && index < 1726);
    
    			if(b)   return 0;														// Bezirk existiert nicht
    		}else if(c == 'I' || c == 'i'){												// Eingabe nach Index
    			printf("Bitte geben Sie den Index des Bezirks ein, von welchem der 'naechste Nachbar' gesucht werden soll: ");
    			scanf("%i", &index);
    		}else{
    			printf("Ihre Eingabe war inkorrekt.");
    			return 0;
    		}
    		int temp[] = {index};
    	naechstenNachbarSuchen(1, temp);
    	return 1;
    }
    


  • Das Problem ist das die Entertaste auch als Zeichen gilt und eingelesen wird. Schreib also zb.

    scanf("%c%c",&c);
    

    , dann wird das "Enter" durch das zweite %c abgefangen.



  • Gnoeg schrieb:

    Das Problem ist das die Entertaste auch als Zeichen gilt und eingelesen wird. Schreib also zb.

    scanf("%c%c",&c);
    

    , dann wird das "Enter" durch das zweite %c abgefangen.

    Das ist falsch. wo soll denn das zweite Zeichen gespeichert werden?

    Setze vor das %c noch ein Leerzeichen. Dies veranlasst scanf dazu Whitespace zu überlesen.

    scanf("%c",&c);
    

    Die Rekursion der Eingabe ist eine schlechte Idee.
    Wenn du nochmal die Eingabe machen willst, dann mach eine Schleife (do-while) darum.

    Dein Problem mit abfragen() konnte ich noch nicht ganz verstehen, liegt evtl aber auch an der Entertaste.
    Ein paar Sachen sind mir aber aufgefallen:
    Bei scanf("%s",&eingabe); ist das & zuviel.
    Zudem solltest du die Länge des Arrays mit angeben:

    scanf("%9s",&eingabe);
    

    Was macht eigentlich: int temp[] = {index}; (Zeile 26 in abfrage)



  • DirkB schrieb:

    Das ist falsch. wo soll denn das zweite Zeichen gespeichert werden?

    Ich will ja das "Enter" nicht speichern. Es funktioniert, denn wenn scanf zu dem zweiten %c kein Parameter findet, überliest es das zweite Zeichen(das Line Feed) einfach.



  • Quatsch.
    scanf weiß zur Laufzeit wegen der variablen Parameterliste nicht, wieviele Argumente du übergeben hast und greift für das zweite %c auf undefinierten Speicher (auch noch schreibend) zu, und das ist undefiniertes Verhalten.
    Wenn, dann %c%*c aber auch das ist wie die " %c" Unsinn, da der Anwender einfach 2 Nicht-Whitespaces eingeben kann und dann läuft dein Programm Amok.
    Was du 'willst' oder nicht willst, ist dem Compiler egal, der produziert Code, der sich an Regeln hält und dabei wird eben nichts 'überlesen'.



  • DirkB schrieb:

    Gnoeg schrieb:

    Das Problem ist das die Entertaste auch als Zeichen gilt und eingelesen wird. Schreib also zb.

    scanf("%c%c",&c);
    

    , dann wird das "Enter" durch das zweite %c abgefangen.

    Das ist falsch. wo soll denn das zweite Zeichen gespeichert werden?

    Setze vor das %c noch ein Leerzeichen. Dies veranlasst scanf dazu Whitespace zu überlesen.

    scanf("%c",&c);
    

    Die Rekursion der Eingabe ist eine schlechte Idee.
    Wenn du nochmal die Eingabe machen willst, dann mach eine Schleife (do-while) darum.

    Dein Problem mit abfragen() konnte ich noch nicht ganz verstehen, liegt evtl aber auch an der Entertaste.
    Ein paar Sachen sind mir aber aufgefallen:
    Bei scanf("%s",&eingabe); ist das & zuviel.
    Zudem solltest du die Länge des Arrays mit angeben:

    scanf("%9s",&eingabe);
    

    Was macht eigentlich: int temp[] = {index}; (Zeile 26 in abfrage)

    ich habe sie jetzt in eine do-while gepackt:

    void eingabePruefen(){
    	char ein = '?';
    	printf("Ihre Eingabe, bitte: ");
    
    	int t = 1;
    	do{
    
    			scanf("%c",&ein);
    			// Was hat der User eingegeben?
    
    			switch(ein){
    				case 'n':
    				case 'N':	if(abfragen() == 0)				// Gab es einen Fehler beim Abfragen nach einem Bezirk um den naechsten Nachbar zu finden
    								printf("\nEs gab einen Fehler beim Ermitteln des Startbezirkes.");
    							break;
    				case 'r':
    				case 'R':	if(reise() == 0)				//"Rundreise"
    								printf("\nEs gab einen Fehler beim Ermitteln des Startbezirkes.");
    							break;
    				case 'e':									// Beenden des Programms (algebraischer Bool-Wert [t])
    				case 'E':	printf("Auf Wiedersehen! \n\n");
    							t = 0;
    							break;
    				case '?':   printf("es gibt folgende Programmfunktion:\n"); // Bedienelemente erneut einblenden
    							printf("-  'n': Berechnung der/des naechsten Nachbars/n eines Bezirkes Ihrer Wahl\n");
    							printf("-  'r': Berechnung einer Route ueber den jeweils naechsten Nachbarn startend mit\n \tdem Bezirk M1_2EA\n");
    							printf("-  'e': Beenden des Programmes\n");
    							printf("-  '?': Funktionen erneut zeigen\n\n");
    							break;		
    				default:	printf("\nIhre Eingabe war leider inkorrekt."); // "falsche" Eingabe
    			}
    		printf("\nBitte waehlen sie erneut: ");
    	}while(t);
    }
    

    int temp[] = {index};
    benutze ich, da ich nur eine Funktion [naechstenNachbarSuchen(int, int[])] haben soll um einmal einen und einmal die "Strecke" zu berechnen. Damit ich es einfacher handhaben kann über gebe ich es bei einem einzelnen ebenfalls als Array.

    bei abfragen habe ich es jetzt auch so gehandhabt:

    scanf("%9s",eingabe);
    

    Mein Problem bei abfragen():
    Ich wähle 'n' und drücke Enter. Es erscheint der Code aus

    printf("Moechten sie den Bezirk nach einem Namen oder einem Index auswaehlen? (N/I)");
    

    JETZT sollte die Eingabe erfolgen, aber er "überspringt" es und gibt direkt

    printf("Ihre Eingabe war inkorrekt.");
    

    aus.

    Dann endet die Funktion durch

    return 0;
    

    Als nächstes kommt logischerweise der Code von

    case 'n':
    				case 'N':	if(abfragen() == 0)				// Gab es einen Fehler beim Abfragen nach einem Bezirk um den naechsten Nachbar zu finden
    								printf("\nEs gab einen Fehler beim Ermitteln des Startbezirkes.");
    							break;
    

    screenshot:
    http://s7.directupload.net/file/d/3049/t48u82ge_png.htm
    // ich wusste nicht wie ich einen Anhang hinzufüge .....-.-

    bei der Eingabe r geschiet dies:
    http://s7.directupload.net/file/d/3049/rk77pfx6_png.htm

    PS: Warum kann/muss ich hier das & bei scanf() weglassen?

    Edit: Methode doppelt eingefügt.



  • müll das forum nicht zu -> reduziere die beispiele zu deinen fragen auf ein minimum



  • saubermann schrieb:

    müll das forum nicht zu -> reduziere die beispiele zu deinen fragen auf ein minimum

    3 Fragen:
    Wo sind Beispiele?
    Was sollte ich deiner Meinung nach weglassen?
    Hast du auch was konstruktives zu dem Thema? [z.B. die/eine Lösung]



  • Hast du das Leerzeichen vor das %c bei scanf gemacht?
    Ein

    scanf(" %c",&c);
    

    Überall da, wo du keine Whitespace (Leerzeichen,Tabulatoren und Entertasten) haben willst) einlesen willst?

    Und wegen int temp[] = {index}; solltest du dich mal mehr bei Arrays und Zeigern einlesen.
    Ein

    naechstenNachbarSuchen(1, &index);
    

    tut es da auch.



  • DirkB schrieb:

    Hast du das Leerzeichen vor das %c bei scanf gemacht?
    Ein

    scanf(" %c",&c);
    

    Überall da, wo du keine Whitespace (Leerzeichen,Tabulatoren und Entertasten) haben willst) einlesen willst?

    Und wegen int temp[] = {index}; solltest du dich mal mehr bei Arrays und Zeigern einlesen.
    Ein

    naechstenNachbarSuchen(1, &index);
    

    tut es da auch.

    This is it!
    doofes Whitespace^^

    kleine Rechtfertigung meinerseits:
    Ich "komme" Java... Da gibt's sowas 'Kompliziertes' nicht^^ der überliest das einfach immer 😉

    Und daher kenne ich das mit dem & auch nicht - also wann ich es brauche und wann nicht...

    Ich danke euch 😃


Anmelden zum Antworten