Здравствуйте, Юдин Евгений Сергеевич.
Программа приведена в приложении. Для простоты, массив записей для сортировки задан в исходном коде. Функция сортировки — та же самая, что и в ответе на
вопрос 178154.
Программа компилировалась и проверялась в режиме "чистого Си" в Borland C++ 3.1 и MSVC++ 6.0 (сохраните в файле с расширением .c). Если Ваш компилятор не понимает комментарии, начинающиеся с '//', то замените их на /* */; если не понимает квалификатор const, то просто уберите его.
Честно говоря, не представляю, что еще в программе можно комментировать. Если будут вопросы, то обращайтесь в мини-форум.
Успехов!
Приложение:
/*
Вопрос № 178149
Написать подпрограмму для универсальной сортировки произвольного массива
с произвольным базовым типом. Подпрограмме передается массив как
нетипизованный параметр, его длина, размер элемента и логическая функция
сравнения двух элементов массива.
С использованием этой подпрограммы решить следующую задачу.
Имеется информация о студентах группы:
Ф.И.О., результаты последней экзаменационной сессии.
Требуется получить список студентов с указанием среднего балла по итогам сессии,
упорядоченный по указанию пользователя либо лексикографически, либо
по невозрастанию среднего балла.
*/
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>
#ifndef _countof
#define _countof(array) (sizeof(array)/sizeof(array[0]))
#endif
typedef int (__cdecl *compare_func )( const void *elem1, const void *elem2 );
/*
функция сортировки выбором
Сортировка выбором - алгоритм сортировки, относящийся к неустойчивым
алгоритмам сортировки. На массиве из n элементов имеет время
выполнения в худшем, среднем и лучшем случае O(n^2), предполагая что
сравнения делаются за постоянное время.
Шаги алгоритма:
1. находим минимальное значение в текущем списке
2. производим обмен этого значения со значением на первой неотсортированной позиции
3. теперь сортируем хвост списка, исключив из рассмотрения уже отсортированные элементы
Параметры:
base - указатель на сортируемый массив;
n - число элементов в массиве
width - размер ("ширина") одного элемента в байтах
compare - указатель на функцию сравнения, которая должна возвращать:
- отрицательное значение, если первый элемент меньше второго;
- положительное - если первый больше второго;
- 0, если элементы равны.
*/
void sort( void* base, size_t n, size_t width, compare_func compare )
{
size_t i, j, iMin;
// внутри используем тип char*, поскольку sizeof(char)==1
char *pMin, *pi, *pj, tmp;
pi = (char*)base;
for( i = 0; i < n-1; ++i, pi += width ) {
pMin = pi;
iMin = i;
// находим минимальное значение в конце массива
for( pj = pi+width, j = i+1; j < n; ++j, pj += width ) {
if( compare( pj, pMin ) < 0 ) {
pMin = pj;
iMin = j;
}
}
// производим обмен минимального значения со значением на первой неотсортированной позиции
if( iMin != i ) {
for( j = 0; j < width; ++j ) {
tmp = pi[j];
pi[j] = pMin[j];
pMin[j] = tmp;
}
}
}
}
// применим функцию сортировки для массива записей об итогах сессии
typedef struct _t_student
{
char* name; // фамилия
int group; // номер группы
int mark[3]; // оценки
} t_student;
static t_student data[] = {
"Пупкин" , 101, { 3,4,5 },
"Иванов" , 101, { 4,4,4 },
"Петров" , 101, { 4,5,5 },
"Сидоров", 102, { 3,2,3 },
"Жуков", 102, { 4,5,4 }
};
#define N_STUDENTS _countof(data)
/* Функция сравнения по именам */
int __cdecl comp_names( const void* p1, const void* p2 )
{
return strcmp( ((t_student*)p1)->name, ((t_student*)p2)->name );
}
/* Функция сравнения по среднему баллу (== сумме баллов) */
int __cdecl comp_marks( const void* p1, const void* p2 )
{
int s1, s2, i;
s1 = s2 = 0;
for( i = 0; i < 3; ++i ) { // вычисляем сумму баллов
s1 += ((t_student*)p1)->mark[i];
s2 += ((t_student*)p2)->mark[i];
}
return s1 - s2;
}
/* Вывод массива на экран */
void print_arr( t_student* p, int n )
{
int i, j;
printf(
"--------------------------------\n"
"Фамилия Группа Баллы\n"
"--------------------------------\n" );
for( i = 0; i < n; ++i, ++p ) {
printf( "%-20s%4d ", p->name, p->group );
for( j = 0; j < 3; ++j )
printf( "%2d", p->mark[j] );
printf( "\n" );
}
printf( "--------------------------------\n" );
}
int main()
{
int ch;
printf( "Исходный массив:\n" );
print_arr( data, N_STUDENTS );
do {
printf(
"\nВыберите способ сортировки:\n"
"1. лексикографически\n"
"2. по среднему баллу\n"
"---------------------------\n"
"0. выход\n" );
switch( ch = getch() ) {
case '1':
sort( (void*)data, N_STUDENTS, sizeof(t_student), comp_names );
printf( "\nМассив, отсортированный по именам:\n" );
print_arr( data, N_STUDENTS );
break;
case '2':
sort( (void*)data, N_STUDENTS, sizeof(t_student), comp_marks );
printf( "\nМассив, отсортированный по среднему баллу:\n" );
print_arr( data, N_STUDENTS );
break;
}
} while( ch != '0' );
return 0;
}