Basics zu Arrays und Initialisierung Im Unterforum Microcontroller - Beschreibung: Hardware - Software - Ideen - Projekte
Autor |
Basics zu Arrays und Initialisierung |
|
|
|
|
BID = 717932
Teletrabi Schreibmaschine
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif)
Beiträge: 2317 Wohnort: Auf Anfrage...
|
|
Moin,
möchte hier ein Programmstricken, dass eine - aus Erweiterungsgründen flexible - Anzahl Elemente überwacht. Eigenschaften der Elemente wie diverse Statusflags usw. werden in einem Vektor abgelegt, der eine struct aus den flags, ein paar int-Werten sowie auch einen Bezeichnungstext enthält.
Um Probleme durch Eingabe zu langer Texte zu vermeiden, wollt ich die Eingaben aus einer Initalisierungs-Variablen ala char[] Name = "Bla1" in die Elemente kopieren und bei zu langen bezeichnungen ggf. nach X Zeichen das Kopieren Abbrechen und \n dranhängen, um eine definierte maximale Bezeichnungslänge zu haben.
Um es konfigurierbar zu halten, wollt ich die Texe als #define Text1 "bla1" in einer Header-Datei Sammeln.
Soo, nur wie löse ich das ganze jetzt möglichst flexibel, ohne im Programmcode selber rumzuwuseln? Ich halte es noch für akzeptabel die Anzahl der Elemente sowie die (ggf überlangen) Namen per Hand eizugeben. Kann ich Beispielsweise ein Array initalisieren ala
#define Elementeanzahl 4
char[Elementeanzahl][] NameArray {"bla1", "bla2", "blubb3", "dumdidum4"};
=> anschließend Kopierschleife, die Elememtananzahl durchläufe zu je max 4 Zeichen in die Felder der jeweiligen Structures kopiert.
sodass die Länge der zweiten Dimension automatisch bestimmt wird in Abhängigkeit vom längsten einkonfigurieten Text?
|
|
BID = 717937
DonComi Inventar
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif)
Beiträge: 8605 Wohnort: Amerika
|
|
Moin!
Ist die Zielumgebung ein µC?
Zitat :
| in einem Vektor abgelegt, der eine struct aus den flags, ein paar int-Werten sowie auch einen Bezeichnungstext enthält. |
Also so:
struct Eigenschaft
{
int nummern;
int flags;
char bezeichner[maximale_String_Länge];
} Eigenschaften[Anzahl_der_Elemente];
?
Zitat :
| Um Probleme durch Eingabe zu langer Texte zu vermeiden, wollt ich die Eingaben aus einer Initalisierungs-Variablen ala char[] Name = "Bla1" in die Elemente kopieren und bei zu langen bezeichnungen ggf. nach X Zeichen das Kopieren Abbrechen und \n dranhängen, um eine definierte maximale Bezeichnungslänge zu haben. |
Das erledigt man dann in so einer Art Konstruktor,m der den Vektor mit allen Werten initialisiert.
Nachteil dabei ist allerdings, dass die Werte im RAM zweimal vorliegen, nämlich einmal im Vektor aller Elemente sowie aus den rein statischen Zellen, die den Initialisierungstext enthalten.
Das ist nachteilig, man kann auch im Vektor bloß Zeiger auf die jeweiligen, statischen!, Texte ablegen:
...
char* bezeichner;
...
Im "Konstruktor" initialisiert richtet man die Zeiger dann auf die entsprechenden Strings, ohne kopieren zu müssen.
Gehen wir aber mal davon aus, dass die Strings im Vektor abgelegt werden, wobei der Bezeichner STRING_LÄNGE Zeichen enthalten darf, dann kann das so aussehen:
Header:
/* Alle Texte als kommaseparierte Liste: */
#define TEXTE "Text1", "Text2", "Text3", "..."
/* und maximale Stringlänge: */
#define TEXT_LÄNGE 4
Programmkode:
/* statisches Array mit den Texten: */
static char* stat_texte[] = {TEXTE};
/* Anzahl der Elemente (kann im Präprozessor berechnet werden): */
#define TEXT_ANZAHL (sizeof stat_texte/sizeof(char*))
/* Struktur (davon ein Vektor mit gleicher Anzahl an Elementen wie es Texte gibt): */
static struct Eigenschaft
{
int nummern;
int flags;
char bezeichner[TEXT_LÄNGE+1];
} Eigenschaften[TEXT_ANZAHL];
/* Struktur initialisieren: */
static void _ctor(void)
{
register unsigned char i;
for(i=0;i<TEXT_ANZAHL;i++)
{
strncpy(Eigenschaften[i].bezeichner, stat_texte[i], TEXT_LÄNGE);
Eigenschaften[i].bezeichner[TEXT_LÄNGE] = '\0';
}
}
So könnte das aussehen.
Es werden auf jeden Fall nur soviele Bytes kopiert, wie Platz vorhanden ist. Dann wird mit einem NUL, also Null-Byte, terminiert. \n ist ein Zeilenumbruch und terminiert den String nicht.
Das einzige, was benötigt wird, sind die diversen Bezeichner (Texte), der Rest erledigt sich automatisch. Das einzige, was im Programm noch erledigt werden muss, ist, den Vektor zu initialisieren (_ctor).
Nachteile sind aber weiterhin:
1. Die Strings sind eigentlich doppelt vorhanden und überlange Texte verbrauchen auf jeden Fall unnötig Speicherplatz. Mit dem Präprozessor kommt man nicht groß weiter, denn Zuweisungen wie
static char text[5] = "Hallogggggg";
Werden ganz brav (gibt beim GCC ne Warnung) umgesetzt: Fünf Bytes (die ersten) werden im Array abgelegt, es fehlt aber die Terminierung! Absolut tödlich, wenn man mit reinen C-Strings arbeitet.
Arbeitet man jedoch mit Zeigern im Vektor, werden die Strings bei statischer Zuweisung nur einmal im RAM abgelegt, dafür fehlt entweder die Terminierung (String zu lang) oder aber man kann sie nicht in der Länge beschänken.
Wird das ganze auf AVRs umgesetzt, empfiehlt es sich außerdem, die konstanten Strings im ROM abzulegen. Der Datentyp heißt dann prog_char* und pgmspace.h muss inkludiert werden.
Edit:
Man kann _ctor sogar so mit Attributen versehen, dass der Konstruktor automatisch ausgeführt wird, also im "Konstuktorsegment" landet. Ergibt nur dann Sinn, wenn es eine argumentlose Prozedur ist.
P.S.: sollen die Bezeichner zur Laufzeit verändert werden können? Wenn nein, dann würde ich das wirklich statisch machen (auf Kosten einer nicht festgelegten Stringlänge).
_________________
[ Diese Nachricht wurde geändert von: DonComi am 2 Okt 2010 2:02 ] |
|
BID = 718028
DonComi Inventar
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif)
Beiträge: 8605 Wohnort: Amerika
|
Achso
Zitat :
|
sodass die Länge der zweiten Dimension automatisch bestimmt wird in Abhängigkeit vom längsten einkonfigurieten Text? |
Ist meines Wissens nicht möglich oder dann wieder nur über üblen Präprozessormissbrauch...
Möglich ist aber natürlich folgendes:
#define MEINE_TEXT "bla1", "bla2", "blablup3", "dumdiddeldum4"
static char Texte[][12] = {MEINE_TEXTE};
Sorge dann dafür, dass der Compiler pedantisch mit dem Source umgeht bzw. lass mehr Warnungen anzeigen. Ein guter Compiler meckert, wenn die Literale länger sind, als Platz verfügbar ist.
Das schützt aber beim GCC z.B. nicht davor, dass eine Zeichenkette mit der maximalen Länge ohne Terminierung abgelegt wird. Für die reicht der Platz nämlich aus, und es wird nicht gemotzt.
Wenn du dann reine C-String-Funktionen nimmst (wie sie die libc traditionell verarbeitet, bis man sie auf Operationen erweiterte, wo Stringlängen explizit mitangegeben werden (strncmp, strncpy, snprintf, ...), um Pufferüberläufen vorzubeugen) kann das völlig harmlos verlaufen (zufällige NUL am Stringende, aber in illegalem Speicherbereich) oder zum Gau führen. Die Sache wird also, ohne Meldung, unsicher. Das ist halt der größte Nachteil an C.
_________________
|
|
Zum Ersatzteileshop
Bezeichnungen von Produkten, Abbildungen und Logos , die in diesem Forum oder im Shop verwendet werden, sind Eigentum des entsprechenden Herstellers oder Besitzers. Diese dienen lediglich zur Identifikation!
Impressum
Datenschutz
Copyright © Baldur Brock Fernsehtechnik und Versand Ersatzteile in Heilbronn Deutschland
gerechnet auf die letzten 30 Tage haben wir 24 Beiträge im Durchschnitt pro Tag heute wurden bisher 32 Beiträge verfasst © x sparkkelsputz Besucher : 183078990 Heute : 6771 Gestern : 7451 Online : 341 18.2.2025 19:52 10 Besucher in den letzten 60 Sekunden alle 6.00 Sekunden ein neuer Besucher ---- logout ----viewtopic ---- logout ----
|
xcvb
ycvb
0.048131942749
|