Forum: PC-Programmierung 2d array in c erste spalte string, zweite spalte uint8


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Frank (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich möchte gerne in c einen 2dimensionalen array erstellen, wobei die 
erste spalte strings enthalten soll und die zweite spalte werte

z,B.
["A"][1]
["B"][2]
usw.

aber ich kann ja nur
uint8_t array[][]
oder
char array[][]

beim ersten habe ich aber beides mal uint8 und beim zweiten habe ich 
beides mal char.
geht so etwas in C überhaupt?
in C# gäbe es ja eine liste, mit der das möglich wäre

von Oliver S. (oliverso)


Bewertung
0 lesenswert
nicht lesenswert
struct

Oliver

von Programmiersprachentheaterintendant (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Frank schrieb:
> Ich möchte gerne in c einen 2dimensionalen array erstellen, wobei die
> erste spalte strings enthalten soll und die zweite spalte werte
>
> z,B.
> ["A"][1]
> ["B"][2]
> usw.
>
> aber ich kann ja nur
> uint8_t array[][]
> oder
> char array[][]
>
> beim ersten habe ich aber beides mal uint8 und beim zweiten habe ich
> beides mal char.

Richtig. Wilkommen bei der niederen "Hoch-"Sprache C.

Wenn Du es geordnet anstellst, hast Du immerhin in beiden Feldern mit 
dem selben Index der  korrespondierende String und Zahlenwert.

Die nächste Evoltionsstufe ist dann in der Tat ein Feld von 
Strukturen.

Bei beiden muss jedoch die Umrechnung von Suchstring zu Index als 
Zwischenschritt ausprogrammiert werden. Gute Übung!
Stichwort: "Algorithmen und Datenstrukturen"

Da sowas bereits viele vor dir getan haben, suche und evaluiere eine 
gebrauchsfertige Bibliothek welche dir o.g. Übung durch eine andere 
ablöst.

von cppbert (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Frank schrieb:
> in C# gäbe es ja eine liste, mit der das möglich wäre

Auch nicht ohne struct oder meinst du ein Dictionary?

von Frank (Gast)


Bewertung
0 lesenswert
nicht lesenswert
cppbert schrieb:
> Auch nicht ohne struct oder meinst du ein Dictionary?

Ja, oder ein Dictionary. Ich weiß nicht mehr genau wie es hieß. Weiß 
aber, dass es sowas gab.

Oliver S. schrieb:
> struct
>
> Oliver

oh ja, das hätte mir auch einfallen können.Besten dank.

Doch leider habe ich probleme damit
#include <stdint.h>
#include <string.h>
#include <stdio.h>

typedef struct
{
  int16_t jahr;
  uint8_t monat;
  uint8_t tag;
}DATUM;

typedef struct
{
  char ereignis[100];
  DATUM datum;
}CARDS;

static void init_cards(CARDS *cards[]);

int main(int argc, char *argv[])
{

  CARDS* cards[5];

  init_cards(cards);
  printf("initialisierung fertig\n\n");

  for(uint8_t x=0; x<1; x++)
  {
    printf("%s Jahr: %d   Monat %d   Tag: %d\n", cards[x]->ereignis, cards[x]->datum.jahr, cards[x]->datum.monat, cards[x]->datum.tag);
  }
  return 0;
}

static void init_cards(CARDS *cards[])
{
  printf("beginne initialisierung\n\n");
  strcpy(cards[0]->ereignis, "A");
  cards[0]->datum.jahr = 1;
  cards[0]->datum.monat = 1;
  cards[0]->datum.tag = 1;

  strcpy(cards[1]->ereignis, "B");
  cards[1]->datum.jahr = 2;
  cards[1]->datum.monat = 2;
  cards[1]->datum.tag = 2;

  printf("ende initialisierung\n\n");
}

Wenn ich in der Funktion init_cards nur cards[0] beschreibe und cards[1] 
auskommentiere (die anderen kommen dann später noch hinzu), funktioniert 
alles. Aberwenn ich cards[1] beschreiben möchte, stürzt das Programm ab. 
Also es kommt nicht mehr zum printf "ende initialisierung".

Aber warum? ich übergeben doch den ganzen array und dieser ist 5 
Elemente lang.

von Dirk B. (dirkb2)


Bewertung
0 lesenswert
nicht lesenswert
Frank schrieb:
> CARDS* cards[5];

Das sind nicht 5 CARDS sondern ein Zeiger auf 5 Cards.

Kannst mal mit sizeof(CARDS) überprüfen.

von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht lesenswert
Frank schrieb:
> Aber warum? ich übergeben doch den ganzen array und dieser ist 5
> Elemente lang.

Ja, aber es handelt sich um 5 Zeiger, die ins Gemüse zeigen 
(uninitialisiert) Und dieses Gemüse versuchst du dann zu beschreiben.

Frank schrieb:
> CARDS* cards[5];

Damit erzeugst du 5 Zeiger auf Karten, aber keine einzige Karte, in 
die du irgendwelche Werte schreiben könntest.

von Dirk B. (dirkb2)


Bewertung
0 lesenswert
nicht lesenswert
Frank schrieb:
> Aber warum? ich übergeben doch den ganzen array

Das geht in C nicht. Es wird die Adresse vom ersten Element übergeben.

von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht lesenswert
Dirk B. schrieb:
> Das sind nicht 5 CARDS sondern ein Zeiger auf 5 Cards.

Umgekehrt: Es sind 5 Zeiger auf jeweils eine Card, aber es sind eben nur 
die Zeiger.

von Dirk B. (dirkb2)


Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Umgekehrt:

Ja. Ich kann es leider nicht mehr löschen.

von Frank (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Guten morgen und erst einmal Danke für die Hinweise.
Zum laufen habe ich es dennoch noch nicht bekommen.
#include <stdint.h>
#include <string.h>
#include <stdio.h>

typedef struct
{
  int16_t jahr;
  uint8_t monat;
  uint8_t tag;
}DATUM;

typedef struct
{
  char ereignis[100];
  DATUM datum;
}CARDS;

static void init_cards(CARDS cards[]);

int main(int argc, char *argv[])
{

  CARDS cards[5];

  init_cards(cards);
  //init_cards(&cards);
  printf("initialisierung fertig\n\n");

  for(uint8_t x=0; x<1; x++)
  {
    printf("%s Jahr: %d   Monat %d   Tag: %d\n", cards[x].ereignis, cards[x].datum.jahr, cards[x].datum.monat, cards[x].datum.tag);
  }
  return 0;
}

static void init_cards(CARDS cards[])
{
  printf("beginne initialisierung\n\n");
  strcpy(cards[0].ereignis, "A");
  cards[0].datum.jahr = 1;
  cards[0].datum.monat = 1;
  cards[0].datum.tag = 1;

  strcpy(cards[1].ereignis, "B");
  cards[1].datum.jahr = 2;
  cards[1].datum.monat = 2;
  cards[1].datum.tag = 2;

  printf("ende initialisierung\n\n");
}

Das Problem ist immer noch das selbe.

Ist es denn schon die richtige Richtung?

von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht lesenswert
Frank schrieb:
> Ist es denn schon die richtige Richtung?

Ja, das sieht besser aus. Ich kann auch keinen Fehler sehen, abgesehen 
davon, dass du nur das erste Element ausgibst:
for(uint8_t x=0; x<1; x++)
Nach dem ersten Durchlauf ist x nicht mehr kleiner als 1, also wird die 
Schleife nur genau einmal durchlaufen.

Es funktioniert bei auch ohne Probleme.

: Bearbeitet durch User
von cppbert (Gast)


Bewertung
0 lesenswert
nicht lesenswert
> Ist es denn schon die richtige Richtung?

Wird besser

Mit

sizeof(Cards)/sizeof(Cards[0])

Bekommst du die groesse des Arrays

Und ich wuerde bei der init cards eher Card* (anstatt Cards[]) und int 
Count uebergeben

von cppbert (Gast)


Bewertung
0 lesenswert
nicht lesenswert
CARDS in CARD umbenennen

Und die zugriffe abkuerzen

CARD* card = &cards[x]; // oder cards+x

card->datum.jahr ...

von Frank (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Nach dem ersten Durchlauf ist x nicht mehr kleiner als 1, also wird die
> Schleife nur genau einmal durchlaufen.

Da hast du recht :). Aber so weit kommt es ja gar nicht. Bekomme also 
noch nicht einmal das erste Element ausgegeben.

cppbert schrieb:
> Und ich wuerde bei der init cards eher Card* (anstatt Cards[]) und int
> Count uebergeben

Ja, das würde ich später auch machen wollen (also zumindest eine länge 
übergeben. Aber zunächst wollte ich so wenig sachen wie möglich. Läuft 
ja mit weniger auch nicht ;)

cppbert schrieb:
> CARDS in CARD umbenennen

OK. JA, wenn man genau überlegt ist das richtig. Ich beschreibe ja nur 
eine Karte im Struct. Vom struct aber mehrere. deswegen dann cards :)

cppbert schrieb:
> CARD* card = &cards[x]; // oder cards+x

Das habe ich nicht ganz verstanden. Wo muss dass denn hin? Bzw. was 
bewirkt das?


Noch einmal besten dank für die Hinweise

von Dirk B. (dirkb2)


Bewertung
0 lesenswert
nicht lesenswert
Frank schrieb:
> Aber so weit kommt es ja gar nicht. Bekomme also
> noch nicht einmal das erste Element ausgegeben.

Welche Ausgabe kommt?
Startest du auch das richtige (neuste) Programm?
Ein
puts(__TIME__);
 am Anfang von main() kann da helfen.

: Bearbeitet durch User
von cppbert (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Frank schrieb:
> Das habe ich nicht ganz verstanden. Wo muss dass denn hin? Bzw. was
> bewirkt das?

weniger schreiben, weniger Fehler

#define ARRAY_SIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))

for(uint8_t x=0; x<ARRAY_SIZE(cards); ++x)
{
  CARD* card = &cards[x];

    printf("%s Jahr: %d   Monat %d   Tag: %d\n", card->ereignis, card->datum.jahr, card->datum.monat, card->datum.tag);
  }

von cppbert (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Frank schrieb:
> Das habe ich nicht ganz verstanden. Wo muss dass denn hin? Bzw. was
> bewirkt das?

du solltest dur "dringenst" ein C Pointer Tutorial anschauen - damit 
wirst du in C ständig konfrontiert - muss es also können

https://www.tutorialspoint.com/cprogramming/c_pointers.htm

von cppbert (Gast)


Bewertung
0 lesenswert
nicht lesenswert
cppbert schrieb:
> #define ARRAY_SIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))
>
> for(uint8_t x=0; x<ARRAY_SIZE(cards); ++x)
> {
>   CARD* card = &cards[x];
>
>     printf("%s Jahr: %d   Monat %d   Tag: %d\n", card->ereignis,
> card->datum.jahr, card->datum.monat, card->datum.tag);
>   }

du kanns die Schleifen z.B. auch so schreiben

#define ARRAY_SIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))

for(CARD* card = &cards[0]; card != &cards[0]+ARRAY_SIZE(cards); ++card)
{
    printf("%s Jahr: %d   Monat %d   Tag: %d\n", card->ereignis, 
card->datum.jahr, card->datum.monat, card->datum.tag);
  }

sehr viele Wege führen in C nach Rom - und es ist gut die Varianten zu 
verstehen, damit man weniger Fehler macht, schneller ist

von cppbert (Gast)


Bewertung
0 lesenswert
nicht lesenswert
cppbert schrieb:

totaler Quatsch - sorry
for(CARD* card = cards; card != cards+ARRAY_SIZE(cards); ++card)
{
    printf("%s Jahr: %d   Monat %d   Tag: %d\n", card->ereignis,
card->datum.jahr, card->datum.monat, card->datum.tag);
}

oder auch
CARD* begin = &cards[0] // oder einfach cards;
CARD* end = begin+ARRAY_SIZE(cards);

for(card = begin; card != end; ++card)
{
  printf("%s Jahr: %d   Monat %d   Tag: %d\n", card->ereignis,
  card->datum.jahr, card->datum.monat, card->datum.tag);
}

von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht lesenswert
cppbert schrieb:
> Frank schrieb:
>> Das habe ich nicht ganz verstanden. Wo muss dass denn hin? Bzw. was
>> bewirkt das?
>
> weniger schreiben, weniger Fehler

So viel macht das hier aber nicht wirklich aus.

> #define ARRAY_SIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))
>
> for(uint8_t x=0; x<ARRAY_SIZE(cards); ++x)

Es ist gefährlich, das einem Einsteiger so zu empfehlen. Das nächste, 
was der nämlich macht, ist, das in eine Funktion auslagern und sich dann 
wundern, warum es plötzlich nicht mehr funktioniert.

von cppbert (Gast)


Bewertung
0 lesenswert
nicht lesenswert
>> Frank schrieb:
>>> Das habe ich nicht ganz verstanden. Wo muss dass denn hin? Bzw. was
>>> bewirkt das?
>>
>> weniger schreiben, weniger Fehler
>
> So viel macht das hier aber nicht wirklich aus.

aber Pointer sollte er schon kennen, oder?


>> #define ARRAY_SIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))
>>
>> for(uint8_t x=0; x<ARRAY_SIZE(cards); ++x)
>
> Es ist gefährlich, das einem Einsteiger so zu empfehlen. Das nächste,
> was der nämlich macht, ist, das in eine Funktion auslagern und sich dann
> wundern, warum es plötzlich nicht mehr funktioniert.

wenn es nicht funktioniert ist es doch nicht gefährlich, oder?

ich wollte einfach nur ein paar Grundlagen aufzeigen, mehr nicht

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.

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