Guten Morgen, werte Bastlerfreunde und Profis!
Ich beschäftige mich momentan mit dem Thema MenuStruktur und damit
einhergehend auch mit Strukturen in C.
Bin noch relativ neu im gesamten Themenkreis, besonders Structs.
Nun stehe ich vor dem Problem, dass ich gerne per Variable auf eine
Struktur zugreifen will:
Ich habe zwei Strukturen von folgendem Aufbau (in Anlehnung an die
MC-FAQ)
1
structMenueintrag
2
{
3
charText[17];
4
VoidFnctFunction;
5
};
6
7
structMenueintragHauptmenu[]={
8
{"++Haupt-Menue++"},
9
{"Einstellungen",settings},
10
{" Start",begin},
11
{" Abbruch",abort},
12
{"Sel Up Down Info"}
13
};
14
15
structMenueintragEinstellungen[]={
16
{"+Einstellungen+"},
17
{"Set Frequency",setFreq},
18
{" Set Amount",setAmount},
19
{" Set Interval",setInterval},
20
{"Sel Up Down Info"}
21
};
Nun möchte ich gerne in einer Funktion namens
1
voidRefreshScreen(structMenueintragMenu[])
das Aktuelle Menü auf eineme Display ausgeben. die Ausgabe funktioniert
auch schon.
Ich kann also momentan über einen Aufruf der Form
1
RefreshScreen(Hauptmenu);
Das jeweilige Menü darstellen.
Nun ist dies jedoch sehr unpraktisch.
Ich würde gerne diese beiden Menüs (Structs) in ein Array oder in eine
Struct packen, um dann per Index das jeweilige Menü benennen zu können.
Also etwa in der Form:
1
RefreshScreen(Menus(1));
oder
1
2
RefreshScreen(Menus(aktuellesMenu));
Das hätte den Vorteil, dass ich damit eine Variable definieren kann, die
das aktuell anzuzeigende Menü repräsentiert.
Könnt Ihr mir da helfen?
Ich habe mir bereits zahlreiche Beiträge zu Structs durchgelesen, bin
aber noch nicht auf einen grünen Zweig gekommen, Sehe momentan den Wald
vor Bäumen nicht.
Mit Dank, Tüftler
Tueftler schrieb:
> Nun ist dies jedoch sehr unpraktisch.> Ich würde gerne diese beiden Menüs (Structs) in ein Array oder in eine> Struct packen, um dann per Index das jeweilige Menü benennen zu können.
warum packst du das nicht wieder in eine neue struct. Dann kannst du
bequem mit dem "." referenzieren.
Tueftler schrieb:
> Ich beschäftige mich momentan mit dem Thema MenuStruktur und damit> einhergehend auch mit Strukturen in C.> Bin noch relativ neu im gesamten Themenkreis, besonders Structs.>> Nun stehe ich vor dem Problem, dass ich gerne per Variable auf eine> Struktur zugreifen will:> Ich habe zwei Strukturen von folgendem Aufbau (in Anlehnung an die> MC-FAQ)
Du bist noch ein wenig zu sehr dem Array verpflichtet
Ein Menü ist noch etwas mehr als eine Abfolge von Menüpunkten in einem
Array :-). Zb hat ein Menü einen Titel (der aber selbst kein
auswählbarer Menüpunkt ist) und es hat eine Anzahl von Menüpunkten (wie
stellen denn deine verarbeitenden Funktionen fest, wieviele Menüpuntke
es gibt?)
(Ausserdem solltest du dir angewöhnen, für Texte, die sich nicht ändern,
keine char-Arrays zu allokieren, sondern ganz einfach nur einen Pointer
auf const char einzubauen. Zum einen spart das Speicher, zum anderen
wirst du es dir danken wenn du anfängst die Texte ins Flash auszulagern)
struct Menueintrag
{
const char* Text;
VoidFnct Function;
};
struct Menu
{
const char* Title;
uint8_t NrEntries;
struct Menueeintrag Entries[];
};
struct Menu HauptMenu =
{ "++Haupt-Menue++",
3,
{ { "Einstellungen", settings },
{ "Start", begin },
{ "Abbruch", abort},
}
};
struct Menu SettingsMenu =
{ "+Einstellungen+",
3,
{ { "Set Frequency", setFreq },
{ "Set Amount", setAmount },
{ "Set Interval", setInterval },
}
};
> Nun möchte ich gerne in einer Funktion namens>
1
>voidRefreshScreen(structMenueintragMenu[])
2
>
> das Aktuelle Menü auf eineme Display ausgeben. die Ausgabe funktioniert> auch schon.> Ich kann also momentan über einen Aufruf der Form>
1
>RefreshScreen(Hauptmenu);
2
>
> Das jeweilige Menü darstellen.> Nun ist dies jedoch sehr unpraktisch.
Ist es.
> Ich würde gerne diese beiden Menüs (Structs) in ein Array oder in eine> Struct packen, um dann per Index das jeweilige Menü benennen zu können.
Brauchst du im Grunde nicht.
Es reicht, wenn du eine Pointer Variable hast, die auf das aktuelle Menü
zeigt
struct Menu* actMenu;
> Also etwa in der Form:>
1
>RefreshScreen(Menus(1));
2
>
> oder>
1
>RefreshScreen(Menus(aktuellesMenu));
2
>
oder einfach
actMenu = &HauptMenu;
RefreshScreen( actMenu );
Hallo Karl,
Vielen Dank für deine ausführliche Antwort, diese hat mich bereits sehr
viel weiter gebracht. Ich habe das jetzt mal so wie von dir
vorgeschlagen implementiert. Nun habe ich allerdings wiederum ein
Problem.
Ich versuche mal zu erklären was ich überhaupt gemacht hab, um zu
prüfen, dass ich das auch verstanden habe:
Als erstes definiere ich eine Struktur mit Namen Menueeintrag, deren
Einträge jeweils aus einem Text und einer Funktion bestehen.
1
structMenueeintrag
2
{
3
constchar*Text;
4
VoidFnctFunction;
5
};
Nun definiere ich eine neue Structure, die sich zusammensetzt aus:
-einem Pointer auf ein Char-?Eintrag? mit Namen Title
-einer Variable vom typ uint8_t mit Namen NrEntries
-sowie einer Structur vom obigen "Typ" Menueeintrag mit Namen Entries
1
structMenue{
2
constchar*Title;
3
uint8_tNrEntries;
4
structMenueeintragEntries[];//
5
};
Nun erzeuge ich eine Struktur vom Typ Menue und trage die Werte ein.
1
structMenueEinstellungen=
2
{"++Einstellungen++",
3
3,
4
{
5
{" Messintervall",setInterval},
6
{" Frequenz",setFreq},
7
{" Spielzahl",setAmount}
8
}
9
};
Nun definiere ich noch einen Pointer der auf den Typ Menue zeigt und
actMenue heisst:
1
structMenue*actMenue;
Die nun folgende Funktion bekommt den oben definierten Pointer als
Argument übergeben und soll den Menutitel sowie die Texte der einzelnen
Einträge ausgeben: Hier fängt das Problem an:
Ich muss zuerst den Inhalt des übergebenen Pointers in eine lokale
Struktur laden, wiederum vom Typ Menue.
Anschliessend kann ich auf den Title der lokalen Struktur zugreifen und
diesen ausgeben. Auch kann ich auf NrEntries zugreifen und diese korrekt
auslesen. Sobald ich allerdings auf die Texte der intregrierten Struct
Menueeintrag zugreifen will, kommen nur noch wirre Zeichen. (in der
Schleife)
1
voidRefreshScreen(structMenue*Menuelokal)
2
{
3
structMenueMenuelocal=*Menuelokal;
4
5
WriteString(2,0,Menuelocal.Title);
6
7
for(uint8_tz=1;z<=Menuelocal.NrEntries;z++)
8
{
9
WriteString(2,z+2,Menuelocal.Entries[z-1].Text);
10
}
11
}
Ander hingegen wenn ich nicht den Pointerinhalt ausgebe sondern direkt
den Inhalt eines Menus:
1
WriteString(2,5,HauptMenue.Entries[1].Text);
Diese Ausgabe funktioniert fehlerfrei.
Meine Frage also:
1. Wie greife ich auf die Elemente der Struct in der Struct zu? :)
2. Welches Buch erklärt diese Sachen ausführlich und verständlich, evtl.
mit Beispielen?
Vielen Dank für deine Mühen und natürlich auch allen Anderen die mir
weiterhelfen können oder es versuchen.
In RefreshScreen brauchst du keine lokale Struktur anzulegen.
Nutze einfach den Pointer um auf die Elemente zuzugreifen:
void RefreshScreen(struct Menue *actMenue)
{
WriteString(2,0,actMenue->Title);
...
WriteString(2,z+2,actMenue->Entries[z-1].Text);
....
Hallo nochmal,
Das geht nun sehr gut, Vielen Dank für diese Hilfe.
Habe nun das Problem, dass ich einer neuen Funktion zwei Argumente
(Pointer) übergebe.
void ExecCommand(struct Menue *actMenue, uint8_t *Selection)
{
actMenue->Entries[*Selection].Function();
}
Allerdings klappt dies nicht, Ich lade extern in den Pointerbereich eine
Zahl:
1
(*Selection)=1;
Dann rufe ich die Funktion auf und übergebe ihr die Adresse an der die
Zahl steht, die ich vorher hineingeschrieben habe.
1
ExecCommand(actMenue,&Selection);
Nun wird jedoch immer das gleiche Unterprogramm aufgerufen, egal welche
Zahl ich vorher in die Speicheradresse auf die der Pointer zeigt
geschrieben habe.
Also
1
(*Selection)=1;
2
ExecCommand(actMenue,&Selection);
3
(*Selection)=2;
4
ExecCommand(actMenue,&Selection);
5
(*Selection)=3;
6
ExecCommand(actMenue,&Selection);
Ruft immer das gleiche Untermenü auf.
Was mache ich da noch falsch?
Danke für eure Bemühungen.
Meiner Ansicht nach hast du da einen "Pointer" zuviel drin.
Statt
1
(*Selection)=2;
2
ExecCommand(actMenue,&Selection);
sollte es gefühlt eher so aussehen:
1
u8_tSelection;
2
Selection=2;
3
ExecCommand(actMenue,&Selection);
Aber eigentlich kannst du doch auf die Übergabe von Selection als
Pointer verzichten und direkt Selection übergeben? Oder soll deine
Funktion schreibend auf Selection zugreifen können?