mikrocontroller.net

Forum: PC-Programmierung struktur elemeten durchlaufen C


Autor: stupp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
struct person
{
  int personalnummer;
  char vorname[10];
  char nachnahme[10];
};


int main(void)
{

    struct person simon={1010, "simon", "klein"};
    struct person_s lucy={1011, "Sally", "Brown"};
    struct person_s sally={1012, "Lucy", "van Pelt"};

return 0;
}

wie kann ich nun in iner for-schleife diese daten ausgeben, also zuerst 
simon mit 101 und nachnahmen klein, dann sally..

Autor: Achim S. (achs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vorher:
#define countof(a) (sizeof(a)/sizeof(a[0]))

void doit(int i, const char *vorname, const char *nachnahme)
{
    ...
}
im main:
struct person *pa[]={simon, lucy, sally];
int i;
   
    for(i=0; i < countof(pa); i++)
    {
        doit(pa[i].personalnummer, pa[i].vorname, pa[i].nachnahme);
    }
}

Autor: Daniel Abrecht (daniel-a)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst sie zuerst einer Datenstruktur hinzufügen, die durchlaufen 
werden kann. Unten ein beispiel mittels eines Arrays. Wenn man 
nachträglich noch elemente hinzufügen will, wären eventuell linked lists 
praktischer. Es gibt unzählige weitere möglichkeiten das umzusetzen.
#include<stddef.h>
#include<stdio.h>

struct person
{
  int personalnummer;
  char vorname[10];
  char nachname[10];
};


int main(void)
{

    struct person simon={1010, "simon", "klein"};
    struct person lucy={1011, "Sally", "Brown"};
    struct person sally={1012, "Lucy", "van Pelt"};

    struct person* people[]={ &simon, &lucy, &sally };
    size_t people_count = sizeof(people) / sizeof(*people);

    for( size_t i=0; i<people_count; i++ ){
      printf( "nr %d, %s %s\n", people[i]->personalnummer, people[i]->vorname, people[i]->nachname );
    }

    return 0;
}

Edit: schonwieder zu langsam...

: Bearbeitet durch User
Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sofern ein Zugriff auf die einzelnen Variablen "simon", "lucy" und 
"sally" nicht benötigt wird, sondern die Variablen immer "durchlaufen" 
werden, kann man den Zwischenschritt mit dem Pointerarray auch 
weglassen.
#include<stddef.h>
#include<stdio.h>

struct person
{
  int personalnummer;
  char vorname[10];
  char nachname[10];
};


int main(void)
{

    struct person people[] =
    {
      {1010, "simon", "klein"},
      {1011, "Sally", "Brown"},
      {1012, "Lucy", "van Pelt"}
    };

    size_t people_count = sizeof(people) / sizeof(people[0]);

    for( size_t i=0; i<people_count; i++ ){
      printf( "nr %d, %s %s\n", people[i].personalnummer, people[i].vorname, people[i].nachname );
    }

    return 0;
}

Autor: Jobst Quis (joquis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achim S. schrieb:
> vorher:
>
> #define countof(a) (sizeof(a)/sizeof(a[0]))
> 
> void doit(int i, const char *vorname, const char *nachnahme)
> {
>     ...
> }
> 
> im main:
>
> struct person *pa[]={simon, lucy, sally];
> int i;
> 
>     for(i=0; i < countof(pa); i++)
>     {
>         doit(pa[i].personalnummer, pa[i].vorname, pa[i].nachnahme);
>     }
> }
> 

Der Sinn von struct ist doch gerade, keine endlosen Parameterlisten 
übergeben zu müssen, sondern nur einen Pointer.
> void doit(struct person *p)
 {
     ...
  printf( "nr %d, %s %s\n", p->personalnummer, p->vorname, p->nachname );
   ...
 }

...

for(i=0; i < countof(pa); i++)
  {
     doit(&pa[i]);
  }

: Bearbeitet durch User
Autor: stupp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

 struct person people[] =
    {
      {1010, "simon", "klein"},
      {1011, "Sally", "Brown"},
      {1012, "Lucy", "van Pelt"}
    };
// was passiert hier? und was ist der Unterschied zu meiner Variante:
// struct person simon={1010, "simon", "klein"}; // ich habe die variable simon vom Typ struct person erstellt. Und bei dir wird irgendwie alles in ein array gepakt oder wie soll ich mir das vorstellen?



    size_t people_count = sizeof(people) / sizeof(people[0]);
//sizeof(people) liefert doch 3 oder? also index 0-2 und was macht das teilen durch sizeof(people[0])?


