Как сравнить строку C ++, используя qsort в c?

Я пытался узнать функцию 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

Я не могу разобрать ошибку. Пожалуйста помоги.

3

Решение

Вы не можете и не должны использовать qsort на массиве std::strings. Элементы должны быть тривиальный тип, какие строки не являются, и, следовательно, поведение не определено. От 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 вместо.

11

Другие решения

Лучше быть ориентированным на 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 использует быструю сортировку.

[ОБНОВЛЕНИЕ] Смотрите комментарии, std :: sort не всегда чисто быстрая сортировка.

[UPDATE2]

Если хочешь выучить 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"));
}
8

Проблема в том, что вы даете qsort массив строк C ++. В вашей функции сравнения вы, похоже, исключаете строки C, поскольку вы приводите их к (const char *).

Также, третий параметр qsort, размер данных, вы на самом деле даете неправильное значение. sizeof (obj [0] .length ()) приведет к sizeof (size_t), что, очевидно, неверно. sizeof (obj [0]) будет более правильным, но помните, что qsort не будет вызывать конструктор копирования строки, что может привести к проблемам.

Я бы предложил не использовать qsort со строками C ++.

Смотрите ответ, предоставленный PiotrNycz для правильного решения.

3

Вы должны использовать 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);
}
0

Ваша ошибка в объявлении размера в 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];
-1

Работает для меня:

#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;
}
-1
По вопросам рекламы [email protected]