stdlibのqsort()を使用して、文字列の配列を並べ替えます
-
27-10-2019 - |
質問
いくつかの序文:私は、Javaの3学期(データ構造まで)の後、CでCでファーストクラスを受講しているコンピューターエンジニアリングの学生です。この質問は宿題の割り当てに関連していますが、私のためにそれを解決することからいくつかのステップが削除されました。
Memoryに読み取る入力ファイルがあり、Char [9] [500]に保存されます。最大長の最大500文字列を読み取ります。STDLIBの組み込みQSORT()関数を使用してこの配列をソートしようとしており、メモリエラーがいくつかあります。
コードの重要なスニペット:
char data[4][500][60];
char debug[500][9];
size_t count = 0;
/* initialize file, open for reading */
FILE* pUserlog;
pUserlog = fopen("userlog","r");
while(!feof(pUserlog))
{
fscanf(pUserlog, "%9s %8s %16s",debug[count], data[1][count], data[2][count]);
fgets(data[3][count], 60, pUserlog);
count++;
}
このセクションでは、データを配列に読み取ります。この部分の関心のある配列は「デバッグ」です。これは、上記で指定された配列です。これがQSORTの私の比較関数です:
int compare(const void* a, const void* b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
puts("I'm in compare!");
return strncmp(*ia, *ib,8);
}
これはQSORTを呼び出す私の試みです:
size_t debug_len = sizeof(debug)/sizeof(char*);
printf("debug len: %d, count: %d, sizeof(char*): %d\n",debug_len,count,sizeof(char*));
qsort(debug,count, sizeof(char *), compare);
私はcountがどこにあるかの電話でdebug_lenを置き換えようとしましたが、私はまだセグメントを断ち切っています。これが出力です:
$ ./test debug len: 1125, count: 453, sizeof(char*): 4 I'm in compare! Segmentation fault (core dumped)
ありがとうございました!
解決
比較関数は、比較されている要素へのポインターを受け取ります。使用して文字を効果的に比較しようとしています strncmp()
. 。各文字列へのポインターがあるので、 char *
比較してください。
int compare(const void* a, const void* b)
{
const char *ia = (const char *)a;
const char *ib = (const char *)b;
puts("I'm in compare!");
return strncmp(ia, ib, 9);
}
また、それは一連の配列であり、ポインターの配列ではないことを忘れないでください。したがって、要素のサイズは配列のサイズでなければなりません。 9
ポインターではなく、 4
. 。この時点で、使用する方が簡単です sizeof debug[0]
2次元配列なので。適切なサイズでこれを行わない場合、 qsort()
配列を破壊するだけです。
size_t elemsize = sizeof debug[0]; /* 9 - size of each element */
size_t count = sizeof(debug)/elemsize; /* 500 - number of elements in array */
qsort(debug, count, elemsize, compare);
他のヒント
ここで起こることは、500文字列があることです。これで、500すべてをQSORTに渡すと、それぞれが最初と2番目の引数として順番に渡されます。それはこれを書くようなものです:
compare(debug[0], debug[1])
Cコンパイラは、もちろん実際の値ではなくアドレスに渡されます。しかし、これで、ポインターからボイドをポインターからポインターまで解釈します。あなたのコードは、呼び出すときに控えめになります strncmp
, 、しかし、それは 価値 (最初の4バイト)はポインターとして扱われます strncmp
. 。しかし strncmp
今度は、ゴミの「ポインター」(文字列の1つの一部で構成される)を繰り返しますが、それは 強打.
これを修正するには、使用してください char *
それ以外の char **
:
int compare(const void* a, const void* b)
{
puts("I'm in compare!");
return strncmp((const char *)a, (const char *)b, 8);
}