2016-12-04 3 views
0

При добавлении строки в массив моего указателя она перезаписывается последней. Может ли кто-нибудь сказать мне, где моя ошибка?Массив указателей на char * in c с использованием 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

Там нет QSort в вашем фрагменте кода и ваша проблема не имеет ничего общего с сортировкой. Можете ли вы определить название своего вопроса? –

+0

Не проблема, но: ** никогда не ** использовать 'get'! Он был удален из стандарта C 5 лет назад и был устаревшим с 1999 года. Вместо этого используйте 'fgets'. – Olaf

+0

Да, это правда @Olaf, я уверен, что самая новая версия 'gcc' предупреждает вас не использовать ее. – RoadRunner

ответ

2

Ответ в следующих двух строк кода:

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

Назначение устанавливает slowa[j] в адрес буфера же, не создавая копии. Следовательно, последнее, что вы положили в буфер, будет ссылаться на все элементы массива slowa[], до позиции j-1.

Чтобы устранить эту проблему, сделайте копии перед сохранением значений в slowa. Вы можете использовать нестандартные strdup или использовать malloc + strcpy:

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

В обоих случаях вам нужно позвонить free по всем элементам массива slowa[], к которому вы назначили значения для того, чтобы избежать утечки памяти.

+0

спасибо, отлично работает. –

+1

Это на самом деле хуже: буфер не существует после первого цикла, поэтому программа вызывает неопределенное поведение. – Olaf

2

Вы всегда указываете на массив символов, который является переменной стека локально распределен только в пределах функции, возможно, каждое объявление строки будет на том же адресе, что и предыдущая итерация в вашем цикле. Вы можете либо вместо того, чтобы использовать массив символов выделить память каждого цикла итерации или использовать массив, а затем с помощью т.е. strdup выделить память для новой строки, как

slowa[j] = strdup(string) : 
0

Как уже говорили другие, вам нужно создать копии строк, в противном случае вы устанавливаете строки на один и тот же адрес, и поэтому они просто перезаписывают друг друга.

Кроме того, я думаю, что использование fgets над gets является гораздо более безопасным подходом. Это связано с тем, что gets очень подвержен buffer overflow, тогда как с fgets вы можете легко проверить переполнение буфера.

Это некоторый код, который я написал некоторое время назад, который похож на то, что вы пытаетесь достичь:

#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; 
} 
Смежные вопросы