2015-01-31 4 views
-3

Я пытаюсь создать отсортированный по алфавиту массив объектов из класса, который также содержит другую переменную int, но я не могу правильно выполнить функцию qsort. Вот мой код:Сортировка массива объектов в C++

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

int cmp (char **str1 , char **str2) 
{ 
    return strcmp(*str1,*str2); 
} 

class myclass 
{ 
int id; 
char text[50]; 
public: 
    void add(char a[], int i) { strcpy(text,a); id=i; } 
    void show(void) { std::cout<<text<<std::endl; } 
}; 


int main (void) 
{ 
    myclass * myobject[4]; 
    myobject[0] = new myclass; 
    myobject[1] = new myclass; 
    myobject[2] = new myclass; 
    myobject[3] = new myclass; 
    myobject[0]->add("zoom",1); 
    myobject[1]->add("zoo",2); 
    myobject[2]->add("animal",3); 
    myobject[3]->add("bull",4); 

    qsort (myobject,4,sizeof(char *), (int (*)(const void *, const void *)) cmp); 

    for (int i=0; i < 4; i++) 
    myobject[i]->show(); 

    return 0; 
} 
+0

И 'qsort()' на самом деле есть? –

+2

@ πάνταῥεῖ Стандартная библиотечная функция C/C++. – Barmar

+4

Почему бы не использовать контейнер 'std' вместо массива. Затем вы можете использовать 'std :: sort' или использовать контейнер, который постоянно сортирует данные. – Barmar

ответ

0

Во-первых, ваша функция сравнения должна быть в состоянии получить доступ к частному члену текстовому из MyClass.

Вы можете либо сделать текст общественности или добавить

friend int cmp (const void *, const void*); 

в определении класса.

Во-вторых, ваша функция сравнения неверна. Он принимает указатели на элементы массива для сортировки. Вы должны написать это:

int cmp (const void *ptr1 , const void *ptr2) 
{ 
    myclass *m1 = *(myclass**)ptr1; 
    myclass *m2 = *(myclass**)ptr2; 

    return strcmp(m1->text, m2->text); 
} 
+0

Вот только мне нужно, чтобы все это работало. Благодарим вас за подсказку кода вашего друга, я забыл об этом! – DvD23

0

Ваша функция сравнения неправильно. Он получает указатель на каждый элемент массива, который является указателем на myclass, а не text. Вы также не должны бросать указатель функции при вызове qsort, вы должны использовать аргументы в функции сравнения.

int cmp (void *a, void *b) { 
    myclass **c1 = (myclass **)a; 
    myclass **c2 = (myclass **)b; 
    return strcmp((*c1)->text, (*c2)->text); 
} 
+0

Этот ответ решил проблему, большое спасибо Бармару! – DvD23

+0

@NicholasM Я упомянул об этом в комментарии. – Barmar

+0

Вы правы; Я удалю свой комментарий. – NicholasM

1

Прямо сейчас, ваш код выглядит деформированной версии кода C, с достаточным количеством C++ «посыпают», чтобы сохранить его от работы с компилятором. По крайней мере, IMO, это дает в значительной степени худшее из обоих миров - он удаляет большинство лучших функций C и лучшие возможности C++. Если вы собираетесь писать на C++, писать C++, не деформирован C.

Для создания и сортировки коллекции объектов в C++, вероятно, вы должны написать код больше, как это:

#include <iostream> 
#include <string> 
#include <vector> 
#include <algorithm> 

class myclass 
{ 
    int id; 
    std::string text; 
public: 
    myclass(std::string const &a, int i) : id(i), text(a) {} 

    bool operator<(myclass const &other) { 
     return text < other.text; 
    } 

    friend std::ostream &operator << (std::ostream &os, myclass const &m) { 
     return std::cout << m.text << "\n"; 
    } 
}; 


int main() 
{ 
    std::vector<myclass> myobjects{ 
     { "zoom", 1 }, 
     { "zoo", 2 }, 
     { "animal", 3 }, 
     { "bull", 4 } 
    }; 

    std::sort(myobjects.begin(), myobjects.end()); 

    for (auto const &o : myobjects) 
     std::cout << o; 
} 

По крайней мере, на мой взгляд, это немного проще и легче понять. Это не утечка памяти. Если (например) мы добавили еще один элемент в коллекцию элементов, нам не пришлось бы переписывать другой код, чтобы это учесть.

Возможно, что более важно, чем любой из вышеперечисленных, по крайней мере для меня это ведет к более быстрой, простой и более безаварийной разработке. Например, приведенный выше код был без ошибок (работал правильно) при первом компиляции. Помимо исправления пары очевидных опечаток (например, я неправильно напечатал operator как opertor), он скомпилировался и работал точно так же, как я изначально набрал его. В качестве небольшого бонуса он, вероятно, работает быстрее, чем C-подобная версия. Только с 4 элементами разница в скорости не будет заметной, но если бы у вас было (например) тысячи предметов, то std::sort почти наверняка было бы значительно быстрее, чем qsort (в два-три раза быстрее, чем обычно).

+0

Да, вы прав, но я должен скомпилировать свой файл в Dev-C++, который использует устаревшие библиотеки, и именно поэтому я пытался использовать qsort. Спасибо за ваш код, я сохраню его для будущих программ! – DvD23

+0

@ DvD23: Если вы используете такой старый компилятор, ему действительно не хватает 'std :: sort', единственным разумным ответом является обновление компилятора. Все, что было выпущено за последние 20 лет (или так), должно иметь 'std :: sort'. –

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