0

C++ で、可変長レコードでいっぱいのバッファーをアルファベット順に並べ替えようとしています。以前、これを実装する方法を尋ねたところ、レコードへのポインターの配列をソートするように言われました。ポインターの配列を設定しましたが、各ポインターがレコードの先頭を指していることに気付きましたが、レコードがいつ停止したかを知る方法はありません。したがって、配列内の各ポインターが指すレコードを出力しようとすると、ポインターごとに、指すレコードから始まるすべてのレコードのバッファー全体が取得されます。(たとえば、バッファーが "Helloworld" を保持し、各文字にポインターがある場合、ポインターの配列を出力すると "Helloworldelloworldlloworldloworldoworldworldorldrldldd" が生成されます。) 明らかに、これは私が望んでいるものではありません。また、qsort はポインターの配列でも機能していないようです。デバッグすると、ポインタが指すメモリ空間は、ASCII文字セットの一部ではなく、入力ファイルに含まれていない非常に奇妙な文字を保持しているようです。私は非常に混乱しています。以下は私のコードです。今得た奇妙な結果を得ることなく、どうすればこれを行うことができますか? どうもありがとう、bsg。

int _tmain(int argc, _TCHAR* argv[])
{
    //allocate memory for the buffer
    buff = (unsigned char *) malloc(2048);
    realbuff = (unsigned char *) malloc(NUM_RECORDS * RECORD_SIZE);

fp = fopen("postings0.txt", "r");
        if(fp)
        {
            fread(buff, 1, 2048, fp);
            /*for(int i=0; i <30; i++)
                cout << buff[i] <<endl;*/

            int y=0;

 //create a pointer to an array of unsigned char pointers
    unsigned char *pointerarray[NUM_RECORDS];
    //point the first pointer in the pointer array to the first record in the buffer
            pointerarray[0] = &buff[0];
            int recordcounter = 1;  



        //iterate through each character in the buffer; 
    //if the character  is a line feed (denoting a new record),
// point the next pointer in the pointer array to the next 
//character in the buffer (that is, the start of the next record)
                for(int i=0;i <2048; i++)
            {
                if(buff[i] == char(10))
                {
                    pointerarray[recordcounter] = &buff[i+1];
                    recordcounter++;
                }


    }

//the actual qsort (NUM_RECORDS is a constant declared above; omitted here)
    qsort(pointerarray, NUM_RECORDS, sizeof(char*), comparator);

        }

        else 
            cout << "sorry";

        cout << sizeof(pointerarray)/sizeof(char*);
    for(int k=0; k < sizeof(pointerarray)/sizeof(char*);k++)
    {
        cout << pointerarray[k];
    }

int comparator(const void * elem1, const void * elem2)
{

    //iterate through the length of the first string
    while(*firstString != char(10))
    {
        return(strcmp(firstString, secondString));

                firstString++;
        secondString++;

        /       
    }
return 0;
    }
4

2 に答える 2

1

問題はコンパレーター関数にあると思います(投稿されたとおりにコンパイルされません)。 qsort配列要素へのポインタをコンパレータ関数に渡します。あなたの場合、それは配列に格納されているへのポインタになります。char*

のマニュアルページにqsortは、次の例が示されています。

static int
cmpstringp(const void *p1, const void *p2)
{
    /* The actual arguments to this function are "pointers to
      pointers to char", but strcmp(3) arguments are "pointers
       to char", hence the following cast plus dereference */

    return strcmp(* (char * const *) p1, * (char * const *) p2);
}

int
main(int argc, char *argv[])
{
    int j;

    assert(argc > 1);

    qsort(&argv[1], argc - 1, sizeof(char *), cmpstringp);

    for (j = 1; j < argc; j++)
        puts(argv[j]);
    exit(EXIT_SUCCESS);
}
于 2010-03-04T18:07:38.420 に答える
1

この質問は、基本的に「可変長レコードの長さをどのように知るか」に帰着します。レコード自体から、または他のデータから、何らかの方法で判断する必要があります。

1 つの方法は、ポインター/長さのペアを使用してレコードを参照することです。つまり、レコードの先頭へのポインターと長さ (int または size_t) を構造体に一緒に格納します。C++ では std::pair を使用でき、C では小さな構造体を定義できます。その後、これらの配列に対して qsort を使用できます。

あなたの場合、文字列を終了するために常に使用するので、char(10) を探すことで長さを知ることができます。これを認識しているカスタム比較 (strcmp は機能しません。NUL ターミネータが必要です) が必要です。

于 2010-03-04T18:08:22.433 に答える