Hall zusammen,
ich baue mir gerade in C ein LCD-Menü auf Basis von struct zusammen. An
einer Stelle habe ich Probleme, die ich auch mit Hilfe der Suche &
Google nicht lösen kann. Offensichtlich habe ich noch nicht das richtige
Verständnis von struct/pointern :(
Mein struct sieht wie folgt aus und deklariert gleichzeitig ein Menü (in
dem Fall ist der Funktinspointer NULL und subMenueCount/subMenues
gefüllt) oder ein Menüpunkt (Funktinspointer verweist auf eine Funktion,
subMenueCount/subMenues sind nicht gesetzt):
1 | typedef void (*fp)(void);
| 2 |
| 3 | typedef struct menue {
| 4 | char* menueName;
| 5 | fp pFunction;
| 6 | uint8_t subMenueCount;
| 7 | // 1 Frage: Wie deklariere ich ein Array von
| 8 | // MENUE-Pointern der Größe 3?
| 9 | struct menue* subMenues[3];
| 10 | struct menue* parentMenu;
| 11 | } MENUE;
|
Nun versuche ich mein Menü zu initialisieren und verwende hierzu zwei
Funktionen:
1 | void init_menu(void) {
| 2 | MENUE* m1 = createMenue("GPS", &operateInGPSMode, 0, NULL);
| 3 |
| 4 | MENUE* m21 = createMenue("Create waypoint route",
| 5 | &createWaypointRoute, 0, NULL);
| 6 | MENUE* m22= createMenue("Load waypoint route",
| 7 | &loadWaypointRoute, 0, NULL);
| 8 | MENUE* m23 = createMenue("Edit waypoint route",
| 9 | &editWaypointRoute, 0, NULL);
| 10 |
| 11 | MENUE g2[3] = {m21, m22, m23};
| 12 | // 2 Frage: Wie übergebe ich ein Pointer auf mein
| 13 | // MENUE-Pointer-Array?
| 14 | MENUE* m2 = createMenue("Waypoint menu", NULL, 3, g2);
| 15 |
| 16 | MENUE g1[2] = {m1, m2};
| 17 | MENUE* m0 = createMenue("Main menu", NULL, 2, g1);
| 18 |
| 19 | (*m2).parentMenu = m0;
| 20 | }
| 21 |
| 22 | // 3 Frage: Wie deklariere ich den Parameter für meinen übergebenen
| 23 | // Pointer auf mein MENUE-Pointer-Array (letzter Parameter)?
| 24 | MENUE* createMenue(char* menueName, fp pFunction,
| 25 | uint8_t subMenueCount, MENUE* subMenues) {
| 26 | MENUE* newMenue = (MENUE*) malloc(sizeof(MENUE));
| 27 | (*newMenue).menueName = menueName;
| 28 | (*newMenue).pFunction = pFunction;
| 29 | (*newMenue).subMenueCount = subMenueCount;
| 30 | // 4 Frage: Wie weise ich das ganze hier zu?
| 31 | (*newMenue).subMenues = subMenues;
| 32 | }
|
Innerhalb des Sourcecodes habe ich Fragen eingefügt, die mein Problem an
den diversen Stellen beschreiben. Im Grunde habe ich Probleme mit einem
Array von MENUE-Pointern, d. h. wie deklariere ich das ganze, wie
übergebe ich sowas an besten an eine Funktion, wie weise ich sowas zu
etc. Habe vieles ausprobiert, aber der Compiler hat immer gemeckert.
Kann mir jemand hierzu Links, Ratschläge, Anregungen o. Tipps geben?
Im voraus schon mal Danke...
Christoph
Hallo Christoph,
die 1. Frage hast Du wohl selbst richtig beantwortet! Hier dreht es
sich im Wesentlichen um Dinge wie Vorwärts-Deklaration u.ä.
Die 2. Frage bezieht sich anscheinend auf das g2[3]. Das stimmt wohl
auch, wie Du es gelöst hast.
Die 3. Frage: Ebenfalls Volltreffer!
Die 4. Frage genauso!
Die 5. Frage sollte jetzt kommen, statt des "der Compiler hat immer
gemeckert"! Sie lautet: "Was bedeuten die folgenden Fehlermeldungen des
Compilers?".
Ich lese jetzt mal Kaffeesatz: Der Compiler beschwert sich, daß hier
lokalen Variablen zwar Werte zugewiesen werden, aber diese Werte nicht
benutzt werden.
Damit komme ich zu Deinem vermutlichen Problem:
Der unterschiedliche Geltungsbereich der verschiedenen Klassen von
Variablen ist Dir wohl unbekannt. Diese Kenntnis gehört allerdings bei
jeder Programmiersprache zum absoluten Basiswissen.
Ein Tip:
Nimm ein gutes C-Lehrbuch und lerne C! Programmiersprachen lernt man
am besten (meine persönliche Erfahrung) von der Theorie her zur Praxis
hin und nicht durch "Ausprobieren". Das ist der Unterschied zu
natürlichen Sprachen, die man genau andersherum lernt.
Grüße
Bernhard
P.S. Deine Frage schreckt allein durch ihren Umfang viele vom Antworten
ab.
Ich weiß allerdings auch nicht, wie Du diese Anfrage hättest kürzer
"bringen" können.
Grüße
Bernhard
Hallo,
erst einmal Danke für die Antwort(en).
Der Compiler meldet für die folgende Zeile (mit << markiert) in
1 | MENUE* createMenue(char* menueName, fp pFunction,
| 2 | uint8_t subMenueCount, MENUE* subMenues) {
| 3 | MENUE* newMenue = (MENUE*) malloc(sizeof(MENUE));
| 4 | (*newMenue).menueName = menueName;
| 5 | (*newMenue).pFunction = pFunction;
| 6 | (*newMenue).subMenueCount = subMenueCount;
| 7 | (*newMenue).subMenues = subMenues; // << error laut compiler
| 8 | }
|
die folgende Meldung:
main.c:126: error: incompatible types in assignment
Hier noch mal der zugehörige struct:
1 | typedef struct menue {
| 2 | char* menueName;
| 3 | fp pFunction;
| 4 | uint8_t subMenueCount;
| 5 | struct menue* subMenues[3];
| 6 | struct menue* parentMenu;
| 7 | } MENUE;
|
Es gibt also keine Probleme bzgl. der Gültigkeitsbereiche von Variablen.
Das Thema Gültigkeitsbereiche ist mir auch klar. Zur Info... ich
entwickle beruflich seit ca. 9 Jahren in Java. Aus diesem Grund fällt
mir die Arbeit mit Pointern momentan schwer bzw. ist noch ziemlich
ungewohnt.
Hallo Christoph,
jetzt lichtet sich der Nebel!
Das (*newMenue).subMenues = subMenues; // << error laut compiler
sollte werden:
(*newMenue).subMenues[0] = subMenues[0];
(*newMenue).subMenues[1] = subMenues[1];
(*newMenue).subMenues[2] = subMenues[2];
U.U. ginge das Ganze auch dann, wenn Du folgendes tust:
statt MENUE* createMenue(char* menueName, fp pFunction,
uint8_t subMenueCount, MENUE* subMenues) {
mache mal MENUE* createMenue(char* menueName, fp pFunction,
uint8_t subMenueCount, MENUE subMenues[3]) {
Der generierte Aufruf-Code wäre identisch, aber der Fehler müßte
verschwinden.
Da liegt - denke ich - einer der Unterschiede zwischen Java und C(++).
Es zahlt sich wirklich aus, an eine neue Programmiersprache von der
Theorie her heranzugehen, anstatt zu glauben "X ist etwa wie Y, also
übertrage ich meine Erfahrungen von Y nach X".
Ich habe den Übergang C ---> C++ bzw. C(++) ---> Java als durchaus mit
Fallen gespickt empfunden - nicht den OO-Teil, sondern die kleinen
Feinheiten, wie z.B. die compiler-interne Umsetzung von "unsigned char"
nach "signed integer" und zurück. Da liegen zwischen C und C++ u.U.
Welten!
Viel Erfolg mit C!
Bernhard
So, das ganze funktioniert jetzt und ich wollte an dieser Stelle den
Code zeigen, falls es jemanden interessiert. Danke an Bernhard, dessen
letzter Tipp zur Lösung geführt hat. Ehrlich gesagt verstehe ich wie die
Lösung funktioniert, aber nicht, wieso der vorherige Ansatz nicht
funktioniert hat. Da werde ich mir also noch ein gutes C-Buch anschaffen
:)
Wie auch immer, weiter unten der funktionierende Code.
Gruß
Christoph
1 | typedef void (*fp)(void);
| 2 |
| 3 | typedef struct menue {
| 4 | char* menueName;
| 5 | fp pFunction;
| 6 | uint8_t subMenueCount;
| 7 | struct menue* parentMenu;
| 8 | struct menue* subMenues[3];
| 9 | } MENUE;
| 10 |
| 11 | // currentMenue ist der Pointer auf das aktuell anzuzeigende Menü
| 12 | MENUE* currentMenue = NULL;
| 13 |
| 14 | /**
| 15 | *
| 16 | */
| 17 | void init_menu(void) {
| 18 | MENUE* m1 = createMenue("GPS", &operateInGPSMode, 0, NULL);
| 19 |
| 20 | MENUE* m21 = createMenue("Create waypoint route", &createWaypointRoute, 0, NULL);
| 21 | MENUE* m22= createMenue("Load waypoint route", &loadWaypointRoute, 0, NULL);
| 22 | MENUE* m23 = createMenue("Edit waypoint route", &editWaypointRoute, 0, NULL);
| 23 | MENUE* g2[3] = {m21, m22, m23};
| 24 | MENUE* m2 = createMenue("Waypoint menu", NULL, 3, g2);
| 25 |
| 26 | MENUE* g1[2] = {m1, m2};
| 27 | MENUE* m0 = createMenue("Main menu", NULL, 2, g1);
| 28 |
| 29 | (*m0).parentMenu = m0;
| 30 | (*m2).parentMenu = m0;
| 31 |
| 32 | currentMenue = m0;
| 33 | }
| 34 |
| 35 | /**
| 36 | *
| 37 | */
| 38 | MENUE* createMenue(char* menueName, fp pFunction,
| 39 | uint8_t subMenueCount, MENUE* subMenues[]) {
| 40 | MENUE* newMenue = (MENUE*) malloc(sizeof(MENUE));
| 41 | (*newMenue).menueName = menueName;
| 42 | (*newMenue).pFunction = pFunction;
| 43 | (*newMenue).subMenueCount = subMenueCount;
| 44 | // Einhängen von Untermenüpunkten in einer Schleife,
| 45 | // weil ein Menü zwischen einem und drei Untermenüpunkte
| 46 | // haben kann (angegeben durch subMenueCount).
| 47 | for (int i=0; i<subMenueCount; i++) {
| 48 | (*newMenue).subMenues[i] = subMenues[i];
| 49 | }
| 50 | return newMenue;
| 51 | }
|
Christoph Borowski wrote:
> Ehrlich gesagt verstehe ich wie die
> Lösung funktioniert, aber nicht, wieso der vorherige Ansatz nicht
> funktioniert hat.
Weil man in C ein Array nicht als Ganzes zuweisen kann. Es gibt in C
keinen Datentyp "Array" oder "String", weshalb man die einzelnen
Elemente immer einzeln behandeln muss.
> Da werde ich mir also noch ein gutes C-Buch anschaffen
> :)
Das ist sicher von Vorteil... Nicht gleich entmutigen lassen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|