Forum: Mikrocontroller und Digitale Elektronik strlen bei mehrdimensionalen Strings


von Bruno (Gast)


Lesenswert?

Hallo zusammen,

habe mal wieder eien Frage. Ist es möglich mit der Funktion strlen die 
Anzahl der einzelnen Strings anzeigen zu lassen?
z.B.:

char *xxx[][6] = { {"xxx"} , {"yyy"}.....;

Ist es möglich die Anzahl (in diesem Fall 6) der Strings anzeigen zu 
lassen??

Gruß Bruno

von w124Dennis (Gast)


Lesenswert?

Hallo Bruno
was spricht hiergegen:
1
char xxx[4][6] = {{"as"},{"asdf"},{"fdas"},{"qwer"}};
2
int iLength;
3
iLenth = strlen(xxx[0]);
???

aber vorsicht die funktion gibt die länge des strings zurück, bedenke 
das noch eine NULL am ende jedes string steht.

gruß Dennis

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Du definierst ein zweidimensionales Feld von Pointern. Du kannst die 
Anzahl der Pointer insgesamt über sizeof des Feldes geteilt durch sizeof 
eines Elementes herausfinden. Die Grösse der zweiten Dimension kennst du 
doch (6) - warum willst du die berechnen? Ich würde erwarten, dass du 
die Grösse der ersten Dimension ermitteln willst... dann wäre die 
Gesamtzahl der Pointer durch die bekannte Dimension zu teilen.

von Bruno (Gast)


Lesenswert?

Ich habe eine Menge solcher Daten und möchte das in einer Funktion 
atomatisieren. Die Anzahl der Strings ist aber unterschiedlich.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ich würde das Pointerfeld in eine struct packen und die Dimensionen als 
weitere struct-Elemente mitführen.

Beim Befüllen zur Compiletime kannst du die automatisch eintragen lassen 
und bist alle Sorgen zur Laufzeit los.

Bzw. wenn du das Feld dynamisch zu Laufzeit anlegst und befüllst, dann 
rechnest du einmal die Dimensionen aus, holst den Speicher und trägst 
die Werte ein und dann brauchst bei der Auswertung nur die Werte 
auszulesen statt jedesmal gross rumzurechnen.

von Bruno (Gast)


Lesenswert?

Hätte ich nicht da wieder das Problem das ich nicht weiß wie lang das 
Struct ist. Was ich in den Pointern ablege sind einzelne 
Displaybildschirme. Habe aber sicher an die 70 - 80 verschiedene 
Anzeigen mit verschiedenen längen. Ich möchte aber nur eine Funktion mit 
der ich alle Bildschirme anzeigen kann. Wenn ich das in einem Array 
mache kann ich das gut nummerieren. Das is auch etwas komplizierter, 
weil ich den ersten Eintrag immmer stehen lasse und den Rest scrollen 
muß. Aber ich lasse mich da gerne belehren.

von Karl H. (kbuchegg)


Lesenswert?

Zunächst mal.
Nein, strlen hilft dir da nicht wirklich weiter.

Was du machen kannst: Du kannst zb vereinbaren, dass
der letzte String in deinem Array ein leerer String sein
muss, er also eine strlen von 0 haben soll.

Dann kannst du einfach über das Array von Strings iterieren.
Wenn der leere String auftaucht, hast du alle abgearbeitet.

In ein ähnliches Horn bläst du, wenn du die Strings nicht
in einem 2D-Array ablegst, sondern ein Pointer-Array auf
Strings baust. Dort ist dann wieder vereinbarungsgemäß der
letzte Pointer ein NULL Pointer, denn du dann wieder einfach
feststellen kannst.

> Wenn ich das in einem Array mache kann ich das gut nummerieren.

Wie ist das zu verstehen? Dazu musst du in den meisten Fällen
die Anzahl der Strings im Vorfeld nicht wissen.

von Winfried J. (Firma: Nisch-Aufzüge) (winne) Benutzerseite


Lesenswert?

Hallo Bruno,

Unterteile doch dein Display in Abschnitte fester Größe so bekommen auch 
die die Strings eine solche.
Eine Struktur kann dann aus Displayadresse und zugehörigem String 
Konstanter länge bestehen. Das Array kann dann beliebig viele dieser 
Strukturen aufnehmen.

Zum Anzeigen übergibst du dann der Ausgaberoutine die Nummer der 
anzuzeigenden Struktur.

Deine Ausgaberoutine entnimmt dieser als erstes die Displayadresse,  und 
setzt den (unsichtbaren) Curser anschließend wird der String gesendet. 
Hier sind Strings konstanter Länge besonders geeignet, da so keine 
Fragmente der vorangegangen Anzeige auf dem Display zurückbleiben und 
der Anzeigebereich zuvor nicht gelöscht werden muss.

Ich habe auf diese Wiese ein 4-zeiliges display beschrieben und die Uhr 
oben rechts im sekundentakt aktualisiert.

Während die anderen Zeilen wechselnde Inhalte aufwiesen.

von Bruno (Gast)


Lesenswert?

Das Problem ist, das auf dem Display nicht alle Einträge gespeichert 
werden können. Der Controller kann das nicht verarbeiten (max 128 Zeilen 
und 16 Zeilen pro Eintrag). Hinzu kommt das die erte und letzte 
dargestellte Zeile fix ist. D.h. das ich die Einträge dazwischen über 
die Software scrollen muß. Daher muß ich mir über die Anzahl der 
Einträge was zurecht schustern. So habe ich mir das zumindest gedacht.

von Karl H. (kbuchegg)


Lesenswert?

Ich denke es wird jetzt mal Zeit dass du etwas weiter ausholst,
was du da machen willst. Welche Anforderungen hast du genau,
wie soll dein Display aussehen, welche Werte musst du speichern?
Sind die Texte regelmässig angeordnet, was hat es mit den fixen
Bereichen auf sich.

Je mehr ich da mitlese, desto mehr komme ich zur Überzeugung,
dass ein simples 2D String Array so nicht das wahre sein wird.

von Bruno (Gast)


Lesenswert?

Ich programmiere ein vollgraphisches Display 128 *128 Pixel). 
Dargestellt werde ca 70-80 verschiedene Screens. Die einzelnen 
Menüpunkte führen zu Unterpunkten und das geht dann noch 2 Schritte 
tiefer (4 Dimensionen). Jeden Sreen wollte ich in einem char *array in 
mindestens 2 Sprachen abspeichern.
Und die Screens wollte ich nach Auswahl der Sprache an eine funktion 
übergeben, die unabhänig von der Arraylänge mir das Display beschreibt. 
Hoffe ich habe mich einigermaßen verständlich ausgedrückt.

