erste verkettete liste
-
slebst mit zeichnung will es nicht wikrlich -.-
also in worten was ich mir dazu gedacht habe:
zunächst hab ich damit ich das erste element nicht verlier einen neuen Zeiger X der aufs gleiche zeigt wie A.
ich biege den zeiger A aufs erste element aufs zweite, dann das next vom ersten element aufs dritte und danach das next vom zweiten element aufs erste.doch er gibt mir jetzt nur ne endlosschleife aus
struct sEmpList *swap(struct sEmpList *A){ struct sEmpList *X; X=A; A=A->next; A->next=A->next->next; A->next->next=X; return(A); }
-
In Zeile 5 lässt du A aufs zweite Element zeigen.
In Zeile 6 und 7 gehst du aber davon aus, dass A noch auf das erste Element zeigt.Nochmal überlegen.
-
wintik schrieb:
slebst mit zeichnung will es nicht wikrlich -.-
Wenn du deinen Code nachzeichnest, solltest du auf die Fehler ganz von allein kommen, d.h. wie du deine Liste 'zerhackst' und dadurch einzelne Elemente nicht mehr zugänglich werden...
Auf jeden Fall solltest du noch Zugriffe(Zuweisungen) auf next-Zeiger, die NULL sein könnten, vermeiden.
-
struct sEmpList *swap(struct sEmpList *A){ struct sEmpList *X; X=A; A=A->next; X->next=A->next; A->next=X; return(A); }
nach 12938skizzen kommt nie das getauschte raus sondern immer nur 4 elemente wo dann das zweite dann fehlt.
meine skizze sieht wie folgt aus:
X=A;
X,A->[1|n]->[2|n]->[3|n]->...
A=A->next;
X->[1|A]->[2|n]->[3|n]->...
X-next=A->next; A->next=X;
A->[2|X]->[1|n]->[3|n]->...
sieht jemand meinen fehler?
-
Wertest du den Rückgabewert der Funktion auch aus?
Steht da ein[b]A = [/b]swap(A);
Sonst zeigt das A aus main natürlich weiterhin auf 1.
-
oh gott -.- das es daran scheitert, dann hab ich jetzt die ganze zeit zeiger geschoben und das war garnicht der fehler..
-
Du solltest beim zeichnen auf Papier auch nur die Verlinkungen umzeichnen und nicht die Objekte selber.
Das folgende stimmt z.B. nicht, da A ja zusätzlich auf das 2. Objekt zeigt
X->[1|A]->[2|n]->[3|n]->... falsch
X->[1|n]->[2|n]->[3|n]->... A-^ so ist besser, 1 und A zeigen auf 2
Am Ende sollte dann
+----------+ | | +-->[1|n]-+ [2|n]+ +->[3|n]->... | X-^ A-^ | +-----------------+
rauskommen.
Und da könnetst du dann sehen, warum 2 nicht mehr ausgegeben wird, weil die Information verloren gegeangen ist, wo es liegt.
Wenn du dann noch unterschiedliche Variablennamen in main und swap hast, ist es sogar klar ersichtlich.
-
Vielen vielen dank leute! ich glaub jetzt hab ichs gerafft
#include <stdio.h> #include <stdlib.h> struct sEmpList { int PersNr; char *Name; struct sEmpList *next; }; struct sEmpList *NewEmployee(struct sEmpList *E, int PersNr,char *Name){ struct sEmpList *F; F= (struct sEmpList*) malloc (sizeof(struct sEmpList)); F->PersNr=PersNr; F->Name=Name; F->next=E; return(F); } struct sEmpList *swap(struct sEmpList *A){ struct sEmpList *X; X=A; A=A->next; X->next=A->next; A->next=X; return(A); } void printList(struct sEmpList *list) { while(list != NULL) { printf("Personalnummer: %i | ", list->PersNr); printf("Name: %s\n", list->Name); list = list->next; } } int main(){ struct sEmpList *A; A= (struct sEmpList*) malloc (sizeof(struct sEmpList)); A->PersNr=1; A->Name="Peter"; A = NewEmployee(A,2,"Hans"); // auf erstes Element achten! ggf. NULL anstatt A A = NewEmployee(A,3,"Wurst"); A = NewEmployee(A,4,"Detlef"); A = NewEmployee(A,5,"Dieter"); A = swap(A); printList(A); while (A != NULL) { A=A->next; free(A); } }
so läuft das programm richtig und gibt auch das aus was gefragt war.
bin grad am üben für eine prüfung und werd mich noch an weiteren funktionen für verkettete listen erproben, das muss alles sitzen bis nächste woche montag!
-
Mit deinem Namen wirst du so auf dauer nicht glücklich.
Gib die Namen doch mal per Hand ein:
char Namen[30]; int i = 10; // statt Zeile 56: while(1) { scanf("%29[^\n]", Namen); if (strlen(Namen) <2) break; A = NewEmployee(A,i++,Namen); }
-
was stimmt denn mit dem namen nicht?
-
Hast du es mal probiert? Und mehr als einen Namen eingegeben?
Du benutzt Stringliterale. Die sind konstat und können nicht verändert werden.
Mein Beispiel verwendet ein Array.
-
ich habs probiert und das programm will aus der whileschleife nicht mehr raus..
-
wintik schrieb:
ich habs probiert und das programm will aus der whileschleife nicht mehr raus..
lol
-
sehr hilfreicher kommentar
-
Da hier offensichtlich noch ein grosses Defizit in Stringsverarbeitung
vorliegt hier mal ein "Lückentext" der möglicherweise weiterhilft.struct sEmpList *NewEmployee(struct sEmpList *E, int PersNr,char *Name){ struct sEmpList *F; F= (struct sEmpList*) malloc (sizeof(struct sEmpList)); if(F == NULL) return NULL; F->Name = (char *) malloc(...); if(F->Name == NULL) return NULL; F->PersNr=PersNr; strcpy(F->Name, ...); /* wenn Vorgänger, dann anhängen */ if(E != NULL) { while(E->next) E = E->next; E->next=F; } return(F); }
Ich würde zudem die neuen Elemente hinten an die Liste anhängen. Dann kann man
den Returnwert prüfen, ohne den Rest der Liste zu verlieren. Bei malloc sollte
man damit rechnen, das es mal nicht klappt ...Das Hauptprogramm könnte dann auf Fehler reagieren:
struct sEmpList *head=NULL, *neu; neu = NewEmployee(head,i++,Namen); if(neu == NULL) { printf("Fehler ... ->exit ?} if(head == NULL) head = neu;
-
wintik schrieb:
ich habs probiert und das programm will aus der whileschleife nicht mehr raus..
Ich habe extra keine Anleitung dazugegeben, denn ich bin davon ausgegangen, dass du zumindest die Grundlagen kennst, bevor du verkettete Listen machst.
while(1) { // Endlosschleife scanf(" %29[^\n]", Namen); // Namen einlesen (maximal 29 Zeichen bis zu einem '\n' if (strlen(Namen) <2) // Wen der Name weniger als 2 Zeichen hat (1 oder 1) ... break; // ... dann beende die while-Schleife A = NewEmployee(A,i++,Namen); // Namen in Liste eintragen }
Gib zum beenden einfach 1 Zeichen ein und drücke Return.
-
hab die whileschleife wieder eingebaut, abbrechen funktioniert jedoch übernimmt er nicht die namen sondern das einzelene zeichen welches zuletzt eingegeben wurde?
-
wintik schrieb:
hab die whileschleife wieder eingebaut, abbrechen funktioniert jedoch übernimmt er nicht die namen sondern das einzelene zeichen welches zuletzt eingegeben wurde?
Wer ist er?
In deiner Funktion NewEmployee werden den Zeigern auf die Namen stets ein und derselbe Speicherplatz zugewiesen(wenn du die while Schleife zur Eingabe benutzst).
Gibst du also z.B. 3 Namen ein, so erzeugst du 3 Listenelemente deren Member *char Name- Zeiger alle auf das Array char Namen[30] zeigen.
Wenn du also willst, das "er" es übernimmt, musst du den Namen irgendwie eigenen Speicher spendieren.
Die einfachste Variante ist, du machst aus dem Zeiger ein Arraystruct sEmpList { int PersNr; char Name[64]; // Array anstelle eines Zeigers struct sEmpList *next; };
und kopierst die eingegebenen Namen ins Array, oder aber du arbeitest mit malloc oder calloc wie hier schon ansatzweise gezeigt wurde.
-
badaboom! es läuft, danke danke danke!
er ist der compiler/das Programm/die Console!#include <stdio.h> #include <stdlib.h> #include <string.h> struct sEmpList { int PersNr; char Name[20]; struct sEmpList *next; }; struct sEmpList *NewEmployee(struct sEmpList *E, int PersNr,char *Name){ struct sEmpList *F; F= (struct sEmpList*) malloc (sizeof(struct sEmpList)); F->PersNr=PersNr; strcpy(F->Name,Name); //wenn Arry schon fest bestimmt (bei *name F->Name=Name) if (E != NULL) { F->next=E; } else F->next=NULL; return(F); } struct sEmpList *swap(struct sEmpList *A){ struct sEmpList *X; X=A; A=A->next; X->next=A->next; A->next=X; return(A); } void printList(struct sEmpList *list) { while(list != NULL) { printf("Personalnummer: %i | ", list->PersNr); printf("Name: %s\n", list->Name); list = list->next; } } int main(){ int i=1; char Namen[20]; struct sEmpList *A; while(1) { // Endlosschleife scanf(" %29[^\n]", Namen); // Namen einlesen (maximal 29 Zeichen bis zu einem '\n' if (strlen(Namen) <2) // Wen der Name weniger als 2 Zeichen hat (1 oder 1) ... break; // ... dann beende die while-Schleife A = NewEmployee(A,i++,Namen); // Namen in Liste eintragen } //A = swap(A); printList(A); while (A != NULL) { A=A->next; free(A); } }
ich hatte jetzt schon ne delet funktion geschrieben die hat auch funktioniert, nun wollt ich diese sowie die swap funktion so umschreiben das ich angeben kann welches element gelöscht bzw getauscht werden soll (bei swap einfach nur stelle angeben und mit dem nächsten wird dann getauscht).
zunächst hab ich einen neuen zeiger erstellt damit ich den anfang der liste nicht verlier, dann mit dem neuen den zeiger umgebogen, ausgegeben krieg ich nur die elemente die vor dem aufruf der deletfunktion sindstruct sEmpList *del(struct sEmpList *A, int n){ int i; struct sEmpList *tmp, *X; X=A; for (i=1; i<n; i++) { X=X->next; } tmp=X; X=X->next; free(tmp); return X; } struct sEmpList *swap(struct sEmpList *A,int n){ int i=1; struct sEmpList *X,*B; B=A; while (i<n) { B=B->next; i++; } X=B; B=B->next; X->next=B->next; B->next=X; return(A); }
-
Das guck dir lieber noch einmal an ...
wintik schrieb:
if (E != NULL) { F->next=E; } else F->next=NULL; return(F);
... und überleg dir was du tun musst, damit auch wirklich E=NULL in NewEmployee reinkommt ...
... dein Eingabe Array ist von einer Sprengung bedroht ...... warum castest du malloc, das ist pfui, in C ist das verpönt...
http://www.c-plusplus.net/forum/206606
... deine schleife für die Spreicherfreigabe .. hüüüstel ... da gucke nochmal hin (ein Zeiger wird nicht NULL, wenn man ihn an free übergibt) ... stürzt dein Programm denn nicht ab?