Сортировка списка по всем полям в любых направлениях. Использовать указатели на функции - C (СИ)

Узнай цену своей работы

Формулировка задачи:

В общем, я запутался. Вот задание. Необходимо разработать программу согласно варианту задания. При реализации использовать указатели на функции и (или) массивы указателей на функции. -------------------------------------------------- Дан список записей типа ТОВАР (размер списка и его элементы вводятся пользователем). Упорядочить список по любому из полей в любом направлении. Поле и направление выбирает пользователь. В функцию сортировки должен передаваться указатель на функцию сравнения двух элементов. (20 баллов). ТОВАР: - наименование товара (строка 15 символов); - единицы измерения (строка 5 символов); - цена (вещественное число с двумя знаками после запятой); - количество (целое положительное число). То, что накалякано
Листинг программы
  1. #include <stdio.h>
  2. #include <stddef.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <conio.h>
  6. typedef struct
  7. {
  8. char name[16];
  9. char mesr[6];
  10. double price;
  11. int count;
  12. }Good;
  13. typedef Good *Ptr;
  14. typedef int (*Pfun)( void *, void * );
  15. int cmpNM ( void *, void * );
  16. int cmpCNT( void *, void * );
  17. void sortbychoice( Ptr , int, size_t, void (*), Pfun );
  18. void swap ( Ptr , Ptr );
  19. int main( int argc, char *argv[ ] )
  20. {
  21. //printf( "%d", offsetof( Good, count) );
  22. int d = 0, count;
  23. printf( "Enter count of lists: ");
  24. while( !d || count <= 0)
  25. {
  26. d = scanf( "%d", &count );
  27. if( !d || count <= 0 ) { while( getchar( ) != '\n' ); printf( "Repeat: "); }
  28. }
  29. fflush( stdin );
  30. int i;
  31. Ptr list = (Good*)calloc( count, sizeof(Good));
  32. for( i = 0; i < count; i++ ) { printf( "Name|Measure|Price|Count: " ); scanf( "%s%s%lf%d", list[i].name, list[i].mesr, &list[i].price, &list[i].count ); while( getchar( ) != '\n' );}
  33. //
  34. //sortbychoice( list, count, sizeof(char)*15, list[i].name, cmpNM );
  35. sortbychoice( list, count, offsetof( Good, count ), &list[i].count, cmpCNT);
  36. for( i = 0; i < count; i ++ ) printf( "Name: %s | Measure: %s | Price: %3.2lf | Count: %03d\n", list[i].name, list[i].mesr, list[i].price, list[i].count );
  37. system( "pause" );
  38. getch( );
  39. return 0;
  40. }
  41. void swap ( Ptr arg1, Ptr arg2 )
  42. {
  43. Good temp = *arg1;
  44. *arg1 = *arg2;
  45. *arg2 = temp;
  46. return;
  47. }
  48. int cmpNM( void * arg1, void * arg2 )
  49. {
  50. if( strcmp( (char*)arg1, (char*)arg2 ) == 1 ) return 1;
  51. else return 0;
  52. }
  53. int cmpCNT( void * arg1, void *arg2 )
  54. {
  55. if(*((int*)arg1) > *((int*)arg2)) return 1;
  56. else return 0;
  57. }
  58. void sortbychoice ( Ptr good, int count, size_t size, void *arr, Pfun fun )
  59. {
  60. Ptr mass = good;
  61. int i, j, im;
  62. char * ar = ( char* )arr;
  63. for( i = 0; i < count - 1; i++ ){
  64. im = i;
  65. for( j = i + 1; j < count; j++ ) if( fun( (void*)( ar + im*size), (void*)( ar + j * size )) ) im = j;
  66. swap( &mass[i], &mass[im] );
  67. }
  68. return;
  69. }
дело в том, что я не могу понять, как мне обращаться к началу памяти одного и того же поля в массиве структур. Делал такое с обычными массивами, вроде всё работало. Вот как делал:
Листинг программы
  1. void SortArray( void *array, unsigned num, size_t size, int (*fun)(void *arg1, void *arg2), void (*fun1)( void *arg1, void *arg2))
  2. {
  3. int i, j;
  4. int imin, imax;
  5. char *ptr = (char* )array; // указатель на начало памяти массива
  6. for( i = 0; i < num - 1; i += 2 )
  7. {
  8. imin = i;
  9. for( j = i + 2; j < num; j += 2 )
  10. if( fun( (void*)(ptr + imin*size), (void*)(ptr + j*size)) > 0 ) imin = j;
  11. fun1( ptr + i*size, ptr + imin*size);// смещение указателя на size бацтов массив
  12. }
  13. for( i = 1; i < num - 1; i += 2 )
  14. {
  15. imax = i;
  16. for( j = i + 2; j < num; j += 2 )
  17. if( fun( (void*)(ptr + imax*size), (void*)(ptr + j*size)) < 0 ) imax = j;
  18. fun1( ptr + i*size, ptr + imax*size );// смещение указателя на size бацтов массив
  19. }
  20. }