von Karl H. (kbuchegg)


Lesenswert?

OK.

Das würde ich so angehen:

Dein Display ist doch 2-geteilt. Zumindest habe ich das aus dem
obigen entnommen. Du hast einen Scrollbereich, in dem die
Menüpunkte durchscrollen (falls notwendig) und du hast einen
fixen Bereich, in dem der Text immer konstant bleibt.

Also würde ich mal damit anfangen, eine Struktur zu machen,
die genau diesen Sachverhalt beschreibt

Oh. Du willst mehrsprachig arbeiten. Das machen wir gleich mal
als aller erstes. Dazu bau ich eine Struktur, die die beiden
Sprachtexte zu einer Einheit gruppiert.
1
struct Text {
2
  char* m_Deutsch;
3
  char* m_Englisch;
4
};
Hier könnte man auch über den Einsatz eines Arrays nachdenken,
damit die eigentliche Sprachauswahl für die Anzeige simpler
zu machen ist (Sprachnummer = Index in das Array)

Zurück zum Display:
1
struct DisplayScreen {
2
  Text       m_FixText;
3
  ScrollArea m_ScrollArea;
4
};

Der Fixtext ist damit klar. Was ist mit der ScrollArea.
Dort sollen einen ganzen Haufen Texte angezeigt werden.
Also braucht man mal ein Array von Text (damits mehrsprachig
wird), und auch die Arraygröße wäre nicht schlecht (wenn man
nicht auf solche Dinge wie 'der letzte Eintrag muss NULL sein)
ausweichen will.
1
struct ScrollArea {
2
  uint8_t  m_Size;    // 255 Einträge werden ja wohl genug sein
3
  Text**   m_Texte;   // Pointer auf ein Array von Texten.
4
};

Ich hab in die ScrollArea absichtlich einen Pointer auf ein Array
reingesetzt, damit ich mich nicht mit Strukturen variabler Größe
rumschlagen muss. Aus irgendeinem Grund habe ich dagegen eine
Abneigung :-)

