Я пытался узнать функцию qsort c-библиотеки stdlib
, Это предусмотрено даже в c++
, Но я не понимаю, как использовать их для сортировки c++
строки. Я не уверен, какие параметры должны быть для sizeof()
оператор и будь моим compare_str
Код правильный. Я попробовал этот код:
#include<iostream>
#include<cstdlib>
using namespace std;
#include<string>
int compare_str( const void *a, const void *b){
string obj = (const char*)a;
string obj1 = (const char*)b;
return obj.compare(obj1);
}
int main(){
string obj[4] = {"fine", "ppoq", "tri", "get"};
qsort(obj, 4, sizeof(obj[0].length()), compare_str);
for( int i=0; i<4; i++)
cout<<obj[i]<<endl;
return 0;
}
Мой вывод был:
ppoq
tri
get
fine
Я не могу разобрать ошибку. Пожалуйста помоги.
Вы не можете и не должны использовать qsort
на массиве std::string
s. Элементы должны быть тривиальный тип, какие строки не являются, и, следовательно, поведение не определено. От 25,5 / 4 («qsort»):
Поведение не определено, если только объекты в массиве не указаны
base
имеют тривиальный тип.
Причина в том, что qsort
будут memcpy
окружающие элементы массива, что невозможно для объектов C ++ в целом (если они не достаточно тривиальны).
Если у вас есть тривиальный тип, вы можете использовать этот универсальный компилятор qsorter (но, конечно, это ужасная идея, и std::sort
всегда предпочтительнее)
template <typename T>
int qsort_comp(void const * pa, void const * pb)
{
static_assert<std::is_trivial<T>::value, "Can only use qsort with trivial type!");
T const & a = *static_cast<T const *>(pa);
T const & b = *static_cast<T const *>(pb);
if (a < b) { return -1; }
if (b < a) { return +1; }
return 0;
}
Использование: T arr[N]; qsort(arr, N, sizeof *arr, qsort_comp<T>);
Не используйте это. использование std::sort
вместо.
Лучше быть ориентированным на C ++ и использовать std :: sort для вашего массива:
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
int main() {
std::string obj[4] = {"fine", "ppoq", "tri", "get"};
std::sort(obj, obj + 4);
std::copy(obj, obj + 4, std::ostream_iterator<std::string>(std::cout, "\n"));
}
НАСКОЛЬКО МНЕ ИЗВЕСТНО — std::sort
использует быструю сортировку.
Если хочешь выучить qsort — поменяй std::string
в const char*
и определить функцию на основе strcmp
, Помните, что qsort передает указатели на элементы в массиве — так разыменование const void*
получить const char*
, Увидеть:
#include <stdlib.h>
#include <string.h>
int compare_cstr(const void* c1, const void* c2)
{
return strcmp(*(const char**)(c1), *(const char**)(c2));
}
int main() {
const char* obj[4] = {"fine", "ppoq", "tri", "get"};
qsort(obj, 4, sizeof(obj[0]), compare_cstr);
std::copy(obj, obj + 4, std::ostream_iterator<const char*>(std::cout, "\n"));
}
Проблема в том, что вы даете qsort массив строк C ++. В вашей функции сравнения вы, похоже, исключаете строки C, поскольку вы приводите их к (const char *).
Также, третий параметр qsort, размер данных, вы на самом деле даете неправильное значение. sizeof (obj [0] .length ()) приведет к sizeof (size_t), что, очевидно, неверно. sizeof (obj [0]) будет более правильным, но помните, что qsort не будет вызывать конструктор копирования строки, что может привести к проблемам.
Я бы предложил не использовать qsort со строками C ++.
Смотрите ответ, предоставленный PiotrNycz для правильного решения.
Вы должны использовать std::sort
Функция шаблона, предоставляемая стандартной библиотекой C ++ (в <algorithm>
заголовочный файл). По умолчанию, std::sort
использует порядок сравнения меньше, чтобы упорядочить элементы (std::string
уже реализует operator<
). Если вам нужно указать условие заказа (например, сравнение строк без учета регистра), std::sort
позволяет указать объект функции заказа.
Пример:
#include <string>
#include <algorithm>
bool caseInsensitiveOrdering(const std::string& lhs, const std::string& rhs)
{
// return true if lowercase lhs is less than lowercase rhs
}
int main()
{
std::string names[] = {"chuck", "amy", "bob", "donna"};
size_t nameCount = sizeof(names) / sizeof(names[0]);
// Sort using built-in operator<
std::sort(names, names + nameCount);
// Sort using comparison function
std::sort(names, names + nameCount, &caseInsensitiveOrdering);
}
Ваша ошибка в объявлении размера в qsort
, Ожидается размер члена, который в вашем случае является строкой. Итак, вы хотите использовать:
qsort(obj, 4, sizeof(string), compare_str);
Однако вам нужно работать с указателем на строку, а не на сами строки. Тогда код должен выглядеть так:
int compare_str( const void *a, const void *b){
const string* obj = (const string*)a;
const string* obj1 = (const string*)b;
return obj->compare(*obj1);
}
// ...
string* obj[4] = { new string("fine"), new string("ppoq"),
new string("tri"), new string("get") };
qsort(obj, 4, sizeof(string*), compare_str);
// And delete the objects
for(int i = 0 ; i < 4 ; ++i) delete obj[i];
Работает для меня:
#include<iostream>
#include<cstdlib>
using namespace std;
#include<string>
int compare_str( const void *a, const void *b){
string* obj = (string*)a;
string* obj1 = (string*)b;
return obj->compare(*obj1);
}
int main(){
string obj[4] = {"fine", "ppoq", "tri", "get"};
qsort(obj, 4, sizeof(string), compare_str);
for( int i=0; i<4; i++)
cout<<obj[i]<<endl;
return 0;
}