Сортировка списка по всем полям в любых направлениях. Использовать указатели на функции - C (СИ)
Формулировка задачи:
В общем, я запутался.
Вот задание.
Необходимо разработать программу согласно варианту
задания. При реализации использовать указатели на
функции и (или) массивы указателей на функции.
--------------------------------------------------
Дан список записей типа ТОВАР
(размер списка и его элементы вводятся пользователем).
Упорядочить список по любому из полей в любом направлении.
Поле и направление выбирает пользователь. В функцию сортировки
должен передаваться указатель на функцию сравнения двух элементов. (20 баллов).
ТОВАР:
- наименование товара (строка 15 символов);
- единицы измерения (строка 5 символов);
- цена (вещественное число с двумя знаками после запятой);
- количество (целое положительное число).
То, что накалякано
На эти строки на намекать. Исправил
Сейчас попробую со строками также провернуть
Листинг программы
- #include <stdio.h>
- #include <stddef.h>
- #include <stdlib.h>
- #include <string.h>
- #include <conio.h>
- typedef struct
- {
- char name[16];
- char mesr[6];
- double price;
- int count;
- }Good;
- typedef Good *Ptr;
- typedef int (*Pfun)( void *, void * );
- int cmpNM ( void *, void * );
- int cmpCNT( void *, void * );
- void sortbychoice( Ptr , int, size_t, void (*), Pfun );
- void swap ( Ptr , Ptr );
- int main( int argc, char *argv[ ] )
- {
- //printf( "%d", offsetof( Good, count) );
- int d = 0, count;
- printf( "Enter count of lists: ");
- while( !d || count <= 0)
- {
- d = scanf( "%d", &count );
- if( !d || count <= 0 ) { while( getchar( ) != '\n' ); printf( "Repeat: "); }
- }
- fflush( stdin );
- int i;
- Ptr list = (Good*)calloc( count, sizeof(Good));
- 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' );}
- //
- //sortbychoice( list, count, sizeof(char)*15, list[i].name, cmpNM );
- sortbychoice( list, count, offsetof( Good, count ), &list[i].count, cmpCNT);
- 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 );
- system( "pause" );
- getch( );
- return 0;
- }
- void swap ( Ptr arg1, Ptr arg2 )
- {
- Good temp = *arg1;
- *arg1 = *arg2;
- *arg2 = temp;
- return;
- }
- int cmpNM( void * arg1, void * arg2 )
- {
- if( strcmp( (char*)arg1, (char*)arg2 ) == 1 ) return 1;
- else return 0;
- }
- int cmpCNT( void * arg1, void *arg2 )
- {
- if(*((int*)arg1) > *((int*)arg2)) return 1;
- else return 0;
- }
- void sortbychoice ( Ptr good, int count, size_t size, void *arr, Pfun fun )
- {
- Ptr mass = good;
- int i, j, im;
- char * ar = ( char* )arr;
- for( i = 0; i < count - 1; i++ ){
- im = i;
- for( j = i + 1; j < count; j++ ) if( fun( (void*)( ar + im*size), (void*)( ar + j * size )) ) im = j;
- swap( &mass[i], &mass[im] );
- }
- return;
- }
дело в том, что я не могу понять, как мне обращаться к началу памяти одного и того же поля в массиве структур. Делал такое с обычными массивами, вроде всё работало. Вот как делал:
Листинг программы
- void SortArray( void *array, unsigned num, size_t size, int (*fun)(void *arg1, void *arg2), void (*fun1)( void *arg1, void *arg2))
- {
- int i, j;
- int imin, imax;
- char *ptr = (char* )array; // указатель на начало памяти массива
- for( i = 0; i < num - 1; i += 2 )
- {
- imin = i;
- for( j = i + 2; j < num; j += 2 )
- if( fun( (void*)(ptr + imin*size), (void*)(ptr + j*size)) > 0 ) imin = j;
- fun1( ptr + i*size, ptr + imin*size);// смещение указателя на size бацтов массив
- }
- for( i = 1; i < num - 1; i += 2 )
- {
- imax = i;
- for( j = i + 2; j < num; j += 2 )
- if( fun( (void*)(ptr + imax*size), (void*)(ptr + j*size)) < 0 ) imax = j;
- fun1( ptr + i*size, ptr + imax*size );// смещение указателя на size бацтов массив
- }
- }
//sortbychoice( list, count, sizeof(char)*15, list[i].name, cmpNM );
* * sortbychoice( list, count, offsetof( Good, count ), &list[i].count, cmpCNT);
В общем, для сортровки по кол - ву работает вроде.
Листинг программы
- void sortbychoice ( Ptr good, int count, void *arr, Pfun fun )
- {
- Ptr mass = good;
- int i, j, im;
- char * ar = ( char * )arr; // указатель на начало памяти выбранного поля аргумента arg
- for( i = 0; i < count - 1; i++ ){
- im = i;
- for( j = i + 1; j < count; j++ ) if( fun( (void*)( ar + im*sizeof( Good)), (void*)( ar + j * sizeof(Good) )) ) im = j;
- swap( &mass[i], &mass[im] );
- }
- return;
- }
В общем, пока работает. Если найдёте грабли ещё, укажите, пожалуйста.
Листинг программы
- #include <stdio.h>
- #include <stddef.h>
- #include <stdlib.h>
- #include <string.h>
- #include <conio.h>
- typedef struct
- {
- char name[16];
- char mesr[6];
- double price;
- int count;
- }Good;
- typedef Good *Ptr;
- typedef int (*Pfun)( void *, void * );
- int cmpNM ( void *, void * );
- int cmpCNT( void *, void * );
- void sortbychoice( Ptr , int, void (*), Pfun ); // для 1 - ого аргумента необходимо передать 2 - ой указатель
- void swap ( Ptr , Ptr );
- int main( int argc, char *argv[ ] )
- {
- //printf( "%d", offsetof( Good, count) );
- int d = 0, count;
- printf( "Enter count of lists: ");
- while( !d || count <= 0)
- {
- d = scanf( "%d", &count );
- if( !d || count <= 0 ) { while( getchar( ) != '\n' ); printf( "Repeat: "); }
- }
- fflush( stdin );
- int i;
- Ptr list = (Good*)calloc( count, sizeof(Good));
- 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' );}
- //
- sortbychoice( list, count,list[0].name, cmpNM );
- //sortbychoice( list, count, &list[0].count, cmpCNT);
- 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 );
- system( "pause" );
- getch( );
- return 0;
- }
- void swap ( Ptr arg1, Ptr arg2 )
- {
- Good temp = *arg1;
- *arg1 = *arg2;
- *arg2 = temp;
- return;
- }
- int cmpNM( void * arg1, void * arg2 )
- {
- if( strcmp( (char*)arg1, (char*)arg2 ) == 1 ) return 1;
- else return 0;
- }
- int cmpCNT( void * arg1, void *arg2 )
- {
- if(*((int*)arg1) > *((int*)arg2)) return 1;
- else return 0;
- }
- void sortbychoice ( Ptr good, int count, void *arr, Pfun fun )
- {
- Ptr mass = good;
- int i, j, im;
- char * ar = ( char * )arr;
- for( i = 0; i < count - 1; i++ ){
- im = i;
- for( j = i + 1; j < count; j++ ) if( fun( (void*)( ar + im*sizeof( Good)), (void*)( ar + j * sizeof(Good) )) ) im = j;
- swap( &mass[i], &mass[im] );
- }
- return;
- }
Решение задачи: «Сортировка списка по всем полям в любых направлениях. Использовать указатели на функции»
textual
Листинг программы
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define MAXNAME 16
- #define MAXUNIT 6
- typedef int (*Pf)(void*, void*);
- typedef struct {
- char name[MAXNAME];
- char unit[MAXUNIT];
- double price;
- int quantity;
- } Product;
- Product *product_list_alloc(int count)
- {
- Product * list = malloc(count * sizeof(*list));
- return list;
- }
- void product_list_free(Product *list)
- {
- free(list);
- }
- void product_list_imput(Product *list, int count)
- {
- for (size_t i=0; i<count; i++)
- {
- printf("Name|Measure|Price|Count: ");
- scanf("%s %s %lf %d", list[i].name, list[i].unit,
- &list[i].price, &list[i].quantity);
- }
- }
- void product_list_print(Product *list, int count)
- {
- for (size_t i=0; i<count; i++)
- {
- printf( "Name: %s | Measure: %s | Price: %3.2lf | Count: %3d\n",
- list[i].name, list[i].unit, list[i].price, list[i].quantity );
- }
- }
- static void swap(void *x, void *y, size_t l) {
- char *a = x, *b = y, c;
- while(l--) {
- c = *a;
- *a++ = *b;
- *b++ = c;
- }
- }
- static void sort(char *array, size_t size, int (*cmp)(void*,void*), int begin, int end) {
- if (end > begin) {
- void *pivot = array + begin;
- int l = begin + size;
- int r = end;
- while(l < r) {
- if (cmp(array+l,pivot) <= 0) {
- l += size;
- } else if ( cmp(array+r, pivot) > 0 ) {
- r -= size;
- } else if ( l < r ) {
- swap(array+l, array+r, size);
- }
- }
- l -= size;
- swap(array+begin, array+l, size);
- sort(array, size, cmp, begin, l);
- sort(array, size, cmp, r, end);
- }
- }
- void quicksort (void *array, size_t nitems, size_t size, int (*cmp)(void*,void*)) {
- sort(array, size, cmp, 0, nitems*size);
- }
- int name_cmp(void *a, void *b)
- {
- Product *p1 = a;
- Product *p2 = b;
- return strcmp(p1->name, p2->name);
- }
- int name_rcmp(void *a, void *b)
- {
- Product *p1 = a;
- Product *p2 = b;
- return strcmp(p2->name, p1->name);
- }
- int quantity_cmp(void *a, void *b)
- {
- Product *p1 = a;
- Product *p2 = b;
- return (p1->quantity - p2->quantity);
- }
- int quantity_rcmp(void *a, void *b)
- {
- Product *p1 = a;
- Product *p2 = b;
- return (p2->quantity - p1->quantity);
- }
- int main(void)
- {
- int count;
- Pf cmps[4] = {name_cmp, name_rcmp, quantity_cmp, quantity_rcmp};
- printf("Enter count of lists: ");
- scanf("%d", &count);
- Product *products = product_list_alloc(count);
- product_list_imput(products, count);
- product_list_print(products, count);
- int ncmp = 3;
- quicksort(products, count, sizeof(*products), cmps[ncmp]);
- product_list_print(products, count);
- product_list_free(products);
- return 0;
- }
Объяснение кода листинга программы
В данном коде реализована сортировка списка продуктов по всем полям в любых направлениях.
- Список функций:
product_list_alloc()
- выделяет память под список продуктовproduct_list_free()
- освобождает память под списком продуктовproduct_list_imput()
- считывает данные о продуктах в списокproduct_list_print()
- выводит данные о продуктах из спискаswap()
- меняет местами два указателя на памятьsort()
- сортирует список по заданному полю с использованием алгоритма быстрой сортировкиquicksort()
- сортирует список по заданному полю с использованием алгоритма быстрой сортировкиname_cmp()
- сравнивает продукты по полюназвание
в порядке возрастанияname_rcmp()
- сравнивает продукты по полюназвание
в порядке убыванияquantity_cmp()
- сравнивает продукты по полюколичество
в порядке возрастанияquantity_rcmp()
- сравнивает продукты по полюколичество
в порядке убывания
- Описание основной функции:
main()
- считывает количество списков продуктов, считывает данные о продуктах, сортирует список по выбранному полю и выводит отсортированный список на экран.
- Описание переменных:
count
- количество списков продуктовproducts
- список продуктовncmp
- номер поля для сортировкиcmps
- указатели на функции сравнения продуктов по полям
- Объяснение работы кода:
- С помощью функции
product_list_alloc()
выделяется память под список продуктов. - В цикле с помощью функции
product_list_imput()
считываются данные о продуктах в список. - С помощью функции
product_list_print()
выводятся данные о продуктах из списка. - Выбирается поле для сортировки с помощью переменной
ncmp
. - С помощью функции
quicksort()
сортируется список продуктов по выбранному полю. - С помощью функции
product_list_print()
выводится отсортированный список на экран. - С помощью функции
product_list_free()
освобождается память под списком продуктов. Таким образом, данный код реализует сортировку списка продуктов по всем полям в любых направлениях.
- С помощью функции
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д