//sortbychoice( list, count, sizeof(char)*15, list[i].name, cmpNM ); * * sortbychoice( list, count, offsetof( Good, count ), &list[i].count, cmpCNT);
На эти строки на намекать. Исправил
В общем, для сортровки по кол - ву работает вроде.
Листинг программы
  1. void sortbychoice ( Ptr good, int count, void *arr, Pfun fun )
  2. {
  3. Ptr mass = good;
  4. int i, j, im;
  5. char * ar = ( char * )arr; // указатель на начало памяти выбранного поля аргумента arg
  6. for( i = 0; i < count - 1; i++ ){
  7. im = i;
  8. for( j = i + 1; j < count; j++ ) if( fun( (void*)( ar + im*sizeof( Good)), (void*)( ar + j * sizeof(Good) )) ) im = j;
  9. swap( &mass[i], &mass[im] );
  10. }
  11. return;
  12. }
Сейчас попробую со строками также провернуть
В общем, пока работает. Если найдёте грабли ещё, укажите, пожалуйста.
Листинг программы
  1. #include <stdio.h>
  2. #include <stddef.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <conio.h>
  6. typedef struct
  7. {
  8. char name[16];
  9. char mesr[6];
  10. double price;
  11. int count;
  12. }Good;
  13. typedef Good *Ptr;
  14. typedef int (*Pfun)( void *, void * );
  15. int cmpNM ( void *, void * );
  16. int cmpCNT( void *, void * );
  17. void sortbychoice( Ptr , int, void (*), Pfun ); // для 1 - ого аргумента необходимо передать 2 - ой указатель
  18. void swap ( Ptr , Ptr );
  19. int main( int argc, char *argv[ ] )
  20. {
  21. //printf( "%d", offsetof( Good, count) );
  22. int d = 0, count;
  23. printf( "Enter count of lists: ");
  24. while( !d || count <= 0)
  25. {
  26. d = scanf( "%d", &count );
  27. if( !d || count <= 0 ) { while( getchar( ) != '\n' ); printf( "Repeat: "); }
  28. }
  29. fflush( stdin );
  30. int i;
  31. Ptr list = (Good*)calloc( count, sizeof(Good));
  32. for( i = 0; i < count; i++ ) { printf( "Name|Measure|Price|Count: " ); scanf( "%s%s%lf%d", list[i].name, list[i].mesr, &list[i].price, &list[i].count ); while( getchar( ) != '\n' );}
  33. //
  34. sortbychoice( list, count,list[0].name, cmpNM );
  35. //sortbychoice( list, count, &list[0].count, cmpCNT);
  36. for( i = 0; i < count; i ++ ) printf( "Name: %s | Measure: %s | Price: %3.2lf | Count: %03d\n", list[i].name, list[i].mesr, list[i].price, list[i].count );
  37. system( "pause" );
  38. getch( );
  39. return 0;
  40. }
  41. void swap ( Ptr arg1, Ptr arg2 )
  42. {
  43. Good temp = *arg1;
  44. *arg1 = *arg2;
  45. *arg2 = temp;
  46. return;
  47. }
  48. int cmpNM( void * arg1, void * arg2 )
  49. {
  50. if( strcmp( (char*)arg1, (char*)arg2 ) == 1 ) return 1;
  51. else return 0;
  52. }
  53. int cmpCNT( void * arg1, void *arg2 )
  54. {
  55. if(*((int*)arg1) > *((int*)arg2)) return 1;
  56. else return 0;
  57. }
  58. void sortbychoice ( Ptr good, int count, void *arr, Pfun fun )
  59. {
  60. Ptr mass = good;
  61. int i, j, im;
  62. char * ar = ( char * )arr;
  63. for( i = 0; i < count - 1; i++ ){
  64. im = i;
  65. for( j = i + 1; j < count; j++ ) if( fun( (void*)( ar + im*sizeof( Good)), (void*)( ar + j * sizeof(Good) )) ) im = j;
  66. swap( &mass[i], &mass[im] );
  67. }
  68. return;
  69. }

Решение задачи: «Сортировка списка по всем полям в любых направлениях. Использовать указатели на функции»

