4

c-library の qsort 関数を学習してみました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

私はエラーを理解することができません。助けてください。

4

6 に答える 6

11

qsortの配列に対しては使用できませんし、使用してはなりませんstd::string。要素は自明な型である必要がありますが、文字列はそうではありません。したがって、動作は未定義です。25.5/4 (「qsort」) から:

baseが指す配列内のオブジェクトが自明な型でない限り、動作は未定義です。

その理由はqsortmemcpy配列要素が周囲にあるためです。これは、一般に C++ オブジェクトでは不可能です (十分に自明でない限り)。


自明な型がある場合は、この一般的な qsorter-comparator を使用できます (ただし、もちろん、これはひどい考えであり、インライン化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代わりに使用してください。

于 2012-09-17T12:42:37.947 に答える
9

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"));
}

AFAIK -std::sortクイックソートを使用します。

[更新] コメントを参照してください。 std::sort は必ずしも純粋なクイック ソートではありません。

[更新2]

qsort - を学習したい場合は、 に基づいて関数を変更std::stringして定義します。qsort は配列内の要素へのポインターを渡すことに注意してください。見る:const char*strcmpconst 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"));
}
于 2012-09-17T12:41:55.953 に答える
3

問題は、qsort に C++ 文字列の配列を与えることです。比較関数では、C 文字列を (const char*) にキャストしているため、C 文字列を除外しているようです。

また、qsort の 3 番目のパラメーターであるデータのサイズは、実際には間違った値を指定します。sizeof(obj[0].length()) は sizeof(size_t) になりますが、これは明らかに間違っています。sizeof(obj[0]) の方が正確ですが、qsort は文字列のコピー コンストラクターを呼び出さないため、問題が発生する可能性があることに注意してください。

C++ 文字列で qsort を使用しないことをお勧めします。

正しい解決策については、PiotrNycz が提供する回答を参照してください。

于 2012-09-17T12:43:07.573 に答える
0

std::sortC++ 標準ライブラリ (<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);
}
于 2012-09-17T12:47:21.357 に答える
-1

のサイズの宣言に誤りがあります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];
于 2012-09-17T12:43:36.987 に答える
-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;
}
于 2012-09-17T12:44:42.673 に答える