In Summe könnte das dann zb so aussehen (ergänzt um ein paar
typedefs um die Schreibarbeit kleiner zu halten)
1
#include <stdio.h>
2
3
typedef struct Text_ {
4
  char* m_Deutsch;
5
  char* m_Englisch;
6
} Text;
7
8
typedef struct ScrollArea_ {
9
  size_t   m_Size;    // 255 Einträge werden ja wohl genug sein
10
  Text*    m_Texte;   // Pointer auf ein Array von Texten.
11
} ScrollArea;
12
13
typedef struct DisplayScreen_ {
14
  Text       m_FixText;
15
  ScrollArea m_ScrollArea;
16
} DisplayScreen;
17
18
Text Display1Text[] =
19
  {
20
    { "Hilfe", "Help" },
21
    { "Bearbeiten", "Edit" },
22
    { "Beenden", "Exit" }
23
  };
24
25
DisplayScreen Display1 =
26
  {  { "Hauptseite", "Main Screen" },
27
     { sizeof( Display1Text ) / sizeof( *Display1Text ),
28
       Display1Text
29
     }
30
  };
31
 
32
int Language = 0;
33
34
char* GetCurrentText( Text* pText )
35
{
36
  if( Language == 0 )
37
    return pText->m_Deutsch;
38
  return pText->m_Englisch;
39
}
40
41
void Display( DisplayScreen* Screen )
42
{
43
  size_t i;
44
  
45
  printf( "FixZeile: %s\n", GetCurrentText( &Screen->m_FixText ) );
46
  
47
  for( i = 0; i < Screen->m_ScrollArea.m_Size; ++i )
48
    printf( "ScrollZeile: %s\n", GetCurrentText( &Screen->m_ScrollArea.m_Texte[i] ) );
49
  
50
}
51
52
int main()
53
{
54
  Display( &Display1 );
55
56
}

von Bruno (Gast)


Lesenswert?

Danke Danke. Jetzt muß ich aber erst mal den Input verarbeiten.

von Karl H. (kbuchegg)


Lesenswert?

Seh gerade, dass ich bei der Erklärung noch ein paar Dinge
anders gemacht habe als im endgültigen Programm.
Ich habe hier drauf los geschrieben und dann die Fragmente
testweise kompiliert. Also: Das Programm gilt.

von Bruno (Gast)


Lesenswert?

Habe mir jetzt mal deine Zeilen angeschaut. Das ist schon schön 
vereinfacht. Was ich mich jetzt noch frage ist, wie ich eine Auswahl 
treffen könnte. Ursprünglich wollte ich die nummerierung nutzen um mit 
switch in Untermenüs zu navigieren. Aber vllcht kann ich das auch anhand 
der Tastendrücke realisieren.
Aber danke schonmal für deine wertvollen Tipps.

von Karl H. (kbuchegg)


Lesenswert?

Bruno wrote:

> treffen könnte. Ursprünglich wollte ich die nummerierung nutzen um mit
> switch in Untermenüs zu navigieren.


Du könntest zb, bei jedem Menüpunkt dazuschreiben, welches
Untermenü davon ausgelöst wird.

Dazu würde ich zb. vorschlagen, dass eine ScrollArea
nicht einfach nur aus einer Ansammlung von Text besteht, sondern
aus einer Ansammlung von Menüpunkten

Was ist wiederrum ein Menüpunkt?
Nun der besteht aus einem anzuzeigendem Text und einem Zeiger
in ein anderes Display, welches angezeigt werden soll, wenn
dieser Menüpunkt ausgewählt wird

