Menü in der Kommandozeile bauen



  • Hallo,

    ich habe mir das so vorgestellt:

    #include <stdio.h>
    #include <stdlib.h>
    
    void print_menu(int option)
    {
    	switch(option)
    	{
    		case 1: {
    			printf("- Menuepunkt 1\n");
    			printf("  Menuepunkt 2\n");
    			break;
    		}
    		case 2: {
    			printf("  Menuepunkt 1\n");
    			printf("- Menuepunkt 2\n");
    			break;
    		}
    	}
    }
    
    int main()
    {
    	// anfangszustand
    	print_menu(1); // erste option ist angewählt
    	unsigned char c=0;
    	while(c != 'e') // 'e' bedeutet, dass menü verlassen werden soll
    	{
    		c=getch();
    		if( c == '1') {
    			system("cls"); // nur unter windows, unter linux: "clear"
    			print_menu(1);
    		} else if( c == '2') {
    			system("cls");
    			print_menu(2);
    		} else {
    			continue;
    		}
    	}
    	return 0;
    }
    

    das alles funktioniert auch ganz gut... aber ich nehme an, da gibts eine bessere lösung?

    lg


  • Mod

    shelll schrieb:

    das alles funktioniert auch ganz gut... aber ich nehme an, da gibts eine bessere lösung?

    Ja. Das Design ist hochgradig unflexibel. Stell dir vor, du wolltest irgendetwas ändern, zum Beispiel einen Punkt hinzufügen -> Änderungen an vielen Stellen im Programm verteilt. Und wehe, an einer Stelle macht man einen Fehler, vergisst etwas, oder die Änderungen passen nicht zusammen 👎

    Mit einem objektorientierten Ansatz ginge das viel schöner, deshalb ist auch nahezu jedes GUI-Framework objektorientiert aufgebaut*. Du registrierst die Menüpunkte bei der Menüdatenstruktur, die dann die Darstellung und Benutzerführung übernimmt. Vielleicht sogar mit Callbacks für die gewählten Menüpunkte.

    Aber vermutlich verstehst du gerade nur noch Bahnhof, schon seit ich "objektorientiert" gesagt habe, oder? Falls ja, dann ist erst einmal das Sammeln von mehr Erfahrung angesagt, wie man überhaupt objektorientiert denkt und wie man diese Denkweise in C umsetzt. Eine Menüführung ist da schon ein etwas fortgeschritteneres Beispiel, das eignet sich nicht unbedingt als Übungsobjekt für absolute Anfänger, die wohl eher mit einfachen Datenstrukturen (dynamische Arrays, Baumstrukturen) anfangen sollten, da man dazu mehr Lehrmaterial findet.

    Falls ich heute Abend Zeit habe (leider eher unwahrscheinlich), könnte ich ein großes Beispiel machen, wie ich mir das vorstelle.

    *: Dies ist übrigens ein Hinweis auf eine andere Art von besserer Lösung: Nimm was fertiges 🙂 .



  • Ein Beispiel wäre echt gut! Würde mich freuen!

    P.S.: Warum gibts "getch()" eigentlich unter Linux nicht?


  • Mod

    shelll schrieb:

    P.S.: Warum gibts "getch()" eigentlich unter Linux nicht?

    Gibt es doch. Das ist, genauso wie in Windows (conio), in einer uralten Konsolenbibliothek (ncurses).



  • #include <stdio.h>
    
    typedef void (*MenuCallback)();
    
    void Optionen_Sound()
    {
    	printf("Soundeinstellungen...\n");
    }
    
    void Optionen_Grafik()
    {
    	printf("Grafikeinstellungen...\n");
    }
    
    void Optionen()
    {
    	const char *menu[] = {"Sound", "Grafik"};
    
    	MenuCallback callbacks[] = {&Optionen_Sound, &Optionen_Grafik};
    
    	int selection = PrintMenu("Einstellungen", menu, 2);
    
    	callbacks[selection]();
    }
    
    void Credits()
    {
    	printf("Copyright by ...\n");
    }
    
    int PrintMenu(const char *header, const char *menu[], int count)
    {
    	int i;
    
    	printf("- %s -\n", header);
    
    	for (i = 0; i < count; ++i)
    	{
    		printf("* %s\n", menu[i]);
    	}
    
    	do
    	{
    		printf("\nIhre Auswahl: ");
    		scanf("%d", &i);
    	} while (i < 1 || i > count);
    
    	--i;
    
    	printf("\n");
    
    	return i;
    }
    
    int main()
    {
    	const char *menu[] = {"Optionen", "Credits"};
    
    	MenuCallback callbacks[] = {&Optionen, &Credits};
    
    	int selection = PrintMenu("Hauptmenu", menu, sizeof(menu) / sizeof(*menu));
    
    	callbacks[selection]();
    
    	return 0;
    }
    

    Das kann man noch massiv erweitern und vereinfachen. Mit einem Zeiger auf das vorherige Menü, etc...



  • Danke, aber eigentlich Wollte ich ein Menü, dass mit den Pfeiltasten gesteuert wird, also über unbuffered input...

    also so:

    --- Hauptmenü ---
    [*] Menüpunkt 1
    [ ] Menüpunkt 2
    

    Wenn man einmal die pfeil-runter-taste drückt, soll das ganze so aussehen:

    --- Hauptmenü ---
    [ ] Menüpunkt 1
    [*] Menüpunkt 2
    

    trotzdem danke...


  • Mod

    shelll schrieb:

    Danke, aber eigentlich Wollte ich ein Menü, dass mit den Pfeiltasten gesteuert wird, also über unbuffered input...

    Das ist doch bloß eine Detailfrage. Wichtig ist doch die Programmstruktur, die dir durch das Beispiel gezeigt werden sollte (und die man tatsächlich noch massiv vereinfachen könnte, aber es ist ein guter Anfang). Wie du da konkret die Steuerung und die Anzeige programmierst, bleibt dir überlassen.

    Wenn du beim Beispiel etwas an der Menüstruktur selber ändern möchtest, dann brauchst du bloß die Zeilen 57 und 59 ändern. In den Programmcode des Menüs brauchst du gar nicht rein, du gibst den Funktionen bloß andere Daten. Bei dir hingegen war das noch ganz anders, da waren die Daten über die Struktur fest in die Menüfunktionen eingebaut und verteilt.



  • eine Sache noch: was ist der ASCII-Code für die Pfeiltasten?

    Ich finde über Google zu diesem Thema nur scheiße... weißt du zufällig die 4 Werte? und sind das unter Linux und Windows diesselben?



  • shelll schrieb:

    Danke, aber eigentlich Wollte ich ein Menü, dass mit den Pfeiltasten gesteuert wird, also über unbuffered input...

    also so:

    --- Hauptmenü ---
    [*] Menüpunkt 1
    [ ] Menüpunkt 2
    

    Wenn man einmal die pfeil-runter-taste drückt, soll das ganze so aussehen:

    --- Hauptmenü ---
    [ ] Menüpunkt 1
    [*] Menüpunkt 2
    

    trotzdem danke...

    http://www.c-plusplus.net/forum/303169-full

    Edit: verdammt, c++, aber der ansatz stimmt.


  • Mod

    shelll schrieb:

    eine Sache noch: was ist der ASCII-Code für die Pfeiltasten?

    Gar keine.

    Lern lieber erst einmal die grundlegenden Programmstrukturen, bevor du dir über so etwas Gedanken machst. Wenn du erst einmal weißt, was du tust, dann findest du das ganz einfach selber raus. Wenn ich es dir jetzt einfach sage, verstehst du es sowieso nicht richtig und kannst es nicht selbstständig anwenden.


Anmelden zum Antworten