2016-05-03 6 views
0

自分の環境をソートしようとしました。CでUnix環境をソート

My C++のバージョン(std :: sort行とCstrLessクラス)​​は動作しますが、qsortバージョンは失敗します。私は間違って何をしていますか?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <algorithm> 
extern char** environ; 


struct CstrLess{ 
    bool operator()(const char* s1, const char* s2){ return ::strcmp(s1,s2)<0; } 
}; 

int main(){ 
    char** env = environ; 
    size_t sz = 0; 
    for(;*env; env++,sz++) {;} //measure the env 

    //? 
    qsort(environ, sz, sizeof(char*), (int (*)(const void*, const void*)) strcmp); 

    /*std::sort(environ, environ + sz, CstrLess{});*/ 

    env = environ; 
    while(*env){ 
    printf("%s%c", *env++, '\0'); 
    } 

    return 0; 
} 
+0

あなたが「失敗」とはどういう意味ですか? – ecatmur

+0

'qsort'は' char * 'ではなく' strcmp'に 'char **'を渡します。 – BLUEPIXY

+0

@ecatmur出力はソートされません。 – PSkocik

答えて

2

qsort要素へポインタを比較するために、その比較関数を渡します。

qsort(environ, sz, sizeof(char*), 
    [](const void* a, const void* b) { 
     return strcmp(
      *reinterpret_cast<const char**>(a), *reinterpret_cast<const char**>(b)); }); 

ピュアC液:

int qsort_strcmp(const void* a, const void* b) { 
    return strcmp(*(const char**)(a), *(const char**)(b)); 
} 

// ... 

    qsort(environ, sz, sizeof(char*), qsort_strcmp); 
+0

これはタグ付きです。 – Lundin

+0

@ Lundin fixed、thanksありがとうございました。 – ecatmur

+0

'const char **' btwへのキャストはなぜですか?完全に余分なようです。 – Lundin

1

strcmpへのポインタはタイプint(*)(const char *, const char *)のですが、あなたは、ポインタがchar const*ポインタがstrcmpに渡されるために得ることをことを間接的に必要です。

qsortで期待されるタイプはint(*)(const void*, const void*)です。

ワイルドファンクションポインタの変換は未定義の動作です。醜いキャストでそれを沈黙させなかったなら、あなたのコンパイラは正当に警告/エラーを与えてしまったでしょう。異なるタイプの呼び出し規約が異なる可能性があるため、この未定義の動作は有効な問題です。

正しいアプローチは、ラッパー関数を記述し、代わりにそのポインタを渡すことです:

int strcmp_wrapper (const void* s1, const void* s2) 
{ 
    return strcmp(s1, s2); // implicit conversion from const void* to const char*. 
} 
関連する問題