D. Chung schrieb:> ich komme besten willen nicht darauf> für was der Pointer *menu_strings[MENU_ITEMS]
Das ist nicht ein Pointer, das ist ein Array aus Pointern.
Wie Rufus schon sagte ist menu_strings ein Array von Pointern. Genauer
ein Array von char Pointer und ein char Pointer ist quasi ein string. In
dem von dir gezeigten Code werden hier die verschiedenen Menüeinträge
abgespeichert.
Ja wenn ich noch dabei bin hab ich mich falsch ausgedrückt, aber warum
das ganze ?Wie Pointer funktionieren das versteh ich,...Vill könntest du
mir das erklären wieso ?
Gruß
Um das Ganze möglichst flexibel zu gestalten. Kein Mensch will die
Menüeinträge wild verteilt in den Code werfen und Konstruktion wie
1
for( i = 0; i < MENU_ITEMS; i++ )
2
{
3
if(i == 0)
4
{
5
d = (w-u8g.getStrWidth("First Line"))/2;
6
u8g.drawStr(d, i*h, "First Line");
7
}
8
if(i == 1)
9
{
10
d = (w-u8g.getStrWidth("Second Item"))/2;
11
u8g.drawStr(d, i*h, "Second Item");
12
}
13
// usw...
14
}
bauen. Bis aus den anzuzeigenden Text ist der Code zum Menüträge
anzeigen offensichtlich identisch. Also packt man alle Einträge in ein
Array und arbeitet dies ab.
Danke für die schnellen Antworten, ja das mit dem Array ist mir ja klar
aber mich stört der Stern ... es würde doch auch ohne Pointer gehen. Ich
erkenne den Sinn dahinter nicht in diesem Beispiel, das ist mein Problem
würde jetzt
menu_strings[MENU_ITEMS] = { "First Line", "Second Item",...
dort stehen müsste es doch auch funktionieren ?
D. Chung schrieb:> Danke für die schnellen Antworten, ja das mit dem Array ist mir ja klar> aber mich stört der Stern ... es würde doch auch ohne Pointer gehen. Ich> erkenne den Sinn dahinter nicht in diesem Beispiel, das ist mein Problem>> würde jetzt>> menu_strings[MENU_ITEMS] = { "First Line", "Second Item",...>> dort stehen müsste es doch auch funktionieren ?
Nein. Das würde der Compiler mit einer Fehlermeldung wegen eines
fehlenden Datentyps quittieren.
Schriebst Du jetzt, aber:
char menu_strings[MENU_ITEMS] = { "First Line", "Second Item",...
so erhälst Du damit ein Array, das nur aus einem MENU_ITEMS langem
String besteht, versuchst aber das Array mit mehreren Strings zu
initialisieren.
Nimm's mir bitte nicht übel, aber das ist das Paradebeispiel für eine
Gelegenheit, auf C-Bücher zu verweisen.
Erstmal geht menu_strings[MENU_ITEMS] alleine sowieso nicht. Da fehlt
noch der Typ, also wenn dann char menu_strings[MENU_ITEMS]. Und nein so
funktioniert das nicht. Wenn du das so machst hast du ein Array in dem
du MENU_ITEMS chars also einzelne Zeichen speichern möchtest.
Tatsächlich möchtest du aber MENU_ITEMS strings in dem Array Speichern.
Hier noch einige Beispiele zu strings:
1
// Array aus chars. Text kann verändert werden
2
char str[] = "Bla Blupp";
3
4
// Pointer zu char. Der Text kann in diesem Fall nicht verändert werden weil es von einem string Literal initialisiert wurde
5
char* str = "Bla Blupp";
6
7
// Array von char Pointern. Text kann auch nicht verändert werden, siehe oben
Ja der Datentyp muss natürlich dabei sein.
@Bitflüsterer
Ich glaub langsam komme ich dahinter bzw. hab wohl was übersehene
char menu_strings[] = { "First Line", "Second Item"}
würde doch ein Array aus 2 char s bilden.
char menu_strings[1]-> First Line
char menu_strings[2]-> Second Item
Würde eine Zahl darin stehen wie
char menu_strings[2] = { "First Line", "Second Item"}
würde das heißen das in menu_strings[2] -> "First Line", "Second Item"
drin stehen würde ?
Und bei
#define MENU_ITEMS 4
char *menu_strings[MENU_ITEMS] = { "First Line", "Second Item",
"3333333", "abcdefg" };
Steht in
char *menu_strings[1] -> First Line
char *menu_strings[2] -> Second Item
char *menu_strings[3] -> 3333333
char *menu_strings[4] -> abcdefg
Ich hoffe ich bin auf dem richtigen Pferd ?
Ich glaube du brauchst tatsächlich ein gutes C Buch...
Wenn du ein Array definierst besagt die Zahl in den eckigen Klammern wie
viele Elemente dein Array haben soll. Man kann die Zahl auch weglassen
dann kriegt das Array so viele Elemente wie du in den runden {} Klammern
liefest. Wenn du später auf das Array zugreifst dann gibst du in den
eckigen Klammern an auf welches Element zu zugreifen willst. Die Zählung
beginnt auch bei 0 und nicht bei 1 wie in deinem Beispiel oben.
sebi707 schrieb:> Ich glaube du brauchst tatsächlich ein gutes C Buch...>> Wenn du ein Array definierst besagt die Zahl in den eckigen Klammern wie> viele Elemente dein Array haben soll. Man kann die Zahl auch weglassen> dann kriegt das Array so viele Elemente wie du in den runden {} Klammern> liefest. Wenn du später auf das Array zugreifst dann gibst du in den> eckigen Klammern an auf welches Element zu zugreifen willst. Die Zählung> beginnt auch bei 0 und nicht bei 1 wie in deinem Beispiel oben.
Sebi707
@
Hä das selbe hab ich doch gerade gemeint ? Bis auf das mit der 0.
Beispiel
char a=menu_strings[1]
in a steht dann Second Item?
Nein. In einem char kannst du keinen kompletten String speichern. Du
brauchst entweder ein Array oder einen Pointern. So muss das aussehen:
char* a=menu_strings[1];
Dann steht da drin "Second Item".
sebi707 schrieb:> Nein. In einem char kannst du keinen kompletten String speichern. Du> brauchst entweder ein Array oder einen Pointern. So muss das aussehen:> char* a=menu_strings[1];>> Dann steht da drin "Second Item".
Weil ein char 8 bit lange ist... Sollte ich eigentlich wissen, bin schon
zulange davon weg sry.
Ein Array von Pointern unter dem Namen menu_strings, wobei jeder
einzelne der Pointer auf einen Text zeigt.
Man hätte natürlich auch ein 2D Array von chars machen können
das hat aber den 'Nachteil', das alle 'Zeilen' des 2D Arrays gleich lang
sein müssen. Was wiederrum Speicherverschwendung bedeutet, wenn
gleichzeitig relativ lange und relativ kurze Texte in diesem Array
gespeichert werden sollen. Denn die Anzahl der Spalten ist ja über das
komplette 2D Array in allen Zeilen gleich und muss sich logischerweise
am längsten zu speichernden Text orientieren.
In der Lösung mit dem Pointer Array brauch ich das nicht. Die Texte sind
ja unabhängig vom Array. Das Array organisiert die nur insofern, dass es
die Verweise enthält, wo die tatsächlichen Texte gespeichert sind. Und
die können unabhängig voneinander beliebig lang sein.
Okay danke, das leuchtet ein. Jetzt wenn ich dieses Thema weiter
ausbauen will und noch Sub Menü s erzeugen will hätte ich anfangs das
Array um eine Dimension erweitert, dann war mein Gedanke dazu das ich
Plätze im Array verschwende, weil ich unterschiedliche Sub menues evtl
habe...
Meine zweite Lösung besteht aus mehreren Switch case bzw genau der
Anzahl der main menues, damit wäre ich in der Anzahl der unter Menues
variable.
Das wird aber irgendwann unübersichtlich denk ich.
Jetzt könnte ich mir das auch mit Pointer vorstellen, das wäre die
elegantere Lösung oder ?Das wäre dann doch eine Pointer auf Pointer
Struktur ?
Gruß
Der ganze Ansatz ist schon zweifelhaft. Denn ein Menü besteht ja nicht
nur aus Texten. Spätestens wenn du noch Submenüs haben willst und ev.
sogar direkt Funktionen an Menüpunkte hängen willst, solltest du mal ein
gutes C Buch konsultieren, welche Möglichkeiten zur Datenstrukturierung
du noch hast. Ein Array ist beileibe nicht alles, was dir an
Möglichkeiten zur Verfügung steht. Da gibt es zb noch die Struktur.
> Das wird aber irgendwann unübersichtlich denk ich.
Im Idealfall hast du EINEN Code, der ein Menü in all seinen Ausprägungen
behandeln kann. Die Daten steuern die Menüabaerbeitung. Der Code
interpretiert nur die Daten in der aufgebauten Datenstruktur. So ein
Design beginnt damit, dass man sich auf Papier mit Bleistift die
Datenstruktur anhand eines konkreten Beispiels aufmalt. Dann sieht man
schon, wie man das ganze strukturiert.
Aber wenn dir das Pointer Array schon kopfzerbrechen bereitet hat,
solltest du dir vielleicht erst mal die Latte nicht so hoch legen, bis
du deine Programmiersprache nicht nur rudimentär beherrscht sondern
tatsächlich mit den Sprachmitteln auch umgehen kannst.
@KHB
Danke für die tolle Darstellung. Wie biegen sich die Zeiger, wenn ich
keinen linearen Speicher, sondern RAM und ROM getrennt mit gleichem
Adressbereich habe?
embedded schrieb:> @KHB> Danke für die tolle Darstellung. Wie biegen sich die Zeiger, wenn ich> keinen linearen Speicher, sondern RAM und ROM getrennt mit gleichem> Adressbereich habe?
Im Prinzip genau gleich. Denn in der Darstellung ist das ja
uninteressant. Du musst nur im Hinterkopf behalten was in welchem
Speicher liegt (kann nicht schaden, wenn man sich das in der Zeichnung
markiert) und je nach Compiler dann eben die entpsrechende Umsetzung in
den C Code machen. Je nach Compiler ist das unterschiedlich. Bei manchen
kommt dann eben zb ein 'const' in die Datenstruktur rein, bei anderen
wieder gibt es spezielle Zugriffsfunktionen für zb den ROM Bereich.
Aber grundsätzlich fürs Design ist das erst mal recht uninteressant. In
der Zeichnung ist ein Pointer nichts anderes als ein Pfeil, der in einem
Kästchen anfängt und dessen Spitze irgendwo anders hinzeigt.
Ich hab mir mal Gedanken dazu gemacht, ich denke der Ansatz wäre sehr
einfach bezüglich weil ich in einem späteren Switch case die id abfragen
kann sollte man zb. in dieser Menü Ebene was abfragen wollen.
Strukturen kenne ich noch, das wird aber jetzt eine Struktur der sich
wohl ein Array befinden muss
struct menu{
const char* Menu_name; // Menue Name
int id; // Menue ID,damit ich mich orientieren
kann
int Number; // Anzahl der Submenues
{
"Submenue 1, id" //Name des Submenues mit der ID
"Submenue ....
......
}
}
}
Das Array würde dann so aussehen
menuEntry []={Submenue 1, id}
Jetzt stellt sich mir aber die Frage wie mache ich die Anzahl der Array
s variable ich habe ja unterschiedlich viele Sub menues
menuSet []={SubSet_1, id}
menueHome []={SubSet_2, id}
....
Wäre der Ansatz okay ? Ich weiß nur gerade einfach nicht wie ich mit dem
Array umgehen muss...
Gruß
Zum Array wäre mir noch was eingefallen, ich verpacke die arrays wieder
in eine Struktur , dann wäre die Anzahl doch variable ?
struct menu{
const char* Menu_name; // Menue Name
int id; // Menue ID,damit ich mich orientieren kann
int Number; // Anzahl der Submenues
struct Sub_menue[]; //
}
}
Und dann habe ich eine Struct in dem sich die Arrays finden mit zb dem
Namen und wieder der ID
Damit hätte ich auch alle Parameter mitgeliefert die ich für ein Menü
brauche
-Anzahl Submenues damit ich Anfang und Ende kenne.
-Id damit ich den Menue abschnitte kenne
-Und den Namen zur ausgabe am Display.
Was soll "strukt Sub_menue [];" sein? Da fehlt irgendwie ein
Variablenname oder der Typ (je nachdem was Sub_menue sein soll).
Außerdem ist struct falsch geschrieben. Compilierst du deinen Code gar
nicht zwischendurch?
Hast du mitlerweile das C Buch von Anfang bis Ende gelesen und bist
jetzt C-Meister und möchtest unbedingt flexible array member benutzen?
Wenn nicht dann überleg dir bitte eine andere Speichermöglichkeit, die
ohne unterschiedlich große Arays in structs auskommt. Z.B. irgendwas mit
Pointern.
Danke nett für deine Antwort, besonders nett der Hinweis das ich mich
bei einem pseudo Code vertippt habe.
Es gibt auch noch Anfänger hier das sollte man nicht vergessen, zu dem
sieht man bei mir das ich mir nicht die Arbeit machen lasse und selbst
mit Ideen komme. C und C++ ist bei mir einfach auch schon mal wieder
lange her!!!
Man kann sich auch anständig unterhalten oder ?
Und zum strukt Sub_menue []; alias struct Sub_menue [];
ja zu diesem Datentyp bin ich mir nicht wirklich sicher , zumal ich mir
die Frage stelle ob das möglich ist.
Mit Stukturen zu arbeiten wäre mir auf anhieb einleuchtend, ich lass
mich aber gern eines besseren belehren,..
Gruß
Der Grund warum hier mehrere zu einem C Buch raten ist, dass du
offensichtlich Defizite bei wichtigen Themen wie z.B. Pointern hast.
Viele deiner Antworten sind irgendwie hingeschriebener C Code oder wie
du ja jetzt sagst Pseudo-Code. Ohne richtiges Verständnis welche
Konstruktionen es in C gibt und welche nicht kommt man meistens nicht
weit. In Pseudo-Code kann man theoretisch alles hinschreiben, aber ob
das in C dann so umzusetzen ist, ist noch eine ganz andere Frage. Wenn
ich mir ein Design überlege dann schreibe ich das direkt in der
Programmiersprache hin, in der ich es auch umsetzen möchte und sehe dann
spätestens beim Compilieren ob das so überhaupt funktioniert.
Um auf dein eigentliches Problem zurückzukommen: Du möchtest eine
Menüstruktur mit Funktionen für einzelne Menüpunkte, sowie Untermenüs
darstellen. Das Ganze soll auf einem µC laufen? Hast du nirgendwo
erwähnt scheinbar. Arrays mit variabler Länge in structs gibt es zwar in
C, ist aber eher ein spezial Feature und sollte man nicht unbedingt
verwenden, da es immer anders geht. Der ursprüngliche Ansatz mit einem
Array von char* war gar nicht so schlecht. Wenn man statt char* ein
struct für ein Menüeintrag erstellt kommt man schon weiter. Ich habe mir
jetzt in ein paar Minuten mal diese Struktur überlegt:
1
struct MenuItem
2
{
3
const char* name;
4
void (*func)(void);
5
MenuItem* submenu;
6
};
7
8
// Beispielmenü
9
MenuItem submenu[] = {
10
{"First submenu function", &sfunc1, NULL},
11
{"Second submenu function", &sfunc2, NULL},
12
{NULL, NULL, NULL}
13
};
14
15
MenuItem mainMenu[] = {
16
{"First function", &func1, NULL},
17
{"Submenu", NULL, submenu},
18
{"Second function", &func2, NULL},
19
{NULL, NULL, NULL}
20
};
Ein Menüeintrag besteht aus einem Namen, einem Functionpointer (bitte
Nachlesen wenn dir das nichts sagt), sowie einem Pointer auf ein
Untermenü. Falls beim Auswählen eines Menüpunktes eine Funktion
aufgerufen werden soll trägst du die Funktion in den Functionpointer
ein. Versteckt sich hinter einem Menüeintrag ein Untermenü dann trägst
du den submenu Pointer ein. Die einzelnen Menüs werden dann wieder in
Arrays gespeichert, mit einem abschließenden Menüeintrag, der nur aus
NULL Einträgen besteht. Der NULL Eintrag markiert das Ende eines Menüs.
Dadurch kann man einfach auf ein Untermenü verweisen und muss nicht auch
noch die Länge irgendwo mitgeben.
Bin gerade unterwegs und danke für deine Antwort, ich hab das ganze
jetzt schnell überflogen.
Ganz kurz aber noch-->
MenuItem mainMenu[] = {
{"First function", &func1, NULL},
{"Submenu", NULL, submenu},
{"Second function", &func2, NULL},
{NULL, NULL, NULL}
};
Main Menue ist ja der oberste Menuepunkt, bei den Submenues was wäre für
dich jetzt eine First function und eine Second funktion?
Wenn ich die Hierarchie richtig verstanden habe
dann würde das in meinem Fall so aussehen -->
MenuItem mainMenu[] = {
{""Main"",Submenue_menue, NULL},
{"Data Log",Submenue_Datalog, Null},
{"Diagnostic",Submenue Diagnistic, NULL},
{NULL, NULL, NULL}
};
MenuItem Submenue_Datalog[] = {
{""Sub1",Sub11,&func0 },
{" Sub2",Sub12,&func1},
{" Sub3",Sub13,&func2},
{NULL, NULL, NULL}
}
Ich versuch das jetzt mal umzusetzen, klingt alles noch logisch danke.
Gruß