Vektor als Switchkriterium

Gast #914825
Lesenswert?

Hallo zusammen.

Ich bin gerade dabei ein Display mit Menüführung zu programmieren. Das 
läuft auch solange, bis ich am Ende des Menüs ankomme und es darum geht 
mir Werte anzeigen zu lassen. Die Menüsprünge realisiere ich mittels 
Vektoren, die auf ein Struct aus Strings zeigen. Diese werden dann 
ausgegeben. Läuft 1a solange ich nur Strings anzeigen muß. Jetzt möchte 
ich aber auf Werte zurück greifen und diese Anzeigen. Dafür benötige ich 
viele verschiedene Funktionen und nicht die Standardroutine.

Lange Rede kurzer Sinn. Kann ich mit einer Switch-Anweisung irgendwie 
auch auf einen Vektor verweisen?

Gruß Bruno
Gast #914880
Lesenswert?

Etwa sowas?
1
typedef struct
2
{
3
  unsigned int  bla;          // Parameter 1
4
  unsigned int  blub;         // Parameter 2
5
  void (*p_func)(void);       // Funktions-Pointer
6
} Cmd_Tab;
7

8

9
void test_func (void)
10
{
11
  ...
12
  return;
13
} 
14

15
const Cmd_Tab Test_Tab =
16
        {0x0000,            // Param 1
17
         0x0001,            // Param 1
18
         test_func          // Funktions-Pointer
19
        };
#914906
Lesenswert?

Bruno wrote:
> Vllcht kannst dui dich an den Thread erinnern
>
> Beitrag "strlen bei mehrdimensionalen Strings"
>
> Ich möchte jetzt nicht auf ein Subdisplay verweisen, sondern auf eine
> Funktion.
>
>
1
> MenuEntry MainMenu[] =
2
>   {
3
>     { { "Hilfe", "Help" },      NULL },
4
>     { { "Bearbeiten", "Edit" }, &EditScreen },
5
>     { { "Beenden", "Exit" },    NULL }
6
>   };
7
>

OK.

Dann musst du deine Struktur erweitern.
Die besteht jetzt nicht mehr aus den 2 Einträgen, sondern aus 3
1
typedef void (*FuncPtr) ( void );
2

3

4
// Ein Eintrag (Menuepunkt) im Scrollbereich
5
typedef struct MenueEntry_ {
6
  Text                   m_Text;
7
  struct DisplayScreen_* m_pSubDisplay;
8
  FuncPtr                m_pFunction;
9
} MenuEntry;

wobei der dritte Eintrag der Funktionspointer ist. Die Auswerte-
funktion checkt jetzt einfach ab, welcher der beiden Pointer
nicht NULL ist. Ist es der SupDisplay Pointer, dann wird ein
Untermenü angezeigt. Ist es der Funktionspointer, dann wird die
Funktion aufgerufen.
1
void doCopy()
2
{
3
}
4

5
void doCut()
6
{
7
}
8

9
void doPaste()
10
{
11
}
12

13
// "Bearbeiten" Display
14
MenuEntry EditMenu[] =
15
  {
16
    { { "Kopieren",     "Copy" },  NULL, doCopy },
17
    { { "Ausschneiden", "Cut" },   NULL, doCut },
18
    { { "Einsetzen",    "Paste" }, NULL, doPaste }
19
  };
20

21
...
22

23
void HandleDisplay( DisplayScreen * pDisplay )
24
{
25
   ...  // konstante Teile des Screens aufbauen
26

27
   HandleMenu( pDisplay->ScrollArea.Entries,
28
               pDisplay->ScrollArea.m_Size );
29
}
30

