wiedermal die Liste
-
Hallo ich habe folgendes Problem:
wir sollten in einer dynamisch doppelt verketteten Litse beliebig viele Werte einlesen.
Habe das auch soweit das es für fünf strings passt. Lese ich aber nun das sechste ein wird das genommen und ein alter string is nicht mehr da wenn ich es ausgebe.Ich hoffe ihr koennt mir helfen
hier meine Liste:struct LISTE{ char name[60]; struct LISTE *nvor; /*Vorgaenger fuer den name*/ struct LISTE *nnach; /*Nachfolger fuer den namen*/ int jahr; struct LISTE *jvor; /*Vorgaenger fuer das Jahr*/ struct LISTE *jnach; /*Nachfolger fuer das Jahr*/ float preis; struct LISTE *pvor; /*Vorgaenger fuer den Preis*/ struct LISTE *pnach; /*Nachfolger fuer den Preis*/ };
Jahr und Preis wird bei mir noch nicht einsortiert.
Und hier nun der Code für das einfügen in der Liste:
struct LISTE *sortiere(struct LISTE *ein, int *anz, char einname[],int einjahr,float einpreis) { struct LISTE *liste; struct LISTE *cha; int pruef=0; if((*anz)==0) { ein=(struct LISTE *)malloc(sizeof(struct LISTE)); if(ein==NULL) { printf("Speicher konnte nicht bereitgestellt werden!\n\n"); } else { strcpy(ein->name,einname); ein->jahr=einjahr; ein->preis=einpreis; ein->nvor=NULL; ein->nnach=NULL; ein->jvor=NULL; ein->jnach=NULL; ein->pvor=NULL; ein->pnach=NULL; (*anz)++; } } else if((*anz)==1) { liste=(struct LISTE *)malloc(sizeof(struct LISTE)); if(liste==NULL) { printf("Speicher konnte nicht bereitgestellt werden!\n\n"); } else { strcpy(liste->name,einname); liste->jahr=einjahr; ein->preis=einpreis; printf("ein %s",ein->name); printf("liste %s",liste->name); if(strcmp(liste->name,ein->name)>=0) { printf("Test"); liste->nnach=ein->nnach; liste->nvor=ein; ein->nnach=liste; } else { liste->nvor=ein->nvor; liste->nnach=ein; ein->nvor=liste; } (*anz)++; } } else if((*anz)>=2) { liste=(struct LISTE *)malloc(sizeof(struct LISTE)); if(liste==NULL) { printf("Es konnte kein Speicher bereitgestellt werden!\n\n"); } else { cha=ein; strcpy(liste->name,einname); liste->jahr=einjahr; liste->preis=einpreis; cha=suchende(cha); do{ if((strcmp(liste->name,cha->name)>=0)&&(cha->nnach==NULL)) { liste->nnach=cha->nnach; liste->nvor=cha; cha->nnach=liste; pruef=1; } else if(strcmp(liste->name,cha->name)<0) { cha=cha->nvor; } else if((strcmp(liste->name,cha->name)>=0)&&(strcmp(liste->name,(cha->nnach)->name)<0)) { (cha->nnach)->nvor=liste; liste->nnach=cha->nnach; liste->nvor=cha->nvor; cha->nnach=liste; pruef=1; } if((strcmp(liste->name,cha->name)<0)&&(cha->nvor==NULL)) { liste->nnach=cha; liste->nvor=cha->nvor; cha->nvor=liste; pruef=1; } }while((pruef==0)&&(cha!=NULL)); (*anz)++; } } return ein; }
Würde mich über jede hilfe freuen
mfg geschen
-
1. tritt das problem mit beliebigen eingabedaten ab dem 6. string auf, oder hast du nur eine kombination getestet?
2. die nahmenswhl ist nicht gerade intuitiv:
LISTE ist ja keine liste, sondern ein listenelement, da besteht ein unterschied.
wofür steht ein? ist das der listenanfang oder nur ein beliebiges listenelement?3.abgesehen davon, das du es dir unnötig schwer machst...
solltest du vielleicht die initialisierung des neuen elementes vor den ganzen if teil schieben, ist schliesslich immer dasselbe. im übrigen ist *anz==1 (und mit ein bisschen aufwand auch *anz==0) kein echter sonderfall.
4. was macht die funktion suchende?
-
ui gleich so viele fragen
also es ist eigentlich ganz egal was ich eingebe nach dem fünften verschwindet immer ein anderes element
ein ist halt das aktuelle (würde ich jetzt sagen aber ka), füge daran doch immer die anderen listenelemente an, so war es zumindest geplant
zu dem ganzen unnötigen kram kann ich nur sagen, mache das halt noch net ganz so langedie funktion suchende sucht das ende der liste, muss doch irgendwo anfangen zu vergleichen und dann einfügen oder nich?
zu den ganzen zeigern in der struktur möchte ich noch sagen, dass ich das so machen muss, wenn es mir auch net gefällt
mfg geschen
-
if((strcmp(liste->name,cha->name)>=0)&&(cha->nnach==NULL))
{
liste->nnach=cha->nnach;
liste->nvor=cha;
cha->nnach=liste;
pruef=1;
}cha->nnach==NULL gilt für das allererste element, mit dem du vergleichst, und kein weiteres; also bring das vor den schleifenanfang (bzw. die schleife in den else zweig)
else if((strcmp(liste->name,cha->name)>=0)&&(strcmp(liste->name,(cha->nnach)->name)<0))
{
(cha->nnach)->nvor=liste;
liste->nnach=cha->nnach;
liste->nvor=cha->nvor;
cha->nnach=liste;
pruef=1;
}die zweite bedingung ist redundant. für das ERSTE element, das lexikalisch kleinergleich als list->name ist, gilt logischerweise immer, dass das folgende element lexikalisch grösser ist (den fall, dass cha->nnach==NULL ist, hast du ja bereits ausgeschlossen).
else if(strcmp(liste->name,cha->name)<0)
{
cha=cha->nvor;
}
/* ... */
if((strcmp(liste->name,cha->name)<0)&&(cha->nvor==NULL))
{
liste->nnach=cha;
liste->nvor=cha->nvor;
cha->nvor=liste;
pruef=1;
}aua!!! hier besteht die gefahr (genauer: das wird immer passieren, wenn man am anfang der liste einfügen müsste - und dann hast du ein problem), dass ein null pointer dereferenziert wird. das 2te if müsste vor dem ersten stehen.
-
ohhh vielen dank
so funktioniert es *freu*
danke dirhabe das letzde mit dem null pointer zwar nicht verstanden aber hauptsache ist ja das es tut
mfg geschen
-
hallo
habe doch ein fehler gefunden
und zwar wenn ich ein wort einfügen will das zwischen zwei gehört,bspl. b zwischen a und c, dann verschindet das a!!hat vielleicht auch jmd da ne ahnung woran es liegen könnte?
camper:
habe es jetzt alles so gemacht wie du gesagt hast, ausser das mit diesen codeif((strcmp(liste->name,cha->name)>=0)&&(strcmp(liste->name,(cha->nnach)->name)<0)) { (cha->nnach)->nvor=liste; liste->nnach=cha->nnach; liste->nvor=cha->nvor; cha->nnach=liste; pruef=1; }
das hab ich net verstanden
mfg geschen
-
else if((strcmp(liste->name,cha->name)>=0)&&(strcmp(liste->name,(cha->nnach)->name)<0)) { (cha->nnach)->nvor=liste; liste->nnach=cha->nnach; liste->nvor=cha; /* !!!!!! */ cha->nnach=liste; pruef=1; }
da war das problem. bzgl. des null pointers muss ich mich korrigieren, es war schon korrekt so, wie du es hattest; nur schwer verständlich.
hier mal wie ich es machen würde als anregung:struct LISTE *sortiere(struct LISTE *ein, int *anz, char einname[],int einjahr,float einpreis) { /* ich gehe davon aus, das ein auf den anfang der liste zeigt bzw. NULL ist andernfalls müsste man entweder erst den anfang der liste suchen oder in abhängigkeit des elements, auf das ein zeigt, die liste von dort ausgehend vorwärts oder rückwärts durchsuchen */ struct LISTE *neu; struct LISTE *prev=NULL; /* Zeiger auf das vorherige Element, also next->prev */ struct LISTE *next=ein; neu=(struct LISTE *)malloc(sizeof(struct LISTE)); if(neu==NULL) { printf("Speicher konnte nicht bereitgestellt werden!\n\n"); } else { strcpy(ein->name,einname); neu->jahr=einjahr; neu->preis=einpreis; /* die liste liegt sortiert vor, beginnend mit dem kleinsten element; wir suchen solange, bis wir das erste element, das grösser als das neue ist, gefunden haben, oder wir das ende der liste erreicht haben (next==NULL) */ while( next!=NULL && strcmp(neu->name,next->name)>=0 ) { prev = next; next = next->nnach; } /* jetzt den nnach pointer von neu initialisieren, und den rückwärtsgericheteten pointer von next auf neu, sofern next!=NULL */ neu->nnach = next; if( next != NULL ) next->nvor = neu; /* analog für nvor und prev, falls prev NULL ist, muss zusätzlich ein auf neu gesetzt werden, damit das funktionsergebnis der anfang der liste ist (und so auch der fall ein==NULL korrekt behandelt wird) */ neu->nvor = prev; if( prev != NULL ) prev->nnach = neu; else ein = neu; } return ein; }