1

以下にデカール化された 2 次元配列があるとします。

char * Arr[4] = 
{
    {"124 -346  DATA...."},
    {"39479 -32 MOREDATA...."},
    {"12 -1 DATA2...."},
    {"100 -45 DATA4...."}
};

qsort()を使用してSECONDフィールドに従ってこの関数をソートしようとしています。つまり、文字列は秒の最小値 (-1、-32、-45、-346) に従って並べ替えられます。各値が 1 桁のみの場合にこの関数を作成する方法は知っていますが、プログラム内の桁は任意に長くなる可能性があります。ここに私が持っているものがありますが、プログラムがクラッシュします。このデータをソートするより効率的な方法があれば、ここに置きたいと思います(私の方法はあまり効率的ではないことはわかっています)。

ソート関数 (qsort() が呼び出す):

inline void GetStr(char *ix, char* Result)  //call to get second number in function
{
    char *spacing;              //iterator to traverse
    spacing = ix;               //iterator = pos of ix
    int LEN = 0;                //length and offset
    int Offset = 0;

    while(*spacing != ' ')      //while not at end of first num
    {
        Offset++;               //offset is more
        spacing++;
    }
    spacing++;                  //go one ahead of the space
    Offset++;

    while(*spacing != ' ')      //while not end of second number
    {
        spacing++;
        Offset++;
        LEN++;                  //length of number
    }
    strncpy(Result, ix + (Offset - LEN),LEN);
}

int sort(const void* a, const void* b)
{
    char *ia = *(char**)a;
    char *ib = *(char**)b;

    char * Str;
    char * Str2;
    GetStr(ia, Str);                                    //getting some strange errors....... program just crashes
    GetStr(ib, Str2);
    printf("Str: %s Str2: %s", Str, Str2);
    int n1 = atoi(Str);
    int n2 = atoi(Str2);
    return (n1 > n2);
}
4

2 に答える 2

3

このようなものから始めることができ、実際にどこかでsortを呼び出す必要があります。また、ファイルが大きい場合に何が起こるかを考慮する必要があります。

#include <stdio.h>

int
Sort(const void *a, const void *b)
{
    int *aa = a, *bb = b;
    return (aa[1] < bb[1]); //i need to sort by field, not a simple comparison. HOW?
}

int main(int argc, char **argv) {
  FILE *f = fopen(argv[1]);
  if (f) {
    char buffer[1024];
    int *v;
    int data[1024][5];
    int cnt = 0;
    while (fgets(buffer, sizeof(buffer), f)) {
        v = data[cnt++];
        sscanf(buffer, "%d %d %d %d %d", v, v+1, v+2, v+3, v+4);
    }
    fclose(f);
  }
  return 0;
}
于 2012-11-28T22:16:22.873 に答える
3

ここに少なくとも 1 つの問題があると思います。

strncpy(Result, ix + (Offset - LEN),LEN);

ドキュメントをstrncpy見ると、文字数制限に達した場合に、コピーされた文字列が自動的に null で終了しないことがわかります。したがって、Result文字列は null で終了しません。

これに変更してみてください:

strncpy(Result, ix + (Offset - LEN),LEN);
Result[LEN] = '\0';

もちろん、まだ Result 文字列用のメモリを提供する必要があります。現在、初期化されていないポインタをに渡していますGetStr():

char * Str;
char * Str2;

これらはかなり小さい整数なので、次のように静的に割り当てられたストレージを使用できます。

#define MAX_RESULT_LEN 64

/* ... */

char Str[MAX_RESULT_LEN]
char Str2[MAX_RESULT_LEN]

/* ... */

if (LEN > MAX_RESULT_LEN - 1) {
    LEN = MAX_RESULT_LEN - 1;
}

strncpy(Result, ix + (Offset - LEN),LEN);
Result[LEN] = '\0';

最後に、関数にはいくつかの問題がありますsort()qsort() のドキュメントを見ると、最初の引数がそれぞれより小さい、等しい、または大きいと見なされる場合、戻り値は「ゼロより小さい、等しい、または大きい整数」であることがわかります。二番目"。n1 - n2これを実現する最も簡単な方法は、 の代わりにロジックを使用することn1 < n2です。

また、タイプの引数char **も奇妙だと思いましたが、さらによく考えてみると、それらが正しいことがわかりました。qsort ドキュメントから:「比較対象のオブジェクトを指す 2 つの引数」。したがって、実際には、それらは C 文字列またはchar **.

したがって、ここに最終バージョンがあります:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_RESULT_LEN 64

void GetStr(char *ix, char* Result)  //call to get second number in function
{
    char *spacing;              //iterator to traverse
    spacing = ix;               //iterator = pos of ix
    int LEN = 0;                //length and offset
    int Offset = 0;

    while(*spacing != ' ')      //while not at end of first num
    {
        Offset++;               //offset is more
        spacing++;
    }
    spacing++;                  //go one ahead of the space
    Offset++;

    while(*spacing != ' ')      //while not end of second number
    {
        spacing++;
        Offset++;
        LEN++;                  //length of number
    }

    if (LEN > MAX_RESULT_LEN - 1) {
        LEN = MAX_RESULT_LEN - 1;
    }

    strncpy(Result, ix + (Offset - LEN),LEN);
    Result[LEN] = '\0';
}

int sort(const void* a, const void* b)
{
    char *ia = *(char **)a;
    char *ib = *(char **)b;

    char Str[MAX_RESULT_LEN];
    char Str2[MAX_RESULT_LEN];

    GetStr(ia, Str);
    GetStr(ib, Str2);

    printf("Str: %s Str2: %s", Str, Str2);
    int n1 = atoi(Str);
    int n2 = atoi(Str2);
    return (n1 - n2);
}

int main(void) {
    char * Arr[4] = 
    {
        {"124 -346  DATA...."},
        {"39479 -32 MOREDATA...."},
        {"12 -1 DATA2...."},
        {"100 -45 DATA4...."}
    };

    qsort(Arr, 4, sizeof(char *), sort);
}
于 2012-11-30T22:19:34.830 に答える