Forum: PC-Programmierung struktur elemeten durchlaufen C


von stupp (Gast)


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..

von A. S. (Gast)


Lesenswert?

vorher:
1
#define countof(a) (sizeof(a)/sizeof(a[0]))
2
3
void doit(int i, const char *vorname, const char *nachnahme)
4
{
5
    ...
6
}
im main:
1
struct person *pa[]={simon, lucy, sally];
2
int i;
3
   
4
    for(i=0; i < countof(pa); i++)
5
    {
6
        doit(pa[i].personalnummer, pa[i].vorname, pa[i].nachnahme);
7
    }
8
}

von Daniel A. (daniel-a)


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.
1
#include<stddef.h>
2
#include<stdio.h>
3
4
struct person
5
{
6
  int personalnummer;
7
  char vorname[10];
8
  char nachname[10];
9
};
10
11
12
int main(void)
13
{
14
15
    struct person simon={1010, "simon", "klein"};
16
    struct person lucy={1011, "Sally", "Brown"};
17
    struct person sally={1012, "Lucy", "van Pelt"};
18
19
    struct person* people[]={ &simon, &lucy, &sally };
20
    size_t people_count = sizeof(people) / sizeof(*people);
21
22
    for( size_t i=0; i<people_count; i++ ){
23
      printf( "nr %d, %s %s\n", people[i]->personalnummer, people[i]->vorname, people[i]->nachname );
24
    }
25
26
    return 0;
27
}

Edit: schonwieder zu langsam...

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


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.
1
#include<stddef.h>
2
#include<stdio.h>
3
4
struct person
5
{
6
  int personalnummer;
7
  char vorname[10];
8
  char nachname[10];
9
};
10
11
12
int main(void)
13
{
14
15
    struct person people[] =
16
    {
17
      {1010, "simon", "klein"},
18
      {1011, "Sally", "Brown"},
19
      {1012, "Lucy", "van Pelt"}
20
    };
21
22
    size_t people_count = sizeof(people) / sizeof(people[0]);
23
24
    for( size_t i=0; i<people_count; i++ ){
25
      printf( "nr %d, %s %s\n", people[i].personalnummer, people[i].vorname, people[i].nachname );
26
    }
27
28
    return 0;
29
}

von Jobst Q. (joquis)


Lesenswert?

Achim S. schrieb:
> vorher:
>
1
> #define countof(a) (sizeof(a)/sizeof(a[0]))
2
> 
3
> void doit(int i, const char *vorname, const char *nachnahme)
4
> {
5
>     ...
6
> }
7
>
> im main:
>
1
> struct person *pa[]={simon, lucy, sally];
2
> int i;
3
> 
4
>     for(i=0; i < countof(pa); i++)
5
>     {
6
>         doit(pa[i].personalnummer, pa[i].vorname, pa[i].nachnahme);
7
>     }
8
> }
9
>

Der Sinn von struct ist doch gerade, keine endlosen Parameterlisten 
übergeben zu müssen, sondern nur einen Pointer.
1
> void doit(struct person *p)
2
 {
3
     ...
4
  printf( "nr %d, %s %s\n", p->personalnummer, p->vorname, p->nachname );
5
   ...
6
 }
7
8
...
9
10
for(i=0; i < countof(pa); i++)
11
  {
12
     doit(&pa[i]);
13
  }

: Bearbeitet durch User
von stupp (Gast)


Lesenswert?

1
 struct person people[] =
2
    {
3
      {1010, "simon", "klein"},
4
      {1011, "Sally", "Brown"},
5
      {1012, "Lucy", "van Pelt"}
6
    };
7
// was passiert hier? und was ist der Unterschied zu meiner Variante:
8
// 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?
9
10
11
12
    size_t people_count = sizeof(people) / sizeof(people[0]);
13
//sizeof(people) liefert doch 3 oder? also index 0-2 und was macht das teilen durch sizeof(people[0])?

von jz23 (Gast)


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.

von stupp (Gast)


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?

von stupp (Gast)


Lesenswert?

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

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Rufus Τ. F. (rufus) Benutzerseite


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?

von stupp (Gast)


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";

von Rufus Τ. F. (rufus) Benutzerseite


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?

von jz23 (Gast)


Lesenswert?

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

überhaupt kein Problem...

von Jobst Q. (joquis)


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:
1
struct person
2
{
3
  int personalnummer;
4
  char * vorname;
5
  char * nachname;
6
};

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.

von stupp (Gast)


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;

von Jens (Gast)


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/015_c_strukturen_006.htm#mj558e0e4fc0892fc3f91cd810f7c07860

von Jobst Q. (joquis)


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?

