Forum: Mikrocontroller und Digitale Elektronik Problem mit Pointer (um)setzen


von Oz z. (ozzy)


Lesenswert?

Moin,

ich probiere gerade ein Menu mit einer doppelt-verketteten Liste zu 
erstellen. Jeder Menüeintrag (struct sNode) enthält dabei (wenn 
vorhanden) einen pointer auf den Menüeintrag über/unter dem Element, 
sowie jeweils einen Pointer auf seine Wurzel und sein Kind:
1
struct sNODE
2
{
3
  int id; 
4
  struct sNODE *root,*child,*up,*down;
5
};
Anschließend lege ich in der Main ein paar items an.

Nun möchte ich mich natürlich auch durch das Menü bewegen. Dafür habe 
ich einen Node "struct sNODE activeNode", den ich zuerst auf den 
root-Knoten setze:
1
activeNode = root;

Über eine Consolenabfrage soll man dann navigieren können. Hierfür 
übergebe ich der Funktion den Pointer auf den ActiveNode sowie das 
Zeichen:
1
navigate(&activeNode,c);
Das werte ich nun in der Funktion aus:
1
void navigate(struct sNODE *sNode, char input)
2
{
3
switch (input)
4
{
5
   case 'c':
6
      if (sNode->child != NULL)
7
         sNode = sNode->child;
8
      break;
9
   ...
10
}
11
}
In der Funktion wird das auch alles schön gesetzt, aber wenn ich aus 
dieser zurückkomme und mir die ID des Knotens ausgeben lasse, dann ist 
es wieder die ID von root, auch wenn der Knoten ein Kind hat. Langsam 
sehe ich den Wald vor lauter Bäumen nicht - warum setzt er den Pointer 
denn nicht um???

Vielen Dank für Eure Hilfe!!!

von Oz z. (ozzy)


Lesenswert?

Oh man,

das war wohl etwas früh heute morgen... Es muss natürlich heissen:
1
*sNode = *(sNode->child);
Man möge mir verzeihen...

von Rolf M. (rmagnus)


Lesenswert?

Damit arbeitest du immer mit einer Kopie des aktuellen Menüeintrags. Das 
geht zwar auch, ist aber eher unüblich.

von Oz z. (ozzy)


Lesenswert?

Moin,

wie würdest Du das denn umsetzen?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Oz zy schrieb:
> void navigate(struct sNODE *sNode, char input)

Das bedeutet, daß Du nur verändern kannst, worauf "sNode" zeigt, aber 
nicht "sNode" selbst.

Da Du aber in Deiner Funktion genau das machen willst:

         sNode = sNode->child;

musst Du nicht einen Pointer auf Deine Struktur übergeben, sondern einen 
Pointer auf einen Pointer auf Deine Struktur:

> void navigate(struct sNODE **psNode, char input)

Das bedeutet natürlich, daß Du beim Aufruf der Funktion den 
Adressoperator verwenden musst, um die Adresse des ersten Parameters zu 
bestimmen, und das bedeutet natürlich auch, daß Du in der Funktion den 
Pointer dereferenzieren musst:

         *psNode = (*psNode)->child;

von Karl H. (kbuchegg)


Lesenswert?

Oz zy schrieb:

> Nun möchte ich mich natürlich auch durch das Menü bewegen. Dafür habe
> ich einen Node "struct sNODE activeNode", den ich zuerst auf den
> root-Knoten setze:
>
1
activeNode = root;

Und genau das willst du nicht.
Wozu willst du Kopien der Menüknoten haben.
Alles was du willst, ist durch das Menü navigieren. Dazu brauchst du 
aber keine Knotenkopien, sondern du brauchst einen Pointer auf den 
Knoten, welcher der aktive Knoten ist.
Also einen
1
  struct sNODE *activeNode;
und du setzt ihn am Anfang auf die Root
1
   activeNode = &root;


> Das werte ich nun in der Funktion aus:
> void navigate(struct sNODE *sNode, char input)

Und da diese Funktion den sNode Pointer verändert, brauchst du eine 
Möglichkeit, damit diese Funktion das auch kann.
Entweder du vereinbarst, dass die Funktion den jeweils neuen Node (ab 
hier ist damit immer ein Pointer gemeint) als Returnwert liefert
1
struct sNODE * navigate( struct sNODE *sNode, char input )
2
{
3
   ...
4
}
5
6
...
7
   activeNode = navigate( activeNode, 'c' );
8
...

oder du versetzt die Funktion in die Lage, das Pointerargument selbst zu 
verändern
1
void navigate(struct sNODE **sNode, char input)
2
{
3
   ....
4
}
5
6
   ....
7
   navigate( &activeNode, 'c' );

von Fabian O. (xfr)


Lesenswert?

Im Prinzip kannst Du Dir das Übergeben von dem Zeiger (auf den Zeiger) 
vom aktiven Knoten auch sparen. Oder gibt es eine Situation, in der die 
Funktion navigate() mit einem inaktiven Knoten arbeiten soll? Wenn 
nicht, würde ich einfach schreiben:
1
void navigate(char input)
2
{
3
switch (input)
4
{
5
   case 'c':
6
      if (activeNode->child != NULL)
7
         activeNode = activeNode->child;
8
      break;
9
   ...
10
}
11
}

von W.S. (Gast)


Lesenswert?

zum X-ten Mal:

Wirf einen Blick in die "Lernbetty" hier in der Codesammlung. Da ist 
auch ein Menüsystem mit drin, was im Groben so ähnlich organisiert ist 
wie das, was du mit deinem Entwurf eigentlich anstrebst.

Ach ja, du solltest besser in solchen Sachen nicht so prozedural 
herangehen wollen, sondern dich auf objektorientierte, 
ereignisgesteuerte Funktionalität orientieren. Ja, das geht auch mit 
plain C, wenn man sich zuvor einen ordentlichen Plan dafür zurechtlegt.


btw:
Es ist schon erstaunlich, wie unsäglich oft hier die Leute verzweifelt 
nach Lösungen nachfragen, die ich in der Lernbetty bereits ausgiebig 
vorgeturnt habe - sei es ne serielle Kommunikation oder Konvertierungen 
oder Menüsystem oder Fontfragen oder Grafik auf LCD oder 
Kommandozeilenparserei oder Systemsetup oder Startupfragen und so 
weiter.

W.S.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.