31
void HandleMenu( MenuEntry* Entries, size_t NrEntries )
32
{
33
  size_t i;
34
  
35
  for( i = 0; i < NrEntries; ++i ) {
36
    // GetCurrentText( &Entries[i].m_Text ) )  ausgeben und so
37
    // das Menü aufbauen
38
  }
39

40
  // du hast eine Rückmeldung vom Benutzer und musst sie
41
  // jetzt auswerten
42

43
  // an dieser Stelle enthält i den Index des ausgewählten
44
  // Eintrags
45
  //
46
  // Checken ob es eine Funktion dafür gibt, wenn ja aufrufen
47
  if( Entries[i].pFunction != NULL )
48
    (*Entries[i].pFunction)();
49

50
  // Wenn es ein Submenü gibt, dann dieses auswählen
51
  if( Entries[i].m_pSubDisplay != NULL )
52
    HandleDisplay( Entries[i].m_pSubDisplay );
53
}


Beachten musst du nur, dass alle Funktionen immer die gleichen
Argumente haben, falls du welche brauchst. Das kann auch mal
bedeuten, dass eine Funktion Argumente bekommt, die sie nicht
benötigt.
Die tatsächlichen Argumente nimmst du ebenfalls mit in die
Struktur auf, damit sie beim Funktionsaufruf zur Verfügung
stehen.

zb.
1
typedef void (*FuncPtr) ( int * );
2

3

4
// Ein Eintrag (Menuepunkt) im Scrollbereich
5
typedef struct MenueEntry_ {
6
  Text                   m_Text;
7
  struct DisplayScreen_* m_pSubDisplay;
8
  FuncPtr                m_pFunction;
9
  int*                   m_pArg1;
10
} MenuEntry;
11

12

13
void doIncrement( int * pArg )
14
{
15
  (*pArg)++;
16
}
17

18
void doDecrement( int * pArg )
19
{
20
  (*pArg)--;
21
}
22

23
int Counter;
24
int Anzahl;
25

26
// "Bearbeiten" Display
27
MenuEntry EditMenu[] =
28
  {
29
    { { "Counter erhöhen", "inc Counter" },    NULL, doIncrement, &Counter },
30
    { { "Coutner verringern", "dec Counter" }, NULL, doDecrement, &Counter },
31
    { { "Anzahl erhöhen", "inc Anzahl" },    NULL, doIncrement, &Anzahl },
32
    { { "Anzahl verringern", "dec Anzahl" }, NULL, doDecrement, &Anzahl },
33
    { { "Beenden",    "Exit" }, NULL, NULL, NULL }
34
  };
35

36
...
37

38
void HandleDisplay( DisplayScreen * pDisplay )
39
{
40
  do {
41
    ...  // konstante Teile des Screens aufbauen
42

43
  } while(  HandleMenu( pDisplay->ScrollArea.Entries,
44
                        pDisplay->ScrollArea.m_Size );
45
}
46

47
uint8_t HandleMenu( MenuEntry* Entries, size_t NrEntries )
48
{
49
  size_t i;
50
  
51
  for( i = 0; i < NrEntries; ++i ) {
52
    // GetCurrentText( &Entries[i].m_Text ) )  ausgeben und so
53
    // das Menü aufbauen
54
  }
55

56
  // du hast eine Rückmeldung vom Benutzer und musst sie
57
  // jetzt auswerten
58

59
  // an dieser Stelle enthält i den Index des ausgewählten
60
  // Eintrags
61
  //
62
  // Checken ob es eine Funktion dafür gibt, wenn ja aufrufen
63
  if( Entries[i].pFunction != NULL )
64
    (*Entries[i].pFunction)( m_pArg1 );
65

66
  // Wenn es ein Submenü gibt, dann dieses auswählen
67
  if( Entries[i].m_pSubDisplay != NULL )
68
    HandleDisplay( Entries[i].m_pSubDisplay );
69

70
  return Entries[i].pFunction != NULL || Entries[i].m_pSubDisplay != NULL;
71
}
Gast #915096
Lesenswert?

Na ja so simpel war das nicht. Wenn man an einem bestehenden Programm an 
der Basis fummelt kommt oft nur quatsch raus. Auf dem ganzen Jedöns 
basieren ca 20k Code. Aber der Ansatz war super. So in der Art hatte ich 
das auch geplant. Nur die Codestelle
1
(*Entries[i].pFunction)( m_pArg1 )

war mir nicht geläufig.
Danke nochmal² für die Hilfe.

Gruß Bruno

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren