Использование qsort для сортировки целых чисел без знака

Программа, над которой я работаю, берет файл и анализирует его построчно, затем изменяет каждую строку на uint32_t и добавляет ее в массив. Оттуда я должен отсортировать массив с помощью qsort(). Я написал свою программу так, как я думал, но когда я тестирую код, он говорит, что все новые uint32_ts имеют одно и то же значение. Это из-за ошибки, когда я меняю строку на uint32_t? Было бы лучше использовать strtoul? Последний вопрос: правильно ли реализован мой qsort? (он компилируется и говорит, что отсортировал вещи, но я не уверен, так как мое преобразование в uint_32 явно неверно. В любом случае, вот код:

int main(int argc, char* argv[]){
  char const* const fileName = argv[1];
  FILE* file = fopen(fileName, "r"); // should check the result
  char line[256];
  uint32_t parArray[256];
  int compar(const void *a, const void *b){
     const unsigned long long *x = a, *y = b;
     if(*x > *y)
       return 1;
     else
       return(*x < *y) ? -1: 0;
   }
  int lineCounter = 0; // starts at 0 for the array
  while(fgets(line, sizeof(line), file)){
     // parse all info here
     uint32_t t = (uint32_t) line;
     // build the array
     parArray[lineCounter]=t;
     lineCounter++;
     printf("Original: %s, Unsigned Int: %u\n", line,t); 
  }
  qsort(&parArray[0],lineCounter+1,sizeof(uint32_t*),compar);
  int i;
  for(i=0;i<lineCounter;i++){
    printf("%u\n",parArray[i]);
  }
  return 0;
}

person Dan Bradbury    schedule 09.02.2012    source источник
comment
Определение функции внутри другой функции (здесь compar внутри main) является расширением gcc. Если вы хотите, чтобы ваш код был переносимым, вам не следует использовать это. Просто переместите свое определение compar перед main.   -  person Jens Gustedt    schedule 10.02.2012


Ответы (2)


Вы не анализируете строки, когда читаете их. Приведение line к uint32_t просто берет адрес этого массива в памяти. Это объясняет, почему каждая строка вывода одинакова. Вы, вероятно, захотите вместо этого вызвать strtoul(line, NULL, 10) или что-то подобное.

Кроме того, ваш второй параметр для qsort отключен на единицу. lineCounter имеет правильное значение на момент завершения цикла: количество строк в файле. Добавляя один, вы вводите неопределенное поведение, читая заполненные значения в массиве.

person warrenm    schedule 09.02.2012

uint32_t t = (uint32_t) line;

Это неправильный способ преобразования строки в число в C. Вероятно, вместо этого вы захотите использовать strtoul. И ваш qsort тоже неверен (неправильное количество элементов, неправильный размер элемента).

parArray[lineCounter] = strtoul(line, NULL, 10);

/* ... */
qsort(parArray, lineCounter, sizeof(uint32_t), compar);

Вы определяете свою функцию compar внутри другой функции. Это расширение GCC, и вам не следует его использовать, если вы не планируете переносимость.

person cnicutar    schedule 09.02.2012
comment
спасибо, это было точно. Ваше объяснение было намного лучше, чем что-либо еще, что я читал - person Dan Bradbury; 10.02.2012
comment
Никогда не делай этого! вы знаете, троглодиты, работающие рабами в шахтах GCC, долго и упорно работали, чтобы вы могли сразу же отбросить их расширения ;-) - person Steve Jessop; 10.02.2012
comment
Или, во всяком случае, с лямбда-лифтом. - person Steve Jessop; 14.02.2012