C ++ qsort массив указателей не сортирует - PullRequest
0 голосов
/ 04 марта 2010

Я пытаюсь отсортировать буфер, полный записей переменной длины, по алфавиту в 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;
    }

Ответы [ 2 ]

1 голос
/ 04 марта 2010

Этот вопрос в основном сводится к тому, «как узнать длину вашей записи переменной длины».Должен быть какой-то способ сказать, либо из самой записи, либо из других данных.

Один из способов - использовать пары указатель / длина для ссылки на записи - указатель на начало записи.и длина (int или size_t), которую вы храните вместе в структуре.С C ++ вы можете использовать std :: pair или с C определить небольшую структуру.Затем вы можете использовать qsort для этих массивов.

В вашем случае вы можете определить длину, посмотрев на char (10), так как вы всегда используете их для завершения ваших строк.Вам нужно пользовательское сравнение (strcmp не будет работать - он ожидает NUL-терминаторы), которое знает об этом.

1 голос
/ 04 марта 2010

Я предполагаю, что проблема в вашей функции компаратора (которая не компилируется как опубликовано). 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);
}
...