von Daniel A. (daniel-a)


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:
1
struct person people_a[3]; // Drei Personen im array
2
struct person *people_b[3]; // Drei Pointer auf Personen im array
3
4
struct person person; // Eine person
5
struct person* person_ptr = &person; // Ein Pointer auf person
6
struct person** person_ptr_ptr = &person_ptr; // Ein Pointer auf einen Pointer auf person
7
8
person.vorname; // Zugriff auf element in Person
9
10
// Dereferenzieren von person_ptr, und zugriff auf person
11
person_ptr->vorname; // Kurzschreibweise
12
(*person_ptr).vorname; // Dereferenzieren mit * und dann zugriff mit .
13
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 .
14
0[person_ptr].vorname; // Equivalenz von x[0] entspricht *(x+0) entspricht *(0+x) entspricht 0[x]
15
16
// 2 mal Dereferenzieren von person_ptr_ptr, und zugriff auf person
17
(*person_ptr_ptr)->vorname;
18
(**person_ptr_ptr).vorname;
19
person_ptr_ptr[0][0].vorname;
20
// etc.
21
22
// 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

von stupp (Gast)


Lesenswert?

Und wie hänge ich eine zusätzliche person an?
1
struct person people[] =
2
    {
3
      {1010, "simon", "klein"},
4
      {1011, "Sally", "Brown"},
5
      {1012, "Lucy", "van Pelt"}
6
    };

von stupp (Gast)


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.

von Jobst Q. (joquis)


Lesenswert?

Wenn du zur Laufzeit neue Einträge erstellen willst, deklarierst du 
einfach ein größeres Array:
1
#define MAX_PEOPLE 100
2
3
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.

von Rufus Τ. F. (rufus) Benutzerseite


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?

von Daniel A. (daniel-a)


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:
1
#include<stdio.h>
2
#include<stddef.h>
3
#include<stdlib.h>
4
#include<string.h>
5
#include<stdbool.h>
6
7
#define UNPACK( ... ) __VA_ARGS__
8
#define ALLODEF( T, X ) allodef( (T[]){{UNPACK X}}, sizeof(T) )
9
10
struct doubly_linked_list {
11
  struct doubly_linked_list_entry* first;
12
  struct doubly_linked_list_entry* last;
13
};
14
15
struct doubly_linked_list_entry {
16
  struct doubly_linked_list_entry* next;
17
  struct doubly_linked_list_entry* previous;
18
  void* entry;
19
};
20
21
bool doubly_linked_list_add( struct doubly_linked_list* list, void* target ){
22
  if( !list || !target )
23
    return false;
24
  struct doubly_linked_list_entry* entry = calloc(1,sizeof(struct doubly_linked_list_entry));
25
  if( !entry )
26
    return false;
27
  entry->entry = target;
28
  entry->previous = list->last;
29
  if( list->last )
30
    list->last->next = entry;
31
  list->last = entry;
32
  if(!list->first)
33
    list->first = entry;
34
  return true;
35
}
36
37
void doubly_linked_list_cleanup( struct doubly_linked_list* list ){
38
  for( struct doubly_linked_list_entry* it=list->first, *next; it; it = next ){
39
    next = it->next;
40
    free(it);
41
  }
42
  list->first = 0;
43
  list->last = 0;
44
}
45
46
void* allodef( void* data, size_t size ){
47
  void* mem = malloc(size);
48
  if( !mem )
49
    return 0;
50
  memcpy( mem, data, size );
51
  return mem;
52
}
53
54
struct person
55
{
56
  int personalnummer;
57
  const char* vorname;
58
  const char* nachname;
59
};
60
61
int main(){
62
63
  // Liste aufbauen
64
  struct doubly_linked_list people = {0};
65
  // TODO: Error handling ;)
66
  doubly_linked_list_add( &people, ALLODEF(struct person,(101,"a","b")) );
67
  doubly_linked_list_add( &people, ALLODEF(struct person,(
68
    .personalnummer = 102,
69
    .vorname = "c",
70
    .nachname = "d"
71
  )) );
72
73
  // Inhalt ausgeben
74
  for( struct doubly_linked_list_entry* it = people.first; it; it = it->next ){
75
    struct person* person = it->entry;
76
    printf( "nr %d, %s %s\n", person->personalnummer, person->vorname, person->nachname );
77
  }
78
79
  // Speicher wieder freigeben
80
  for( struct doubly_linked_list_entry* it = people.first; it; it = it->next )
81
    free(it->entry);
82
  doubly_linked_list_cleanup(&people);
83
84
  return 0;
85
}

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Jobst Q. (joquis)


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.

von Programmiersprachentheaterintendant (Gast)


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.

von Jobst Q. (joquis)


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.

von Peter (Gast)


Lesenswert?

Genau diese Dinge sind in C++ wesentlich einfacher als in C. std::vector 
statt Array, std::string statt char-Pointer/Array:
1
struct person
2
{
3
  int personalnummer;
4
  std::string vorname;
5
  std::string nachnahme;
6
};
7
8
std::vector<person> personen;

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

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

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

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.