2010-03-04 2 views
0

Я пытаюсь сортировать буфер, полный записей переменной длины, в алфавитном порядке в C++. Ранее я спросил, как это реализовать, и ему было предложено отсортировать массив указателей на записи. Я настроил массив указателей, но понял, что каждый указатель указывает на начало записи, но нет способа узнать, когда запись прекратится. Когда я пытаюсь распечатать запись, на которую указывает каждый указатель в массиве, поэтому для каждого указателя я получаю весь буфер всех записей, начиная с указателя. (Например, если буфер хранит «Helloworld», и есть указатель на каждую букву, печать массива указателей приведет к созданию «Helloworldelloworldlloworldloworldoworldworldorldrldldd».) Очевидно, это не то, что я хочу; Кроме того, qsort, похоже, не работает над массивом указателей. Когда я отлаживаю, пространства памяти, на которые указывают указатели, похоже, содержат очень странные символы, которые определенно не являются частью набора символов ascii и не были включены в мой входной файл. Я очень смущен. Ниже мой код; как я могу это сделать без получения нечетных результатов, которые я получаю сейчас? Большое вам спасибо, bsg.C++ qsort массив указателей не сортировки

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; 
    } 
+5

Посмотрите больше как C, чем C++ для меня ... – ALOToverflow

+2

Ваша функция компаратора * очень * неверна - подумайте о том, что вы на самом деле пытаетесь сделать здесь. –

+1

Почему вы используете _tmain, но затем используете char непосредственно в остальной части кода? – jmucchiello

ответ

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); 
} 
1

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

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

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

Смежные вопросы