Как отсортировать этот массив указателей, не меняя тип исходного массива? - PullRequest
3 голосов
/ 26 июня 2011

Я создал этот файл, чтобы устранить некоторую путаницу с указателями и массивами указателей. Я понимаю вплоть до закомментированного кода и могу изменять порядок значений в p_to_pointers без изменения p_to_nums. Но у меня возникают проблемы при переводе его в qsort.

Вот мой вывод:

0 p_to_nums: 7 p_to_pointers: 7
1 p_to_nums: 4 p_to_pointers: 4
2 p_to_nums: 4 p_to_pointers: 4
3 p_to_nums: 2 p_to_pointers: 2
4 p_to_nums: 1 p_to_pointers: 1

Это желаемый результат:

0 p_to_nums: 4 p_to_pointers: 7
1 p_to_nums: 2 p_to_pointers: 4
2 p_to_nums: 7 p_to_pointers: 4
3 p_to_nums: 4 p_to_pointers: 2
4 p_to_nums: 1 p_to_pointers: 1

И мой код:

int compare_values (const void *a, const void *b) {
    const int *int_a = (const int *) a;
    const int *int_b = (const int *) b;

    return (*int_b > *int_a) - (*int_b < *int_a);
}

main() {

    int i;
    int nums[5];
    int *p_to_nums;
    int *p_to_pointers[5];

    nums[0] = 4;
    nums[1] = 2;
    nums[2] = 7;
    nums[3] = 4;
    nums[4] = 1;

    p_to_nums = &nums[0];

  for (i=0; i< 5; i++) {
        p_to_pointers[i] = &p_to_nums[i];
  }

    //p_to_pointers[0] = &p_to_nums[2];
    //p_to_pointers[2] = &p_to_nums[0];

    qsort(*p_to_pointers, 5, sizeof(int), compare_values);

    for (i=0; i< 5; i++) {
        printf("%d p_to_nums: %d p_to_pointers: %u\n", i, (p_to_nums[i]), *p_to_pointers[i]);
  }

  return 0;
}

Ответы [ 2 ]

3 голосов
/ 26 июня 2011

Вы сортируете * p_to_pointers с sizeof (int), тогда как я считаю, что вы хотите отсортировать p_to_pointers sizeof (int *).

Сравнить_значения нужно будет дважды откорректировать для разыменования.

Если ... и это большое, если ... Я понимаю, что вы пытаетесь сделать.

Кроме того, ваше сравнение в compare () излишне сложно. Вы можете просто сделать простое вычитание вместо двух сравнений и вычитания.

int compare_values (const void *a, const void *b) {
  const int **int_a = (const int **) a;
  const int **int_b = (const int **) b;

  return (**int_b - **int_a);
}

main() {

  int i;
  int nums[5];
  int *p_to_nums;
  int *p_to_pointers[5];

  nums[0] = 4;
  nums[1] = 2;
  nums[2] = 7;
  nums[3] = 4;
  nums[4] = 1;

  p_to_nums = &nums[0];

  for (i=0; i< 5; i++) {
    p_to_pointers[i] = &p_to_nums[i];
    printf("%d p_to_nums: %d p_to_pointers: %u\n", i, (p_to_nums[i]), *p_to_pointers[i]);
  }

  qsort(p_to_pointers, 5, sizeof(int *), compare_values);

  for (i=0; i< 5; i++) {
    printf("%d p_to_nums: %d p_to_pointers: %u\n", i, (p_to_nums[i]), *p_to_pointers[i]);
  }

  return 0;
}

Выход:

0 p_to_nums: 4 p_to_pointers: 4
1 p_to_nums: 2 p_to_pointers: 2
2 p_to_nums: 7 p_to_pointers: 7
3 p_to_nums: 4 p_to_pointers: 4
4 p_to_nums: 1 p_to_pointers: 1

0 p_to_nums: 4 p_to_pointers: 7
1 p_to_nums: 2 p_to_pointers: 4
2 p_to_nums: 7 p_to_pointers: 4
3 p_to_nums: 4 p_to_pointers: 2
4 p_to_nums: 1 p_to_pointers: 1
1 голос
/ 26 июня 2011

Первый аргумент qsort - *p_to_pointers.Это то же самое, что p_to_pointers[0], который вы установили на &p_to_nums[0].Это, в свою очередь, то же самое, что и p_to_nums.Таким образом, вы звоните на qsort в итоге эквивалентно

qsort(p_to_nums, 5, sizeof(int), compare_values);

Таким образом, вы сортируете p_to_nums.

То, что вы хотите, это

qsort(p_to_pointers, 5, sizeof(int*), compare_values);

Тогдаваше сравнение_значений должно конвертировать void* в int**, а не int*, и вам нужен дополнительный уровень косвенности в ваших разыменованиях.Обычный способ выполнить сравнение будет примерно таким:

int compare_values (const void *a, const void *b) {
    const int **int_a = a;
    const int **int_b = b;

    return **int_b - **int_a;
}

Обратите внимание, что в C приведение от void* не является необходимым (хотя в C ++ они есть).Также обратите внимание на более типичное вычитание в выражении return, а не на вашу довольно необычную конструкцию (хотя ваша работает).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...