C - Telefonbuch Zeiger/Listen |
|
C - Telefonbuch Zeiger/Listen |
|
Hallo Leute,
ich muss euch leider noch einmal nerven!
Unsere letzte Praktikumsaufgabe hat es (meiner Meinung nach) in sich.
Wir sollen ein einfaches Telefonbuch mithilfe von Listen realisieren.
Es soll:
1.: Einträge neu erstellen können (vom Nutzer eingegeben)
2.: Alle Einträge ausgeben können
3.: Nach einem Nachnamen suchen und die dazu passende Telefonnummer ausgeben
4.: Nach einem Nachnamen suchen und diesen Eintrag dann löschen
5.: Das komplette Telefonbuch löschen.
Mit der theoretischen Umsetzung an sich habe ich kein Problem, aber es hapert noch am Verständnis von Listen und etwas bei Zeigern.
Ich habe bereits Teilaufgabe 1 und 2 programmiert bekommen, jedoch weißt dies noch einen Fehler auf:
code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
|
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char *nachname;
char *vorname;
char *wohnort;
long int telefonnummer;
struct Person *next;
}Person;
void Hinzufuegen(Person *derzeitige)
{
Person *naechste;
char *n_name;
char *v_name;
char *w_ort;
long int t_nummer;
if (derzeitige == NULL) return;
if (derzeitige->next != NULL) return;
printf("\nGeben Sie den Nachnamen ein\n"); scanf("%s", n_name);
printf("\nGeben Sie den Vornamen ein\n"); scanf("%s", v_name);
printf("\nGeben Sie den Wohnort ein\n"); scanf("%s", w_ort);
printf("\nGeben Sie die Telefonnummer ein\n"); scanf("%d", &t_nummer);
derzeitige->next = (struct Person*) malloc(sizeof(Person));
naechste = (Person*) derzeitige->next;
naechste->nachname = n_name;
naechste->vorname = v_name;
naechste->wohnort = w_ort;
naechste->telefonnummer = t_nummer;
naechste->next = NULL;
}
void Ausgabe(Person *erste)
{
int i = 1;
Person *derzeitige = erste;
while (derzeitige != NULL)
{
printf("%d. Person: %s, %s, %s, %ld \n",i, derzeitige->nachname, derzeitige->vorname, derzeitige->wohnort, derzeitige->telefonnummer);
derzeitige = (Person*) derzeitige->next;
i++;
}
}
main()
{
Person *erste, *derzeitige;
erste = (Person*) malloc(sizeof(Person));
erste->nachname = "Kinkel";
erste->vorname = "Marvin";
erste->wohnort = "Dinslaken";
erste->telefonnummer = 491635685977;
erste->next = NULL;
derzeitige = erste;
Hinzufuegen(derzeitige);
Hinzufuegen(derzeitige);
Ausgabe(erste);
}
|
|
Schaut man sich die Funktion "Hinzufuegen()" an sieht man, dass ich per scanf Werte an die Zeiger übergeben möchte.
Sobald ich aber den v_namen eingeben möchte (nach dem n_namen) bricht das Programm (mittendrin) ohne Fehlermeldung ab, als wäre nichts passiert.
Nutze ich aber stattdessen die Befehle:
code: |
1:
|
scanf("%s", &v_name); scanf("%s", &w_ort); |
|
Speichert er n_name korrekt ein und gibt es auch bei der Ausgabe korrekt aus.
Nur v_name und w_ort dann natürlich nicht.
Ist meine Methode um Benutzereingaben an eine Struktur zu übergeben falsch?
Für Hilfe wäre ich sehr dankbar!
|
|
18.01.2016 14:44 |
|
|
|
Hiermit:
code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
|
void Hinzufuegen(Person *derzeitige)
{
Person *naechste;
char *n_name[20];
char *v_name[20];
char *w_ort[20];
long int t_nummer;
if (derzeitige == NULL) return;
if (derzeitige->next != NULL) return;
printf("\nGeben Sie den Nachnamen ein\n"); scanf("%s", n_name);
printf("\nGeben Sie den Vornamen ein\n"); scanf("%s", v_name);
printf("\nGeben Sie den Wohnort ein\n"); scanf("%s", w_ort);
printf("\nGeben Sie die Telefonnummer ein\n"); scanf("%ld", &t_nummer);
derzeitige->next = (struct Person*) malloc(sizeof(Person));
naechste = (Person*) derzeitige->next;
strcpy(naechste->nachname,n_name);
strcpy(naechste->vorname,v_name);
strcpy(naechste->wohnort,w_ort);
naechste->telefonnummer = t_nummer;
naechste->next = NULL;
}
|
|
Bekomme ich jetzt folgende Fehlermeldung:
code: |
1:
2:
3:
4:
5:
|
Telefonbuch.c: In Funktion »Hinzufuegen«:
Telefonbuch.c:30:4: Warnung: Unverträgliche implizite Deklaration der eingebauten Funktion »strcpy«
strcpy(naechste->nachname,*n_name);
^
|
|
|
|
18.01.2016 15:44 |
|
|
|
Ja gerade eben :/
Man bin ich doof...
Jetzt hab ich folgendes:
Diese Zeilen:
code: |
1:
2:
3:
|
strcpy(naechste->nachname,n_name);
strcpy(naechste->vorname,v_name);
strcpy(naechste->wohnort,w_ort); |
|
geben mir diese Fehlermeldung:
code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
|
Telefonbuch.c: In Funktion »Hinzufuegen«:
Telefonbuch.c:31:30: Warnung: Übergabe des Arguments 2 von »strcpy« von inkompatiblem Zeigertyp
strcpy(naechste->nachname,n_name);
^
In file included from /usr/include/stdio.h:29:0,
from Telefonbuch.c:1:
/usr/include/string.h:30:8: Anmerkung: »const char *« erwartet, aber Argument hat Typ »char **«
char *_EXFUN(strcpy,(char *__restrict, const char *__restrict));
^
Telefonbuch.c:32:29: Warnung: Übergabe des Arguments 2 von »strcpy« von inkompatiblem Zeigertyp
strcpy(naechste->vorname,v_name);
^
In file included from /usr/include/stdio.h:29:0,
from Telefonbuch.c:1:
/usr/include/string.h:30:8: Anmerkung: »const char *« erwartet, aber Argument hat Typ »char **«
char *_EXFUN(strcpy,(char *__restrict, const char *__restrict));
^
Telefonbuch.c:33:29: Warnung: Übergabe des Arguments 2 von »strcpy« von inkompatiblem Zeigertyp
strcpy(naechste->wohnort,w_ort);
^
In file included from /usr/include/stdio.h:29:0,
from Telefonbuch.c:1:
/usr/include/string.h:30:8: Anmerkung: »const char *« erwartet, aber Argument hat Typ »char **«
char *_EXFUN(strcpy,(char *__restrict, const char *__restrict));
^
|
|
und wenn ich es darin ändere:
code: |
1:
2:
3:
|
strcpy(naechste->nachname,*n_name);
strcpy(naechste->vorname,*v_name);
strcpy(naechste->wohnort,*w_ort); |
|
kriege ich einen Segmentation fault
|
|
18.01.2016 15:55 |
|
|
|
Du musst den Datentypen in der struct auch anpassen:
code: |
1:
2:
3:
4:
5:
6:
7:
8:
|
typedef struct
{
char nachname[20];
char vorname[20];
char wohnort[20];
long int telefonnummer;
struct Person *next;
} Person; |
|
Das zieht Änderungen für die main nach sich.
__________________ Syntax Highlighting fürs Board (Link)
|
|
18.01.2016 16:08 |
|
|
|
Also Änderungen an meiner Zuweisung der ersten Person?
|
|
18.01.2016 16:33 |
|
|
|
Ich bin den Segmentation Fault jetzt losgeworden und die Eingabe durchläuft er jetzt so ohne sich zu beschweren.
Jedoch komme ich nicht in die AusgabeFunktion.
Außerdem hat es nichts gebracht malloc in der main Funktion für mein erstes Element aufzurufen sondern ich musste es in der Hinzufuegen Funktion machen. Woran liegt das?
Hier mein jetziger Code:
code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
|
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char nachname[15];
char vorname[15];
char wohnort[15];
char telefonnummer[15];
struct Person *next;
}Person;
void Hinzufuegen();
void Ausgabe();
main()
{
Person *erste, *derzeitige;
erste = NULL;
Hinzufuegen(erste, derzeitige);
Hinzufuegen(erste, derzeitige);
Ausgabe(erste);
}
void Hinzufuegen(Person *erste, Person *derzeitige)
{
if (erste == NULL){
erste = (Person *) malloc(sizeof(Person));
printf("\nGeben Sie den Nachnamen ein\n"); gets(erste->nachname);
printf("\nGeben Sie den Vornamen ein\n"); gets(erste->vorname);
printf("\nGeben Sie den Wohnort ein\n"); gets(erste->wohnort);
printf("\nGeben Sie die Telefonnummer ein\n"); gets(erste->telefonnummer);
erste->next = NULL;
derzeitige = erste;
}
else{
Person *naechste;
if (derzeitige == NULL) return;
if (derzeitige->next != NULL) return;
derzeitige->next = malloc(sizeof(Person));
naechste = (Person*) derzeitige->next;
printf("\nGeben Sie den Nachnamen ein\n"); gets(naechste->nachname);
printf("\nGeben Sie den Vornamen ein\n"); gets(naechste->vorname);
printf("\nGeben Sie den Wohnort ein\n"); gets(naechste->wohnort);
printf("\nGeben Sie die Telefonnummer ein\n"); gets(naechste->telefonnummer);
naechste->next = NULL;
}
}
void Ausgabe(Person *erste)
{
int i = 1;
Person *derzeitige = erste;
while (derzeitige != NULL)
{
printf("%d. Person: %s, %s, %s, %ld \n",i, derzeitige->nachname, derzeitige->vorname, derzeitige->wohnort, derzeitige->telefonnummer);
derzeitige = (Person*) derzeitige->next;
i++;
}
} |
|
Es kommt mir so vor als wenn sich mein Programm über die Funktionsgrenzen hinaus nichts merkt...
Aber erste und derzeitige müssten doch global sein oder nicht?
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von LightSideOfLife: 19.01.2016 00:44.
|
|
18.01.2016 23:40 |
|
|
|
Mit Person* kannst du nur den Inhalt der Person ändern, ihr z.B. einen anderen Namen geben oder auch einen Nachfolger zuweisen. Aber es ist nicht möglich den Zeiger so zu ändern, dass die Person selbst eine andere wird. Wenn Person* vorher NULL war, musst du die Adresse von Person* ändern. Sonst kriegt die main davon nichts mit. Daher der Doppelzeiger.
Bei der Ausgabe reicht ein Zeiger - und den kann man sogar überschreiben.
code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
|
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char nachname[15];
char vorname[15];
char wohnort[15];
char telefonnummer[15];
struct Person *next;
}Person;
void Hinzufuegen(Person**);
void Ausgabe(Person*);
int main()
{
Person *erste;
Hinzufuegen(&erste);
Hinzufuegen(&erste);
Ausgabe(erste);
return 0;
}
void Hinzufuegen(Person **erste) //Doppelzeiger, weil wir nicht nur den Inhalt, sondern auch die Adresse ändern müssen
{
Person* naechste;
if (*erste == NULL) {
*erste = (Person*) malloc(sizeof(Person));
naechste = *erste;
while (naechste->next != NULL)
naechste = (Person*) naechste->next;
}
else {
naechste = *erste;
while (naechste->next != NULL)
naechste = (Person*) naechste->next;
Person* tmp = (Person*) malloc(sizeof(Person));
naechste->next = (Person*) tmp;
naechste = (Person*) naechste->next;
}
printf("Geben Sie den Nachnamen ein: "); scanf("%s", naechste->nachname);
printf("Geben Sie den Vornamen ein: "); scanf("%s", naechste->vorname);
printf("Geben Sie den Wohnort ein: "); scanf("%s", naechste->wohnort);
printf("Geben Sie die Telefonnummer ein: "); scanf("%s", naechste->telefonnummer);
}
void Ausgabe(Person *erste)
{
int i = 1;
while (erste != NULL)
{
printf("%d. Person: %s, %s, %s, %s \n",i, erste->nachname, erste->vorname, erste->wohnort, erste->telefonnummer);
erste = (Person*) erste->next;
i++;
}
} |
|
__________________ Syntax Highlighting fürs Board (Link)
|
|
19.01.2016 07:38 |
|
|
|
Ok das mit dem Doppelzeiger ist jetzt etwas kompliziert für mich da muss ich mich mal genauer reinlesen und reindenken.
Außerdem beschwert sich noch mein Compiler oO
code: |
1:
2:
3:
4:
5:
6:
7:
|
else{
naechste = *erste;
while (naechste->next != NULL)
naechste = (Person*) naechste->next;
Person *tmp = (Person*) malloc(sizeof(Person));
naechste->next = (Person*) tmp;
naechste = (Person*) naechste->next; |
|
code: |
1:
2:
3:
4:
|
Telefonbuch.c:39:19: Warnung: Zuweisung von inkompatiblem Zeigertyp
naechste->next = (Person*) tmp;
^
|
|
|
|
19.01.2016 14:06 |
|
|
|
Hier auch mal mein Versuch das Löschen eines Eintrags zu realisieren:
code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
|
void Loeschen(Person *erste)
{
Person *derzeitige = erste;
char gesucht;
printf("Wessen Eintrag soll gelöscht werden? (Nachname)"); scanf("%s",gesucht);
while (derzeitige != NULL)
{
if (derzeitige->next->nachname == gesucht)
{
Person *tmp1 = derzeitige->next->next;
free(derzeitige->next);
derzeitige->next = tmp1;
}
}
} |
|
Hier sagt mir der Compiler immer:
code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
|
Telefonbuch.c: In Funktion »NummerSuchen«:
Telefonbuch.c:75:30: Warnung: Vergleich zwischen Zeiger und Ganzzahl
if (derzeitige->nachname == gesucht)
^
Telefonbuch.c: In Funktion »Loeschen«:
Telefonbuch.c:88:25: Fehler: Dereferenzierung eines Zeigers auf unvollständigen Typen
if (derzeitige->next->nachname == gesucht)
^
Telefonbuch.c:90:37: Fehler: Dereferenzierung eines Zeigers auf unvollständigen Typen
Person *tmp1 = derzeitige->next->next;
^
Telefonbuch.c:92:23: Warnung: Zuweisung von inkompatiblem Zeigertyp
derzeitige->next = tmp1;
^
|
|
Ihm scheinen also diese doppelten Pfeile nicht zu schmecken.
Außerdem wieder das "Zuweisung von inkomtabliblem Zeigertyp" Problem.
Man... Ich hab echt Verständnisprobleme bei Zeigern...
|
|
19.01.2016 15:05 |
|
|
|
Der Stringvergleich klappt so nicht, zumindest nicht in C. strcmp heißt die Funktion, nach der du und gleich auch google suchen.
Und beim Löschen kann es passieren, dass der erste Eintrag entfernt werden soll. Bei deinem aktuellen Entwurf will die aufrufende Funktion dann immer noch auf die mittlerweile gelöschte Person zugreifen. Du brauchst auch hier Person**.
__________________ Syntax Highlighting fürs Board (Link)
|
|
19.01.2016 20:33 |
|
|
|