如何使用qsort对c ++中的字符串数组进行排序?

时间:2016-11-05 14:29:19

标签: c++

我正在使用qsort对c ++中的字符串数组进行排序。我的代码如下:

#include <iostream>
#include <cstdlib>
using namespace std;
int CompareString( const void * e1, const void * e2) {
    string * s1 = (string * ) e1;
    string * s2 = (string * ) e2;
    if( *s1 < *s2 )     return -1;
    else if( *s1 == *s2 ) return 0;
    else if( *s1 > *s2 ) return 1;
}
int main() {
    string Array[4] = {"hehe","789","456","123"};
    qsort(Array,4,sizeof(string),CompareString);
    for( int i = 0;i < 4;++i )
        cout << Array[i] << endl;
    return 0;
}

但它收到运行时错误。我确实知道那种有效,但我想知道为什么我不能使用qsort。谢谢:))

此问题与This Question类似 但是有一些不同之处。在那个问题中,人们建议使用sort,或者使用qsort来处理普通类型。但是,我的问题是我必须使用qsort而不是sort ,所以我的问题没有在那个问题中解决,而且我不认为我的问题是重复的。

至于为什么我必须使用qsort而不是sort,答案是&#34;这是作业的要求&#34;,链接是:Here。我将原来的问题翻译如下:

实现继承std:string的MyString类,代码应该使用以下代码正确编译和运行:

MyString SArray[4] = {"big","me","about","take"};
qsort(SArray,4,sizeof(MyString), CompareString);
for( int i = 0;i < 4;++i )
    cout << SArray[i] << endl;

MyString应该是这样的:

class MyString:public string{
...
};

这个原始问题需要MyString传递其他测试,我已经通过了。但是我仍然无法通过 qsort ,所以我对它进行了改编并询问了我的第一版问题。

从答案中,我可以得出结论,qsort不适用于非POD。由于MyString继承了字符串,而字符串是非POD,因此MyString是非POD,因此MyString无法通过测试。

谢谢大家回答我的问题:)

3 个答案:

答案 0 :(得分:2)

为了在数组中重新排列和移动C ++类,必须使用类的复制/移动构造函数和/或赋值运算符。 qsort()是一个C库函数,它对std::string或任何其他C ++类,其构造函数或析构函数一无所知。 qsort()不能用于对非POD类的向量进行排序。

使用std::sort()来对矢量进行排序。

答案 1 :(得分:1)

C qsort无法移动非POD对象。但它可以移动指针。因此,如果您必须使用qsortstd::string数组进行排序,则可以通过对相应的指针数组进行排序来实现:

#include <iostream>
#include <string>           // std::string
#include <vector>           // std::vector
#include <stdlib.h>         // qsort
using namespace std;

auto compare( void const* e1, void const* e2 )
    -> int
{
    string const* const p1 = *reinterpret_cast<string* const*>( e1 );
    string const* const p2 = *reinterpret_cast<string* const*>( e2 );
    return p1->compare( *p2 );
}

template< size_t n >
void sort( string (&a)[n] )
{
    vector<string const*> pointers;
    pointers.reserve( n );
    for( string& item : a ){ pointers.push_back( &item ); }
    qsort( &pointers[0], n, sizeof( pointers[0] ), compare );
    vector<string> result;
    result.reserve( n );
    for( string const* p : pointers ) { result.push_back( move( *p ) ); }
    for( int i = 0; i < int( n ); ++i ) { a[i] = move( result[i] ); }
}

auto main()
    -> int
{
    string strings[4] = { "hehe", "789", "456", "123" };
    sort( strings );
    for( string const& s : strings )
    {
        cout << s << endl;
    }
}

答案 2 :(得分:1)

您的代码

string Array[4] = {"hehe","789","456","123"};

产生4个字符串,而不是4个字符串指针,sizeof(std :: string)应该是3 * sizeof(void *)+如果您的实现使用SmallStringOptimization则为常量。

尝试我的思维技巧我会猜你认为Array是指向字符串的指针或字符串本身就是一个指针。

最初声明字符串是这样的(如果删除所有模板的东西)。

class string {
  size_t length;
  size_t capacity
  char *buffer;
};

如果您已声明您的数组

std::string *Array[4] = {
  new std::string("hehe"),
  new std::string("789"),
  new std::string("456"),
  new std::string("123")
};

它会起作用。

您可以看到整个代码here