struct DisplayScreen_;

typedef struct MenueEntry_ {
  Text                   m_Text;
  struct DisplayScreen_* m_pSubDisplay;
} MenuEntry;

typedef struct ScrollArea_ {
  size_t     m_Size;    // 255 Einträge werden ja wohl genug sein
  MenuEntry* m_Texte;   // Pointer auf ein Array von Texten.
} ScrollArea


Wieder als Testprogram (beachte die forward Deklaration am Anfang!)
1
#include <stdio.h>
2
3
struct DisplayScreen_;
4
5
// Ein uebersetzbarer Text
6
typedef struct Text_ {
7
  char* m_Deutsch;
8
  char* m_Englisch;
9
} Text;
10
11
// Ein Eintrag (Menuepunkt) im Scrollbereich
12
typedef struct MenueEntry_ {
13
  Text                   m_Text;
14
  struct DisplayScreen_* m_pSubDisplay;
15
} MenuEntry;
16
17
// Der Scrollbereich besteht aus vielen Menuepunkten
18
typedef struct ScrollArea_ {
19
  size_t     m_Size;      // 255 Einträge werden ja wohl genug sein
20
  MenuEntry* m_Entries;   // Pointer auf das Array von Menüpunkten
21
} ScrollArea;
22
23
// Ein komplettes Display besteht aus: Fixtext und den Menüpunkten
24
typedef struct DisplayScreen_ {
25
  Text       m_FixText;
26
  ScrollArea m_ScrollArea;
27
} DisplayScreen;
28
29
// "Bearbeiten" Display
30
MenuEntry EditMenu[] =
31
  {
32
    { { "Kopieren",     "Copy" },  NULL },
33
    { { "Ausschneiden", "Cut" },   NULL },
34
    { { "Einsetzen",    "Paste" }, NULL }
35
  };
36
37
DisplayScreen EditScreen =
38
  {  { "Bearbeiten", "Edit Screen" },
39
     { sizeof( EditMenu ) / sizeof( *EditMenu ),
40
       EditMenu
41
     }
42
  };
43
44
// Hauptseite
45
MenuEntry MainMenu[] =
46
  {
47
    { { "Hilfe", "Help" },      NULL },
48
    { { "Bearbeiten", "Edit" }, &EditScreen },
49
    { { "Beenden", "Exit" },    NULL }
50
  };
51
52
DisplayScreen MainScreen =
53
  {  { "Hauptseite", "Main Screen" },
54
     { sizeof( MainMenu ) / sizeof( *MainMenu ),
55
       MainMenu
56
     }
57
  };
58
 
59
int Language = 0;
60
61
char* GetCurrentText( Text* pText )
62
{
63
  if( Language == 0 )
64
    return pText->m_Deutsch;
65
  return pText->m_Englisch;
66
}
67
68
void DisplayMenu( MenuEntry* Entries, size_t NrEntries )
69
{
70
  size_t i;
71
  
72
  for( i = 0; i < NrEntries; ++i ) {
73
    printf( "ScrollZeile: %s\n", GetCurrentText( &Entries[i].m_Text ) );
74
    if( Entries[i].m_pSubDisplay != NULL )
75
      printf( "Eintrag verlinkt mit Screen: %s\n", GetCurrentText( &Entries[i].m_pSubDisplay->m_FixText ) );
76
  }
77
}
78
79
void Display( DisplayScreen* Screen )
80
{
81
  printf( "FixZeile: %s\n", GetCurrentText( &Screen->m_FixText ) );
82
  
83
  DisplayMenu( Screen->m_ScrollArea.m_Entries, Screen->m_ScrollArea.m_Size );
84
}
85
86
int main()
87
{
88
  Display( &MainScreen );
89
90
}

Wenn du bei einem Menüpunkt noch weitere Informationen brauchst,
dann hast du jetzt einen Platz an dem du jederzeit erweitern
kannst.

von Bruno (Gast)


Lesenswert?

Das mit der Zuweisung is ne super sache. Sollten noxh erweiterungen 
kommen kann ich die einfach einpflegen. Nochmal danke.

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.