struct-Array sortieren
-
Hallo Freunde,
ich bin wieder hier um euch mein Seelenleid zu klagen
Ich habe ein struct-Array das folgendermaßen aufgebaut bzw. befüllt wird.void saveInput(sData *pData) { FILE *fPtr; sData *pData = (sData*) malloc(sizeof(sData)); printf("Name.....: "); scanf("%s", pData->name); printf("Stadt....: "); scanf("%s", pData->stadt); //save to Index (sorted) strcpy(index[counter].name, pData->name); index[counter].pos += sizeof(sData)*counter; //unflexibel (nicht geeignet wenn Element gelöscht wird) sortArray(index, counter, pData); counter++;
und die sortArray-Funktion (um die es nun auch gehen soll).
void sortArray(sIndex *index, int counter, sData *pData) { sIndex *temp = (sIndex *)malloc(sizeof(sIndex)); if(temp == NULL) { printf("Konnte keinen Speicher reservieren...\n"); return; } for(int i=0; i<counter; i++) { for(int j=i+1; j<=counter; j++) { if(strcmp(index[i].name, index[j].name) > 0) { *temp=index[j]; index[j]=index[i]; index[i]=*temp; } //if (strcmp(index[i].name, index[j].name) == 0) //{ // // //} } } free(temp); }
Das funktioniert auch alles wunderbar, aber ich benötige auch eine Lösung für doppelte Einträge im Array. Diese sollen gelöscht werden. Das soll in dem obigen auskommentierten Bereich (strcmp(index[i].name, index[j].name == 0)) passieren. Leider fällt mir keine Lösung dazu ein und bitte euch wiedermal um hilfe.
-
Welcher der beiden Einträge soll denn gelöscht werden, wenn du ein Duplikat findest? Ich würde ja beim Sortieren die Duplikate drin lassen und anschließend noch einmal drüberlaufen und sie löschen:
int i=1,j=1; for(;i<counter;++i) { if(strcmp(index[i].name,index[i-1].name)==0) { index[j]=index[i]; ++j; } }
-
also eigentlich ist es mir egal welcher der beiden Einträge gelöscht. Hauptsache einer der doppelten Einträge wird gelöscht. Ich hab mir halt gedacht, dass einer der doppelten Einträge (index[i].name) wieder auf NULL gesetzt wird. Allerdings ist nun das Problem, dass die NULL-Einträge auch beim sortieren berücksichtigt werden und dann logischerweise vor allen anderen Einträgen einsortiert wird.
-
Wie gesagt, eine Möglichkeit wäre es, die Doppeleinträge erstmal drinzulassen und nach dem Sortieren zu entsorgen. Alternativ kannst du auch deine Vergleichsfunktion so anpassen, daß NULL-Einträge größer als alle "normalen" Felder sind:
if[index[i].name==NULL || (index[j].name!=NULL && strcmp(index[i].name,index[j].name)>0))) { ... }
-
so habs jetzt hinbekommen, zwar nicht mit deiner Lösung CStoll, aber du hast mich auf ein paar Ideen gebracht. Hier mal der Code:
//Hier die Funktion, die die Eingaben speichert saveRet = delDuplicate(index, counter, pData); if (saveRet != NULL) { strcpy(index[counter].name, pData->name); index[counter].pos += sizeof(sData)*counter; sortArray(index, counter); counter++; } //------------------------------------------------------------------ //Hier die Funktion zur Löschung von Duplikaten sData * delDuplicate(sIndex *index, int counter, sData *pData) { for (int i=0; i<counter; i++) { if (strcmp(index[i].name, pData->name) == 0) { free(pData); pData = NULL; break; } } return pData; }
Ich habs halt jetzt mit dem Pointer gemacht (Juhu Pointer). Ich habe diesen der Funktion delDuplicate mitübergeben und diesen dann mit dem Array verglichen. Anschließend habe ich den Pointer wieder zurückgegeben und wenn dieser NULL ist dann mach nix.Wenn ich nichts übersehen haben, dann glaube ich Thats It. Kritik und Änderungsvorschläge erwünscht. Vielen Dank.
GiJoe/junkon2005
-
servus miteinander,
leider benötige ich wieder eure Hilfe. Ich dachte, dass mit dem löschen usw. funktioniert wunderbar, aber Pustekuchen. Nun habe ich so einigermaße die dazugehörige PrintList-Funktion geschrieben. Diese Funktion soll, wie der Name schon sagt den Inhalt der Datenbank sortiert ausgeben. Hier der Code:
void printList() { FILE *fPtr = fopen(PATH, "r"); sData *pData = (sData*) malloc(sizeof(sData)); for (int i=0; i<BUFF; i++) { fseek(fPtr, sizeof(sData)*i, SEEK_SET); if ((fread(pData, sizeof(sData), 1, fPtr)) == 0) { break; } else { //save to Index (sorted) if (delDuplicate(pData) != NULL) { strcpy(index[counter].name, pData->name); index[counter].pos = sizeof(sData)*counter; //unflexibel (nicht geeignet wenn gelöscht wird) sortArray(); counter++; } } } for (int j=0; j<counter; j++) { fseek(fPtr, index[j].pos, SEEK_SET); fread(pData, sizeof(sData), 1, fPtr); printf("Name.....: %s\n", pData->name); printf("Stadt....: %s\n\n", pData->stadt); } counter = 0; fclose(fPtr); printf("\nWeiter mit beliebiger Taste.\n"); _getch(); system("cls"); //<------- PROBLEM?? }
Wenn das Programm zu dem Punkt system("cls") kommt, meldet er folgenden Fehler:
Windows hat einen Haltepunkt in DB_Index.exe ausgelöst.
Dies kann auf eine Beschädigung des Heaps zurückzuführen sein und weist auf ein Problem in DB_Index.exe oder in einer der geladenen DLLs hin.
Wie kann er da einen Fehler habe und genau das ist auch das Problem. Er gibt so seltsame Fehler aus (die man nicht sonderlich gut nachvollziehen kann). Nun seid ihr dran
Gruß
GiJoe/junkon2005
-
Du hast ein großes Array mit malloc() angefordert, das kannst du nicht einfach stückchenweise an den Heap zurückgeben. Ich hatte dir dort oben doch eine Lösung angegeben, wie du Duplikate erkennen und "löschen" (im Prinzip nur überschreiben) kannst.
(PS: Bist du wirklich auf C festgelegt? Oder darf's auch C++ sein?)
-
Leider bin ich auf C angewiesen. Deine Variante mit doppelte Einträge löschen ist meiner Meinung nach nur eine if-Abfrage, in der du halt auch Einträge mit NULL berücksichtigst oder sehe ich das falsch.
Scheinbar kann ich dir bei deinen Ausführungen diesmal nicht folgen. Ich wäre allerdings sehr dankbar wenn du es mir evtl. anders erklären könntest. Vielen Dank
Gruß junkon2005
-
Ich meinte eigentlich die Variante aus meinem ersten Beitrag:
CStoll schrieb:
int i=1,j=1; for(;i<counter;++i) { if(strcmp(index[i].name,index[i-1].name)==0) { index[j]=index[i]; ++j; } }
Damit gehst du einmal durch das (sortierte) Array und entsorgst alle Duplikate, indem du die Elemente zusammenschiebst.
Der zweite Code lief darauf hinaus, wie in deinem Ausgangspost Duplikate bei Erkennung durch NULL zu ersetzen - und gleichzeitig den Vergleich so anzupassen, daß diese NULL-Einträge größer als alle echten Daten sind.