mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik strlen bei mehrdimensionalen Strings


Autor: Bruno (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: w124Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Bruno
was spricht hiergegen:
char xxx[4][6] = {{"as"},{"asdf"},{"fdas"},{"qwer"}};
int iLength;
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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bruno (Gast)
Datum:

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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bruno (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Winfried J. (Firma: Nisch-Aufzüge) (winne)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bruno (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bruno (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.
struct Text {
  char* m_Deutsch;
  char* m_Englisch;
};
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:
struct DisplayScreen {
  Text       m_FixText;
  ScrollArea m_ScrollArea;
};

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.
struct ScrollArea {
  uint8_t  m_Size;    // 255 Einträge werden ja wohl genug sein
  Text**   m_Texte;   // Pointer auf ein Array von Texten.
};

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)
#include <stdio.h>

typedef struct Text_ {
  char* m_Deutsch;
  char* m_Englisch;
} Text;

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

typedef struct DisplayScreen_ {
  Text       m_FixText;
  ScrollArea m_ScrollArea;
} DisplayScreen;

Text Display1Text[] =
  {
    { "Hilfe", "Help" },
    { "Bearbeiten", "Edit" },
    { "Beenden", "Exit" }
  };

DisplayScreen Display1 =
  {  { "Hauptseite", "Main Screen" },
     { sizeof( Display1Text ) / sizeof( *Display1Text ),
       Display1Text
     }
  };
 
int Language = 0;

char* GetCurrentText( Text* pText )
{
  if( Language == 0 )
    return pText->m_Deutsch;
  return pText->m_Englisch;
}

void Display( DisplayScreen* Screen )
{
  size_t i;
  
  printf( "FixZeile: %s\n", GetCurrentText( &Screen->m_FixText ) );
  
  for( i = 0; i < Screen->m_ScrollArea.m_Size; ++i )
    printf( "ScrollZeile: %s\n", GetCurrentText( &Screen->m_ScrollArea.m_Texte[i] ) );
  
}

int main()
{
  Display( &Display1 );

}

Autor: Bruno (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Danke. Jetzt muß ich aber erst mal den Input verarbeiten.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bruno (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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!)
#include <stdio.h>

struct DisplayScreen_;

// Ein uebersetzbarer Text
typedef struct Text_ {
  char* m_Deutsch;
  char* m_Englisch;
} Text;

// Ein Eintrag (Menuepunkt) im Scrollbereich
typedef struct MenueEntry_ {
  Text                   m_Text;
  struct DisplayScreen_* m_pSubDisplay;
} MenuEntry;

// Der Scrollbereich besteht aus vielen Menuepunkten
typedef struct ScrollArea_ {
  size_t     m_Size;      // 255 Einträge werden ja wohl genug sein
  MenuEntry* m_Entries;   // Pointer auf das Array von Menüpunkten
} ScrollArea;

// Ein komplettes Display besteht aus: Fixtext und den Menüpunkten
typedef struct DisplayScreen_ {
  Text       m_FixText;
  ScrollArea m_ScrollArea;
} DisplayScreen;

// "Bearbeiten" Display
MenuEntry EditMenu[] =
  {
    { { "Kopieren",     "Copy" },  NULL },
    { { "Ausschneiden", "Cut" },   NULL },
    { { "Einsetzen",    "Paste" }, NULL }
  };

DisplayScreen EditScreen =
  {  { "Bearbeiten", "Edit Screen" },
     { sizeof( EditMenu ) / sizeof( *EditMenu ),
       EditMenu
     }
  };

// Hauptseite
MenuEntry MainMenu[] =
  {
    { { "Hilfe", "Help" },      NULL },
    { { "Bearbeiten", "Edit" }, &EditScreen },
    { { "Beenden", "Exit" },    NULL }
  };

DisplayScreen MainScreen =
  {  { "Hauptseite", "Main Screen" },
     { sizeof( MainMenu ) / sizeof( *MainMenu ),
       MainMenu
     }
  };
 
int Language = 0;

char* GetCurrentText( Text* pText )
{
  if( Language == 0 )
    return pText->m_Deutsch;
  return pText->m_Englisch;
}

void DisplayMenu( MenuEntry* Entries, size_t NrEntries )
{
  size_t i;
  
  for( i = 0; i < NrEntries; ++i ) {
    printf( "ScrollZeile: %s\n", GetCurrentText( &Entries[i].m_Text ) );
    if( Entries[i].m_pSubDisplay != NULL )
      printf( "Eintrag verlinkt mit Screen: %s\n", GetCurrentText( &Entries[i].m_pSubDisplay->m_FixText ) );
  }
}

void Display( DisplayScreen* Screen )
{
  printf( "FixZeile: %s\n", GetCurrentText( &Screen->m_FixText ) );
  
  DisplayMenu( Screen->m_ScrollArea.m_Entries, Screen->m_ScrollArea.m_Size );
}

int main()
{
  Display( &MainScreen );

}

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

Autor: Bruno (Gast)
Datum:

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.