[C++] Przekazywanie sterowania


(Krzychu224) #1

Piszę program obiektowo w C++ w którym mam klasę, której funkcje wyświetlają poszczególne Menu w programie (całość jest pod konsolę).

Wywołuję funkcję obiektu z funkcji main()

obiekt_w_ktorym_są_funkcje_wyswietlające_menu.WyswietlMenuG();

Poruszanie się po menu jest zrobione w pętli while(1) - pobieram znak z klawiatury i odpowiednia opcja jest podświetlana. Gdy ktoś wciśnie enter funkcja MenuGlowne odpalana inna funkcje (np. WyswietlMenuP())

Gdy użytkownik wybierze już wszystkie parametry, chciałbym żeby sterowanie wróciło do funkcji main() i jedna ze zmiennych z obiektu została przekazana do konstruktora innego obiektu.

Czy ktoś wie jak to zrobić?


(Bkcotm) #2

Robisz break i wychodzisz z tej pętli do main().

Ale przydałoby się więcej info, jakiś kod etc.


([alex]) #3
#include 

using namespace std;


struct Menu;

void submenu(const Menu*);

void crt(const Menu*) { cout<<"Create something"<
void add(const Menu*) { cout<<"Add something"<
void del(const Menu*) { cout<<"Delete something"<
void rptvert(const Menu*) { cout<<"Show verticaly"<
void rpthorz(const Menu*) { cout<<"Show horizontaly"<
void load(const Menu*) { cout<<"Load from file"<
void save(const Menu*) { cout<<"Save to file"<

const struct Menu { const char *text; void (*fun)(const Menu*); const Menu *sub; }

  RptMenu[]=

    {

     {"Pionowo",rptvert},

     {"Poziomo",rpthorz},

     {"Wroc"},

    },

  MainMenu[]=

    {

     {"Nowy",crt},

     {"Dodaj",add},

     {"Usun",del},

     {"Pokaz (sub)",submenu,RptMenu},

     {"Wczytaj z pliku",load},

     {"Zapisz do pliku",save},

     {"Koniec"},

    }

  ;


void submenu(const Menu *menu)

  {

   cout<
   while(true)

     {

      cin.sync();

      unsigned n=0;

      const Menu *tmp=menu;

      while(tmp->fun) cout<<(++n)<<": "<<(tmp++)->text<
      cout<<"0: "<text<
      unsigned m;

      if((cin>>m)&&(m<=n))

        {

         if(!m) break;

         const Menu *tmp=menu+m-1;

         tmp->fun(tmp->sub);

        }

      else

        {

         cin.clear();

         cout<<"Nie ma takiej opcji"<
        }

     }

   cout<
  }


int main()

  {

   submenu(MainMenu);

   return 0;

  }

Obczaj to - bardzo łatwo się przerabia na klasy.


(Krzychu224) #4

Tylko program będzie już w innej pętli bo z funkcji wyświetlającej jedno menu jest wywołanie innych

Kod:

Funkcja main:

int _tmain(int argc, _TCHAR* argv[])

{


	MenuGlowne tytan;

	tytan.WyswietlG();


	return 0;

}

Funkcja WyswietlG:

void MenuGlowne::WyswietlG(void)

{

	while(1)

	{

		bialy();

		system("cls");

		printf("\t\t SSSS kk\n");

		printf("\t\t SS SS kk\n");

		printf("\t\t SS SS kk\n");

		printf("\t\t SS nnnnn aaaa kk kk eeee\n");

		printf("\t\t SSS nn nn aa aa kk kk ee ee\n");

		printf("\t\t SSS nn nn aaaa kkkk eeeeee\n");

		printf("\t\t SS nn nn aa aa kkk ee\n");

		printf("\t\t SS SS nn nn aa aa kkkk ee\n");

		printf("\t\t SS SS nn nn aa aa kk kk ee ee\n");

		printf("\t\t SSSSS nn nn aaaaa kk kk eeee\n\n\n");	



		if(m==1){magnetowy();}printf("\t\t\t\t ROZPOCZNIJ GRE \n");bialy();

	    if(m==2){magnetowy();}printf("\t\t\t\t MENU OPCJI \n");bialy();

	    if(m==3){magnetowy();}printf("\t\t\t\t WYJSCIE \n");bialy();

		z = _getch();


		if(z == 72){m--;}

		if(m == 0){m =+ 3;}

		if(z == 80){if(m<3){m++;}} // Ograniczenie z dołu


		if((z == 13) && (m == 3)) exit(0); // Wyjście z programu

// if((z == 13) && (m == 2)) Opcje(); // Menu opcji

		if((z == 13) && (m == 1)) WyswietlP(); // Wyswietlenie menu wyboru poziomu trudnosci

	}



}

Dzięki, jutro jak będę miał jaśniejszy umysł to obczaję:slight_smile: -- Dodane 14.06.2012 (Cz) 15:42 -- Staram się zrobić to tak jak pokazał alex ale mam pewne problemy z konstruktorem klasy Klasa:

class MenuR

{


private:

	const char *text; 

	void (*fun)(const MenuR*); 

	const MenuR *sub;


public:


	void WyswietlMenu(const MenuR *menu);

	MenuR(void);

	MenuR(const char, const MenuR);

	~MenuR(void);

};

Konstruktor: Znakami zapytania zaznaczyłem miejsce w którym nie wiem jaki typ danych wpisać. Nie bardzo wiem o co chodzi z tymi dwoma nawiasami obok siebie

MenuR::MenuR(const char *tekst, ??????, MenuR *nastepne_menu)

{

	const char *text=tekst; 

//	void (*fun)(const MenuR*)= funkcja; 

	const MenuR *sub = nastepne_menu;


}

(Bkcotm) #5

Tak czy inaczej, jeżeli chcesz robić tego typu program-grę, na pewno będziesz miał jedną główną pętlę w main() (tzw. pętla czasu rzeczywistego), w której będą kręciły się inne pętle:

void main()

{

   while(true) // pętla czasu rzeczywistego

   {

      Ustawienia ustawienia = PetlaMenu();

      PetlaGry(ustawienia);    

   }

}


Ustawienia PetlaMenu()

{

   while(czySkonczonoUstawienia)

   {

      //pętla w której użytkownik sobie ustawia różne rzeczy,

      //które przypisujesz do obiektu klasy Ustawienia

   }

}


void PetlaGry(Ustawienia ustawienia)

{

   while(czyGraSkonczona)

   {

       //pętla w której grasz, korzystając z ustawień

   }  

}

([alex]) #6

ThaRealiestJEDI, mylisz Menu z MenuItem - w moim kodzie struktura Menu to element menu, dopiero tablica elementów stanowi menu.

W przypadku klasy opłaca się pakować elementy menu w listę jednokierunkową.

Elementy menu lepiej zrobić jako klasę wewnętrzną.


(Krzychu224) #7

Ok ale tablice elementów tworzysz na podstawie struktury, czyli jest to tablica struktur tak?

Każde menu to osobna tablica struktur 'Menu'. Czyli z tego co widzę powinno wystarczyć zamienić strukturę na klasę i zrobić odpowiedni konstruktor.

-- Dodane 15.06.2012 (Pt) 21:13 --

Ok, już wiem gdzie namieszałem wcześniej. Źle przypisywałem zmienne w konstruktorze (oj trzeba solidnie odświeżyć programowanie obiektowe).

W każdym razie przerobiłem kod tak żeby ze struktur otrzymać klasy i ogólnie wygląda to tak:

#include "StdAfx.h"

#include 


using namespace std;


class MenuZ;

void submenu(class MenuZ *menu);

void crt(class MenuZ*) { cout<<"Create something"<
void add(class MenuZ*) { cout<<"Add something"<
void del(class MenuZ*) { cout<<"Delete something"<
void rptvert(class MenuZ*) { cout<<"Show verticaly"<
void rpthorz(class MenuZ*) { cout<<"Show horizontaly"<
void load(class MenuZ*) { cout<<"Load from file"<
void save(class MenuZ*) { cout<<"Save to file"<

const class MenuZ { 

public:

	const char *text; 

	void (*fun)(class MenuZ*); 

	class MenuZ *sub; 

};





void submenu(class MenuZ *menu)

  {

   cout<
   while(true)

     {

      cin.sync();

      unsigned n=0;

      class MenuZ *tmp=menu; //tmp wskazuje na MenuZ ktore zostalo przekazane do funkcji

      while(tmp->fun) cout<<(++n)<<": "<<(tmp++)->text<
      cout<<"0: "<text<
      unsigned m;

      if((cin>>m)&&(m<=n))

        {

         if(!m) break;

         class MenuZ *tmp=menu+m-1;

         tmp->fun(tmp->sub);

        }

      else

        {

         cin.clear();

         cout<<"Nie ma takiej opcji"<
        }

     }

   cout<
  }


int main()

  {

	MenuZ MainMenu;

	MainMenu.text="Dodaj";

	MainMenu.fun=add;

//	MainMenu.sub


	submenu(MainMenu*);



   return 0;

  }

Na razie bez konstruktora. Sprawdziłem czy przypisania działają i wszystko jest ok. Obecnie natrafiłem na dwa problemy: Kompilator nie chce zbudować programu z linijką:

submenu(MainMenu*);

i w jaki sposób tworzyć menu tak jak robione jest to tutaj:

RptMenuZ[]=

    {

     {"Pionowo",rptvert},

     {"Poziomo",rpthorz},

     {"Wroc"},

    },

  MainMenuZ[]=

    {

     {"Nowy",crt},

     {"Dodaj",add},

     {"Usun",del},

// {"Pokaz (sub)",subMenuZ,RptMenuZ},

     {"Wczytaj z pliku",load},

     {"Zapisz do pliku",save},

     {"Koniec"},

    }

  ;