Fehler bei alphabetischer Sortierung der Buchstaben von Strings
-
Hallo.
Ich habe ein Programm geschrieben, was Strings in einer Stringtabelle auf verschiedene Weise sortiert. Eine Art ist, die Buchstaben jeden Strings alphabetisch zu sortieren. Soweit klappt das alles.
Das Problem ist, dass er bei der Sortierung beim 17. String plötzlich den 1. mit anderen Zeichen überschreibt, dann den Rest aber normal weiter sortiert.
In der Ausgabe sind dann in allen Strings die Buchstaben alphabetisch sortiert, nur im ersten stehen andere Zeichen. Beim Einzelschrittdurchlauf wurden die Buchstaben des ersten Strings aber korrekt sortiert.Hier die Funktion:
Funktionsaufruf:
char** strArray1 = lettersort(strArray);
char** lettersort(char *ptr[]) { char **ptrptr; ptrptr = (char**)malloc(sizeof(ptr)); for (int i=0;i<20;i++) { //printf("%s - %c\n",ptr[i],*(ptr[i])); int l = strlen(ptr[i]); ptrptr[i] = (char*)malloc(strlen(ptr[i])+1); // Hier tritt der Fehler auf aber nur bei i=16 strcpy(ptrptr[i],ptr[i]); for (int j=0;j<l-1;j++) { char text = *(ptrptr[i]+j); if (isupper(*(ptrptr[i]+j))) { *(ptrptr[i]+j) = tolower(*(ptrptr[i]+j)); } if (*(ptrptr[i]+j)>*(ptrptr[i]+j+1)) { char tmp = *(ptrptr[i]+j); *(ptrptr[i]+j) = *(ptrptr[i]+j+1); *(ptrptr[i]+j+1) = tmp; j = -1; } } } return ptrptr; }
Vielen Dank schon mal für eure Hilfe. Heiko
-
Hallo,
ptrptr = (char**)malloc(sizeof(ptr));
Das gibt dir lediglich ca. 4 Zeiger zurück, also ca. 16 zu wenig.
Das sich der Fehler erst beim xten Element bemerbar macht ( bei dir mit x = 16 )
ist normal für C Programme.Gruß,
B.B.
-
Danke für die Antwort.
Aber er sortiert die Buchstaben aller Strings jeweils alphabetisch und ändert dann irgendwann den ersten String. Das verstehe ich nicht so ganz. Wie kann ich das Problem lösen? Bin noch recht neu auf dem C-Gebiet und deshalb auch noch nicht so firm mit Zeigern etc. Bin schon froh, dass ich das so hinbekommen habe.
-
Okay, also wenn ich statt sizeof(ptr) 20 einsetze funktioniert es.
aber warum gibt er mir bei sizeof(ptr) 4 zurück, obwohl ptr Zeiger auf ein Array mit 20 Strings ist. Müßte er nicht eigentlich dann 20 zurückgeben?
-
Im der Parameterliste wird ein Array zum Zeiger, übergib einfach die Anzahl:
void lettersort_proto (char** arr, unsigned n) { }
Ich weiß nicht, wie du die Arrays erzeugst - die einzelnen Buchstaben der Zeilen lassen sich auch ohne Kopie manipulieren ( array[i][j] ).
Ist auch besser lesbar als *(array[i]+j) finde ich. Casten ist bei malloc nicht nötig.Hier noch andere Anregungen zum Thema, ich war etwas faul und habe qsort benutzt:
int compare ( const void* a, const void *b ) { return ( *(char*)a - *(char*)b ); } void lettersort (char** arr, unsigned n) { int i; for ( i = 0; i<n; i++ ) qsort ( arr[i], strlen(arr[i]), sizeof(char), compare ); } void show_array ( char** arr, unsigned n ) { int i = 0; while ( i<n ) puts(arr[i++]); } void free_array ( char** arr, unsigned n ) { int i = 0; while ( i<n ) free(arr[i++]); free (arr); } int main() { int nzeilen = 2; char* z[] = {"Zeile1", "Zeile2"}; char** arr; arr = malloc ( nzeilen * sizeof(char**) ); arr[0] = malloc ( strlen(z[0]) + 1 ); arr[1] = malloc ( strlen(z[1]) + 1 ); strcpy(arr[0], z[0]); strcpy(arr[1], z[1]); show_array(arr, nzeilen); lettersort(arr, nzeilen); show_array(arr, nzeilen); return 0; }
-
Okay, ich glaub ich weiß, warum der mir 4 zurückgibt: ptr ist ein Zeiger auf das Array und hat wahrscheinlich nen INT Wert, sizeof gibt die Byteanzahl zurück oder? INT sind 4 Byte, bei nem 32bit-System. Kann man irgendwie die Größe des Urspungsarrays über den Pointer herausbekommen oder muss ich die separat übergeben?
-
Also das Ursprungsarray ist im Code festeingegeben.
Die Sortierung sollte in einer extra Funktion passieren.
Und es sollte mit Zeigern gearbeitet werden.
Und da hab ich immer beim Buchstabentausch eine Access Violation bekommen, deshalb die Kopie.Ich habe jetzt einfach malloc(20) geschrieben, so funktioniert es un die Aufgabe ist erfüllt. Ist ja quasi dasselbe, als wenn ich die 20 der Funktion übergebe.
Danke für eure Hilfe, so ist mein Verständnis über die Zeiger schon wieder gewachsen.
-
Wie du schon richtig bemerkt hast gibt dir sizeof(ptr) die Größe des Zeigers, nicht die Größe des Objekts worauf ptr zeigt.
Normalerweise benutzt man sizeof(*ptr), damit dereferenziert man den Pointer und erhält das Objekt dessen Größe man haben will. Blöderweise zeigt der Pointer auf ein char welches 1 Byte groß ist, so war das nicht gedacht.
In deinem Fall möchtest du sizeof(strlen(ptr)+1) benutzen. strlen gibt dir die Länge eines Strings, +1 ist für das '\0'-Zeichen am Ende.
Von der 20 würde ich dir dringend abraten, irgendwann willst du mal strings sortieren, weißt dass du sowas schonmal gemacht hast, benutzt den Code und er funktioniert und irgendwas stürzt dann ab. Das allermindeste was du tun musst ist über deinen Code "//ACHTUNG: FUNKTIONIERT NUR MIT STRINGS BIS 19 ZEICHEN" schreiben.
Aber malloc(strlen(ptr)+1) ist natürlich besser, es sorgt dafür dass es immer funktioniert.
-
Vielen Dank für die Antwort. Die Speicherreservierung bezieht sich aber doch auf die komplette Stringtabelle, also die 20 wäre dann die Anzahl der Strings, nicht die Anzahl der Zeichen.
Habe das jetzt wie folgt gelöst:
char** lettersort(char *ptr[],int anz) { ... ptrptr = (char**)malloc(anz); for (int i=0;i<anz;i++) ... } void main(void) { ... int n = sizeof(strArray)/sizeof(char*); char** strArray1 = lettersort(strArray,n); ... }
So sollte es für beliebig große Stringtabellen funktionieren.
Danke nochmal an alle, die mir geholfen haben.