Autor: jz23 (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
stupp schrieb:
> // was passiert hier? und was ist der Unterschied zu meiner Variante:
> // struct person simon={1010, "simon", "klein"}; // ich habe die
> variable simon vom Typ struct person erstellt. Und bei dir wird
> irgendwie alles in ein array gepakt oder wie soll ich mir das
> vorstellen?

Genau, hier werden die drei Personen in ein Array gepackt. So kann man 
danach eben "durchlaufen", was bei einzelnen Variablen nicht so leicht 
geht.

stupp schrieb:
> //sizeof(people) liefert doch 3 oder? also index 0-2 und was macht das
> teilen durch sizeof(people[0])?

sizeof(people) liefert - wie alle sizeof Aufrufe - die Menge an 
Arbeitsspeicher, die die Daten brauchen. Das ist 3x die Größe einer 
einzelnen struct von people. Und durch sizeof(people[0]) wird geteilt, 
um genau diese 3 herauszubekommen.

Autor: stupp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jz23 schrieb:
> sizeof(people) liefert - wie alle sizeof Aufrufe - die Menge an
> Arbeitsspeicher, die die Daten brauchen. Das ist 3x die Größe einer
> einzelnen struct von people. Und durch sizeof(people[0]) wird geteilt,
> um genau diese 3 herauszubekommen

Warum ist das 3x mal die größe die es eigentlich braucht?
Und was macht size_t dabei?

Autor: stupp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und noch eine frage wieso klappt das nicht:
struct person_s people[0]={1010, "Charlie", "Brown"};
struct person_s people[1]={1011, "Sally", "Brown"};
struct person_s people[2]={1012, "Lucy", "van Pelt"};
struct person_s people[3]={1013, "Snoopy", "Dog"}; *
// oder auch das nicht:

struct person_s people[]={1010, "Charlie", "Brown"};
struct person_s people[]={1011, "Sally", "Brown"};
struct person_s people[]={1012, "Lucy", "van Pelt"};
struct person_s people[]={1013, "Snoopy", "Dog"}; *


Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
stupp schrieb:
> Warum ist das 3x mal die größe die es eigentlich braucht?

Du siehst ein Sofa, und stellst fest, daß es drei Meter breit ist. Und 
Du weißt, daß eine (ziemlich wohlgenährte) Person einen Meter Platz 
braucht.

Damit kannst Du ausrechnen, daß auf Deinem Sofa wohl drei Personen Platz 
haben.

Genau das gleiche Prinzip findet hier Anwendung.

Du hast ein Array im Arbeitsspeicher, das z.B. 300 Bytes groß ist. Und 
Du weißt, das jedes einzelne Element, aus denen sich Dein Array 
zusammensetzt, 100 Bytes groß ist. Der Rechenweg, um festzustellen, daß 
das Array drei Elemente enthält, dürfte Dir jetzt bekannt vorkommen.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
2 lesenswert
nicht lesenswert
stupp schrieb:
> und noch eine frage wieso klappt das nicht:

Weil Du hier versuchst, mehrfach Variablen unter dem gleichen Namen 
anzulegen.

Wie wäre es, wenn Du, statt herumzuprobieren, einfach mal die Abschnitte 
"Variablen", "Arrays" und "Strukturen" in Deinem C-Buch durchlesen 
würdest?

Autor: stupp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habs mir doch 10 mal durchgelesen diese structs bringen alles 
durcheinander verstehe da nichts mehr..


Und wieso kann ich auch nicht mehr auf die strukturenelemente zugreifen 
will den namen ändern.

 people[2].nachname ="was anderes";

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Auch hier solltest Du Dir Dein C-Buch durchlesen, hier das Thema 
Stringverarbeitung.

Du wirst vermutlich vom Unterschied zwischen Initialisierung und 
Zuweisung durcheinandergebracht.


Wenn Dich Dein Buch durcheinanderbringt, dann ist vielleicht das Buch 
nicht das richtige?

Autor: jz23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wobei man hier zugeben muss, das strings in C auch echt unintuitiv sind 
- in den meisten Programmiersprachen wäre
people[2].nachname ="was anderes";

überhaupt kein Problem...

Autor: Jobst Quis (joquis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
stupp schrieb:
> Und wieso kann ich auch nicht mehr auf die strukturenelemente zugreifen
> will den namen ändern.
>
>  people[2].nachname ="was anderes";

Das ginge, wenn du den struct anders deklariert hättest:
struct person
{
  int personalnummer;
  char * vorname;
  char * nachname;
};


Statt der char[10] einen Stringpointer char*.

Sonst müsstest du in das char-array kopieren, und das gäbe Probleme, 
wenn ein Name länger als 9 Zeichen wäre. Wenn du aber die Arrays größer 
deklarierst, ist die Speicherplatzverschwendung auch größer.

Mit den Pointern ist es viel flexibler.

Autor: stupp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay mein Fehler man braucht strcpy.. Aber selbst das geht nicht, oder 
auch hier die Zahl? Das Array mit dem Struct bringt mich durcheinander. 
Normallerweise würde ich jetzt an die stelle 3 des Arrays eine 1 
hinschreiben. Wieso geht das hier nicht...
people[2].personalnummer=1;

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
stupp schrieb:
> und noch eine frage wieso klappt das nicht:
> struct person_s people[0]={1010, "Charlie", "Brown"};
> struct person_s people[1]={1011, "Sally", "Brown"};
> struct person_s people[2]={1012, "Lucy", "van Pelt"};
> struct person_s people[3]={1013, "Snoopy", "Dog"}; *
> // oder auch das nicht:
>
> struct person_s people[]={1010, "Charlie", "Brown"};
> struct person_s people[]={1011, "Sally", "Brown"};
> struct person_s people[]={1012, "Lucy", "van Pelt"};
> struct person_s people[]={1013, "Snoopy", "Dog"}; *

Weil du vorher ein Array deklarieren musst, bevor du die einzelnen 
Elemente (Strukturen) initialisieren kannst. Du sprichst über den Index 
Elemente an, die noch garnicht existieren.

Schau dir außerdem mal das Beispiel hier an: 
http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/...

Autor: Jobst Quis (joquis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
stupp schrieb:
> Okay mein Fehler man braucht strcpy.. Aber selbst das geht nicht, oder
> auch hier die Zahl? Das Array mit dem Struct bringt mich durcheinander.
> Normallerweise würde ich jetzt an die stelle 3 des Arrays eine 1
> hinschreiben. Wieso geht das hier nicht...
> people[2].personalnummer=1;

Müsste gehen. Vielleicht woanders noch ein Fehler?

Autor: Daniel Abrecht (daniel-a)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
stupp schrieb:
> Wieso geht das hier nicht...
> people[2].personalnummer=1;

Vermutlich hast du ein array von pointern auf personen, und nicht ein 
array von Personen. Dann muss man den mointer Dereferenzieren:
struct person people_a[3]; // Drei Personen im array
struct person *people_b[3]; // Drei Pointer auf Personen im array

struct person person; // Eine person
struct person* person_ptr = &person; // Ein Pointer auf person
struct person** person_ptr_ptr = &person_ptr; // Ein Pointer auf einen Pointer auf person

person.vorname; // Zugriff auf element in Person

// Dereferenzieren von person_ptr, und zugriff auf person
person_ptr->vorname; // Kurzschreibweise
(*person_ptr).vorname; // Dereferenzieren mit * und dann zugriff mit .
person_ptr[0].vorname; // Pointer kann als auf ein Array mit einem Element zeigend aufgefasst werden, dereferenzierung von element 0, zugriff auf struct member mit .
0[person_ptr].vorname; // Equivalenz von x[0] entspricht *(x+0) entspricht *(0+x) entspricht 0[x]

// 2 mal Dereferenzieren von person_ptr_ptr, und zugriff auf person
(*person_ptr_ptr)->vorname;
(**person_ptr_ptr).vorname;
person_ptr_ptr[0][0].vorname;
// etc.

// Achtung: sizeof(person_ptr_ptr) entspricht sizeof(struct person**) entspricht sizeof(void*), alle pointer sind gleich gross, aber sizeof(people_b) entspricht sizeof(struct person*[3]) entspricht sizeof(struct person*)*3 entspricht sizeof(void*)*3


Autor: stupp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wie hänge ich eine zusätzliche person an?
struct person people[] =
    {
      {1010, "simon", "klein"},
      {1011, "Sally", "Brown"},
      {1012, "Lucy", "van Pelt"}
    };

Autor: stupp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
struct person_s x={1013, "neu", "name"};
    people[2]=x;
das funktioniert, aber wird halt der andere der an stelle 2 ist 
überschrieben, wenn ich people[3] gehts nicht.

und  drekt people[2] = {1013, "neu", "name"} geht auch nicht.

Autor: Jobst Quis (joquis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du zur Laufzeit neue Einträge erstellen willst, deklarierst du 
einfach ein größeres Array:

#define MAX_PEOPLE 100

struct person people[MAX_PEOPLE];


Wie oben schon gesagt, sollten dann aber im struct keine char-Arrays 
sein, sondern Pointer.

In einem wirklich sinnvollen Programm initialisiert man solche Daten 
sowieso nicht im Programmtext, sondern lässt sie eingeben oder liest sie 
aus einer Datei.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
stupp schrieb:
> Und wie hänge ich eine zusätzliche person an?

Zur Laufzeit ist das nicht möglich.

Um das zu machen, brauchst Du dynamische Speicherverwaltung.

Bist Du Dir sicher, daß Du schon so sattelfest mit Variablen, Arrays, 
Strukturen etc. bist, daß Du Dir das ansehen willst?

Ganz sicher?

Autor: Daniel Abrecht (daniel-a)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
stupp schrieb:
> Und wie hänge ich eine zusätzliche person an?

Daniel A. schrieb:
> Wenn man nachträglich noch elemente hinzufügen will,
> wären eventuell linked lists praktischer.

Hier mal mit doubly linked lists:
#include<stdio.h>
#include<stddef.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>

#define UNPACK( ... ) __VA_ARGS__
#define ALLODEF( T, X ) allodef( (T[]){{UNPACK X}}, sizeof(T) )

struct doubly_linked_list {
  struct doubly_linked_list_entry* first;
  struct doubly_linked_list_entry* last;
};

struct doubly_linked_list_entry {
  struct doubly_linked_list_entry* next;
  struct doubly_linked_list_entry* previous;
  void* entry;
};

bool doubly_linked_list_add( struct doubly_linked_list* list, void* target ){
  if( !list || !target )
    return false;
  struct doubly_linked_list_entry* entry = calloc(1,sizeof(struct doubly_linked_list_entry));
  if( !entry )
    return false;
  entry->entry = target;
  entry->previous = list->last;
  if( list->last )
    list->last->next = entry;
  list->last = entry;
  if(!list->first)
    list->first = entry;
  return true;
}

void doubly_linked_list_cleanup( struct doubly_linked_list* list ){
  for( struct doubly_linked_list_entry* it=list->first, *next; it; it = next ){
    next = it->next;
    free(it);
  }
  list->first = 0;
  list->last = 0;
}

void* allodef( void* data, size_t size ){
  void* mem = malloc(size);
  if( !mem )
    return 0;
  memcpy( mem, data, size );
  return mem;
}

struct person
{
  int personalnummer;
  const char* vorname;
  const char* nachname;
};

int main(){

  // Liste aufbauen
  struct doubly_linked_list people = {0};
  // TODO: Error handling ;)
  doubly_linked_list_add( &people, ALLODEF(struct person,(101,"a","b")) );
  doubly_linked_list_add( &people, ALLODEF(struct person,(
    .personalnummer = 102,
    .vorname = "c",
    .nachname = "d"
  )) );

  // Inhalt ausgeben
  for( struct doubly_linked_list_entry* it = people.first; it; it = it->next ){
    struct person* person = it->entry;
    printf( "nr %d, %s %s\n", person->personalnummer, person->vorname, person->nachname );
  }

  // Speicher wieder freigeben
  for( struct doubly_linked_list_entry* it = people.first; it; it = it->next )
    free(it->entry);
  doubly_linked_list_cleanup(&people);

  return 0;
}

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
3 lesenswert
nicht lesenswert
Daniel A. schrieb:
> Hier mal mit doubly linked lists:

Ich habe leichte Zweifel daran, daß es hier wirklich hilfreich ist, 
solchen Code zu posten.

Autor: Jobst Quis (joquis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus Τ. F. schrieb:
> Ich habe leichte Zweifel daran, daß es hier wirklich hilfreich ist,
> solchen Code zu posten.

Für den Fragesteller wohl nicht. Aber es lesen ja noch andere hier.

Autor: Programmiersprachentheaterintendant (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jobst Q. schrieb:
> Rufus Τ. F. schrieb:
>> Ich habe leichte Zweifel daran, daß es hier wirklich hilfreich ist,
>> solchen Code zu posten.
>
> Für den Fragesteller wohl nicht. Aber es lesen ja noch andere hier.

Es ist immer angebracht, weitere Leute von C/C++ fernzuhalten.

Autor: Jobst Quis (joquis)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Programmiersprachentheaterintendant schrieb:
> Es ist immer angebracht, weitere Leute von C/C++ fernzuhalten.

Ist vielleicht besser für C/C++. Wer kein Talent zum Programmieren hat, 
sollte sich davon fernhalten.

Autor: Peter (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Genau diese Dinge sind in C++ wesentlich einfacher als in C. std::vector 
statt Array, std::string statt char-Pointer/Array:
struct person
{
  int personalnummer;
  std::string vorname;
  std::string nachnahme;
};

std::vector<person> personen;

Wie viele Personen sind in der Datenstruktur?
int anzahlPersonen = personen.size();

Zusätzliche Person anhängen?
personen.push_back(simon);

Nachname ändern?
personen[2].nachname = "was anderes";

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.