2016-12-04 7 views
0

Während String zum Array meines Zeigers hinzugefügt wird, wird es vom letzten überschrieben. Kann mir jemand sagen, wo ist mein Fehler?Array von Zeigern zu char * in c mit qsort

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

int main(){ 
int ile = 3; 
const char * slowa[ile]; 
for(int j = 0; j < ile; j++){ 
    char string[30]; 
    gets(string); 
    slowa[j] = string; 
    printf ("%s dodalem pierwsza\n",string); 
} 
for (int i = 0; i < ile; i++) { 
    printf ("%s numer %d\n",slowa[i],i); 
} 
return 0; 
} 
+0

Es gibt keinen qsort in Ihrem Code-Snippet und Ihr Problem nichts zu tun hat. Können Sie den Titel Ihrer Frage korrigieren? –

+0

Nicht das Problem, aber: ** nie ** benutzen '' ''! Es wurde vor 5 Jahren aus dem C-Standard entfernt und ist seit 1999 veraltet. Verwenden Sie stattdessen "fgets". – Olaf

+0

Ja, das stimmt @Olaf, ich bin ziemlich sicher, dass die neueste Version von 'gcc' warnt, dass du es nicht benutzt. – RoadRunner

Antwort

2

Die Antwort ist in den folgenden zwei Zeilen Code:

char string[30]; 
... 
slowa[j] = string; 

Die Zuordnung setzt slowa[j] auf die Adresse der gleichen Puffer, ohne eine Kopie zu machen. Daher wird das letzte, was Sie in den Puffer setzen, von allen Elementen des Arrays slowa[] bis zur Position j-1 referenziert.

Um dieses Problem zu beheben, erstellen Sie Kopien, bevor Sie Werte in slowa speichern. Sie können Nicht-Standard-strdup verwenden oder verwenden malloc + strcpy:

char string[30]; 
gets(string); 
slowa[j] = malloc(strlen(string)+1); 
strcpy(slowa[j], string); 

In beiden Fällen müssen Sie free auf alle Elemente von slowa[] Array nennen, zu denen Sie Werte, um Speicherlecks zu vermeiden zugewiesen haben.

+0

danke, funktioniert perfekt. –

+1

Es ist eigentlich schlimmer: Der Puffer existiert nicht nach der ersten Schleife, also ruft das Programm undefiniertes Verhalten auf. – Olaf

2

Sie zeigen immer auf Array von Zeichen, die Stapelvariable ist es nur im Bereich der Funktion lokal zugeordnet, möglicherweise jede Deklaration von Zeichenfolge wird auf der gleichen Adresse wie vorherige Iteration in der Schleife sein. Sie könnten entweder anstelle Array von Zeichen der Verwendung von Speicher zuweisen jeder Schleifeniterationslatenzzeit oder Array verwenden und dann unter Verwendung von zB strdup wie

slowa[j] = strdup(string) : 
0

Speicher für die neue Zeichenfolge zuweisen Wie andere gesagt haben, müssen Sie Kopien der Saiten erstellen, Andernfalls setzen Sie die Zeichenfolgen auf die gleiche Adresse und überschreiben sich daher gegenseitig.

Darüber hinaus denke ich mit fgets über gets ist ein viel sicherer Ansatz. Dies liegt daran, gets ist sehr anfällig für buffer overflow, während mit fgets, können Sie einfach auf Pufferüberlauf überprüfen.

Dies ist ein Code ich vor einer Weile geschrieben, das ähnlich ist, was Sie versuchen zu erreichen: mit Sortier

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define PTRS 3 
#define STRLEN 30 

int 
string_cmp(const void *a, const void *b) { 
    const char *str1 = *(const char**)a; 
    const char *str2 = *(const char**)b; 
    return strcmp(str1, str2); 
} 

int 
main(void) { 
    char *strings[PTRS]; 
    char string[STRLEN]; 
    int str; 
    size_t len, i = 0; 

    while (i < PTRS) { 

     printf("Enter a string: "); 
     if (fgets(string, STRLEN, stdin) == NULL) { 
      fprintf(stderr, "%s\n", "Error reading string"); 
      exit(EXIT_FAILURE); 
     } 

     len = strlen(string); 

     if (string[len-1] == '\n') { 
      string[len-1] = '\0'; 
     } else { 
      break; 
     } 

     strings[i] = malloc(strlen(string)+1); 
     if (strings[i] == NULL) { 
      fprintf(stderr, "%s\n", "Cannot malloc string"); 
      exit(EXIT_FAILURE); 
     } 

     strcpy(strings[i], string); 

     i++; 
    } 

    qsort(strings, i, sizeof(*strings), string_cmp); 

    printf("\nSuccessfully read strings(in sorted order):\n"); 
    for (str = 0; str < i; str++) { 
     printf("strings[%d] = %s\n", str, strings[str]); 
     free(strings[str]); 
     strings[str] = NULL; 
    } 

    return 0; 
}