2015-04-02 3 views
2

У меня есть программа, которая запрашивает несколько строк и должна сортировать их. Мой код:Сортировка строк с qsort не работает

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

#define MAX_STR_LEN 256 

int myStrCmp (const void * a, const void * b) 
{ 
    return strcmp((const char *)a, (const char *)b); 
} 

int main(void) 
{ 
    int strNum; // expected number of input strings 
    int strCnt; // counter of strings 
    char ** storage; // pointr to the memory when strings are stored 
    char strBuf[ MAX_STR_LEN]; // buffer for strings 
    char * strPtr; 
    // input of strings number 
    do{ 
     printf("How many strings will be entered: "); 
     while(scanf("%d", &strNum) != 1) 
     { 
      printf("ERROR: Not number was entered!\n"); 
      while(getchar() != '\n'); 
      printf("Please enter a number: "); 
     } 
     if(strNum < 2) 
     { 
      printf("ERROR: Number less than 2 was entered!\n"); 
     } 
     while(getchar() != '\n'); 
    } 
    while(strNum < 2); 
    // allocation of memory for pointers 
    storage = (char **) calloc(strNum, sizeof(char*)); 
    if(storage == NULL) 
    { 
     printf("ERROR: Unexpected problems with memory allocation!\n"); 
     return 1; 
    } 
    // input of strings 
    for(strCnt = 0; strCnt < strNum; strCnt++) 
    { 
     printf("Enter string #%d:\n", strCnt + 1); 
     fgets(strBuf, MAX_STR_LEN, stdin); 
     strPtr = strchr(strBuf, '\n'); 
     if(strPtr) 
     { 
      *strPtr = '\0'; 
     } 
     else 
     { 
      strBuf[ MAX_STR_LEN - 1] = '\0'; 
     } 
     // allocation memory for particular string 
     storage[strCnt] = (char *) malloc(strlen(strBuf) + 1); 
     if(storage[strCnt] == NULL) 
     { 
      printf("ERROR: Unexpected problems with memory allocation!\n"); 
      return 2; 
     } 
     // move string to dynamic memory 
     strcpy(storage[strCnt], strBuf); 
    } 
    // sort the strings 
    qsort(storage, strNum, sizeof(char**), myStrCmp); 
    // output the result 
    printf("\nSorted strings:\n"); 
    for(strCnt = 0; strCnt < strNum; strCnt++) 
    { 
     printf("%s\n", storage[strCnt]); 
    } 
    return 0; 
} 

Самый простой тест показывает проблемы:

How many strings will be entered: 3 
Enter string #1: 
ddd 
Enter string #2: 
aaa 
Enter string #3: 
ccc 

Sorted strings: 
ddd 
aaa 
ccc 

Я судимое Visual C++ и GCC, но результат тот же. Пожалуйста, скажите мне, что не так в коде?

+1

Hi SannyD! Я ценю, что вы включили исходный код и пример запуска программы. Вы делаете гораздо лучше, чем большинство из них, с их первым вопросом о StackOverflow. Одна вещь, которую вы могли бы сделать, чтобы сделать ваш вопрос еще лучше, - это жестко ввести ввод. Перед вызовом 'qsort()' существует значительная часть кода. Вы могли бы пойти туда и просто записать его так, чтобы «хранилище» всегда было одним и тем же 5 строк. Это сделает ваш вопрос __awesome__! –

+0

Спасибо за консультацию. В следующий раз, я сделаю. –

+0

Примечание: вместо 'storage = (char **) calloc (strNum, sizeof (char *));', рассмотрите 'storage = calloc (strNum, sizeof * storage);' Легче кодировать и поддерживать. – chux

ответ

4

Проблема в myStrCmp функция.

Поскольку a и b являются элементами не простой массив, но в массиве указателей, их тип должен быть char ** и функция, которая сравнивает два элемента должны быть следующими:

int myStrCmp (const void * a, const void * b) 
{ 
    return strcmp(*(const char **)a, *(const char **)b); 
} 
+0

Это решение отлично сработало для меня, хотя я не уверен на 100%, я понимаю, почему это должно быть так концептуально. Кто-нибудь хочет попытаться объяснить это дальше? – ImpromptuMusic

+1

Я попытаюсь объяснить необходимость второго * ассоциативным примером. Представьте, у вас есть яблоки, и вы сортируете их по размеру (это простой случай и сравнить два яблока, которые вы указываете двумя пальцами разных рук на 2 яблока в один момент), они делают задачу более сложной - вы сортируете пакеты из яблок (поэтому объекты, которые нужно сравнить, это «объекты в пакете объектов» и для достижения яблока вам нужно указать пакет (первый *), а затем указать конкретное яблоко (второе *)). – VolAnd

+1

Как только яблоко похоже на одиночный символ, а строка (массив) похожа на пакет яблок, вы можете себе представить, что 'strcmp' подобен балансу для сравнения пакетов без распаковки. – VolAnd

Смежные вопросы