textual
Листинг программы
  1. #include  <stdio.h>
  2. #include  <stdlib.h>
  3. #include  <string.h>
  4.  
  5. #define MAXNAME 16
  6. #define MAXUNIT 6
  7.  
  8. typedef int (*Pf)(void*, void*);
  9.  
  10. typedef struct {
  11.     char  name[MAXNAME];
  12.     char  unit[MAXUNIT];
  13.     double price;
  14.     int quantity;
  15. } Product;
  16.  
  17. Product *product_list_alloc(int count)
  18. {
  19.     Product * list = malloc(count * sizeof(*list));
  20.     return list;
  21. }
  22.  
  23. void product_list_free(Product *list)
  24. {
  25.     free(list);
  26. }
  27.  
  28. void product_list_imput(Product *list, int count)
  29. {
  30.     for (size_t i=0; i<count; i++)
  31.     {
  32.         printf("Name|Measure|Price|Count: ");
  33.         scanf("%s %s %lf %d", list[i].name, list[i].unit,
  34.               &list[i].price, &list[i].quantity);
  35.     }
  36.  
  37. }
  38.  
  39. void product_list_print(Product *list, int count)
  40. {
  41.     for (size_t i=0; i<count; i++)
  42.     {
  43.         printf( "Name: %s | Measure: %s | Price: %3.2lf | Count: %3d\n",
  44.                list[i].name, list[i].unit, list[i].price, list[i].quantity );
  45.     }
  46.  
  47. }
  48.  
  49. static void swap(void *x, void *y, size_t l) {
  50.    char *a = x, *b = y, c;
  51.    while(l--) {
  52.       c = *a;
  53.       *a++ = *b;
  54.       *b++ = c;
  55.    }
  56. }
  57.  
  58. static void sort(char *array, size_t size, int (*cmp)(void*,void*), int begin, int end) {
  59.    if (end > begin) {
  60.       void *pivot = array + begin;
  61.       int l = begin + size;
  62.       int r = end;
  63.       while(l < r) {
  64.          if (cmp(array+l,pivot) <= 0) {
  65.             l += size;
  66.          } else if ( cmp(array+r, pivot) > 0 )  {
  67.             r -= size;
  68.          } else if ( l < r ) {
  69.             swap(array+l, array+r, size);
  70.          }
  71.       }
  72.       l -= size;
  73.       swap(array+begin, array+l, size);
  74.       sort(array, size, cmp, begin, l);
  75.       sort(array, size, cmp, r, end);
  76.    }
  77. }
  78.  
  79. void quicksort (void *array, size_t nitems, size_t size, int (*cmp)(void*,void*)) {
  80.    sort(array, size, cmp, 0, nitems*size);
  81. }
  82.  
  83. int name_cmp(void *a, void *b)
  84. {
  85.     Product *p1 = a;
  86.     Product *p2 = b;
  87.     return strcmp(p1->name, p2->name);
  88. }
  89. int name_rcmp(void *a, void *b)
  90. {
  91.     Product *p1 = a;
  92.     Product *p2 = b;
  93.     return strcmp(p2->name, p1->name);
  94. }
  95.  
  96. int quantity_cmp(void *a, void *b)
  97. {
  98.     Product *p1 = a;
  99.     Product *p2 = b;
  100.     return (p1->quantity - p2->quantity);
  101. }
  102. int quantity_rcmp(void *a, void *b)
  103. {
  104.     Product *p1 = a;
  105.     Product *p2 = b;
  106.     return (p2->quantity - p1->quantity);
  107. }
  108.  
  109. int main(void)
  110. {
  111.     int count;
  112.     Pf cmps[4] = {name_cmp, name_rcmp, quantity_cmp, quantity_rcmp};
  113.    
  114.     printf("Enter count of lists: ");
  115.     scanf("%d", &count);
  116.    
  117.     Product *products = product_list_alloc(count);
  118.    
  119.     product_list_imput(products, count);
  120.    
  121.     product_list_print(products, count);
  122.    
  123.     int ncmp = 3;
  124.    
  125.     quicksort(products, count, sizeof(*products), cmps[ncmp]);
  126.    
  127.     product_list_print(products, count);
  128.    
  129.     product_list_free(products);
  130.    
  131.     return 0;
  132. }

Объяснение кода листинга программы

В данном коде реализована сортировка списка продуктов по всем полям в любых направлениях.

  1. Список функций:
    • product_list_alloc() - выделяет память под список продуктов
    • product_list_free() - освобождает память под списком продуктов
    • product_list_imput() - считывает данные о продуктах в список
    • product_list_print() - выводит данные о продуктах из списка
    • swap() - меняет местами два указателя на память
    • sort() - сортирует список по заданному полю с использованием алгоритма быстрой сортировки
    • quicksort() - сортирует список по заданному полю с использованием алгоритма быстрой сортировки
    • name_cmp() - сравнивает продукты по полю название в порядке возрастания
    • name_rcmp() - сравнивает продукты по полю название в порядке убывания
    • quantity_cmp() - сравнивает продукты по полю количество в порядке возрастания
    • quantity_rcmp() - сравнивает продукты по полю количество в порядке убывания
  2. Описание основной функции:
    • main() - считывает количество списков продуктов, считывает данные о продуктах, сортирует список по выбранному полю и выводит отсортированный список на экран.
  3. Описание переменных:
    • count - количество списков продуктов
    • products - список продуктов
    • ncmp - номер поля для сортировки
    • cmps - указатели на функции сравнения продуктов по полям
  4. Объяснение работы кода:
    • С помощью функции product_list_alloc() выделяется память под список продуктов.
    • В цикле с помощью функции product_list_imput() считываются данные о продуктах в список.
    • С помощью функции product_list_print() выводятся данные о продуктах из списка.
    • Выбирается поле для сортировки с помощью переменной ncmp.
    • С помощью функции quicksort() сортируется список продуктов по выбранному полю.
    • С помощью функции product_list_print() выводится отсортированный список на экран.
    • С помощью функции product_list_free() освобождается память под списком продуктов. Таким образом, данный код реализует сортировку списка продуктов по всем полям в любых направлениях.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

13   голосов , оценка 3.923 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы