Сортировка списка по всем полям в любых направлениях. Использовать указатели на функции - 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()
освобождается память под списком продуктов. Таким образом, данный код реализует сортировку списка продуктов по всем полям в любых направлениях.
- С помощью функции
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д