Вот проверенное исправление (я сделал это, поэтому у вас есть обзор хорошего, я думаю, хорошего кода, а не для облегчения домашней работы: вы должны понимать это, а не копировать / вставлять его).
Для вашей проблемы наиболее важна функция sort ().
#include <stdio.h>
/** Types *************************************************************/
//You should introduce constants, to allow quick changes
#define BOOK_NAME_LEN 30
#define NAME_LEN 30
#define PRICE_NUMBERS 4
#define LIBRARY_CAPACITY 100
//Allows to calculate ID numbers from library capacity (they're linked)
#define STRINGIZE(a) #a
#define STRINGIZE_CONSTANT(a) STRINGIZE(a)
#define ID_NUMBERS (sizeof(STRINGIZE_CONSTANT(\
LIBRARY_CAPACITY))/sizeof(char)-1)
typedef struct book Book;
struct book
{
//id is unsigned
size_t id;
char name[BOOK_NAME_LEN+1];
char author[NAME_LEN+1];
float price;
};
typedef struct library Library;
struct library {
Book books[LIBRARY_CAPACITY];
size_t inventory; //Book count
size_t id_cnt; //ID counter, never decremented
};
/** Input *************************************************************/
#include <string.h>
#include <stdlib.h>
//Purge stdin after removing ending \n
void clean(const char *buffer, FILE *fp)
{
char *p = strchr(buffer,'\n');
if (p != NULL) {
*p = 0;
}
else {
int c;
while ((c = fgetc(fp)) != '\n' && c != EOF);
}
}
//Gets a string from input without ending \n and
//with stdin purge
void get_str(char *str, size_t len) {
fgets(str, len+1, stdin);
clean(str, stdin);
}
//Explicit
int get_int_num(size_t n_digits) {
int ret = 0;
//Converts an entered string to integer
char *num = malloc((n_digits+1)*sizeof(char));
if(num !=NULL) {
get_str(num, n_digits);
ret = atoi(num);
free(num), num = NULL;
}
return ret;
}
//Explicit
float get_float_num(size_t n_digits) {
float ret = 0.f;
//The comma is a char
char *num = malloc((n_digits+2)*sizeof(char));
if(num !=NULL) {
get_str(num, n_digits+1);
ret = atof(num);
free(num), num = NULL;
}
return ret;
}
#include <math.h>
//Gets an integer choice in a range, useful for menus
int get_choice(int min, int max) {
int ret = 0;
do {
//The number of digits is deduced from
//max's one.
ret = get_int_num(log10(max)+1);
}while(ret < min || ret > max);
return ret;
}
/** Library functions **************************************************/
//Printing
void print_library(Library const * const library) {
for(size_t i = 0 ; i < library->inventory ; ++i) {
printf("%u) %s BY %s : %.2f USD\n", i+1, library->books[i].name,
library->books[i].author,
library->books[i].price);
}
}
/* Adding */
void add(Library * const library) {
//Fills infos
printf("Name ? ");
get_str(library->books[library->inventory].name, BOOK_NAME_LEN);
printf("Author ? ");
get_str(library->books[library->inventory].author, NAME_LEN);
printf("Price (%u significative numbers) ? ", PRICE_NUMBERS);
library->books[library->inventory].price = get_float_num(PRICE_NUMBERS);
//Unique id from internal library counter
library->books[library->inventory].id = ++library->id_cnt;
//And finally increments books count
library->inventory++;
}
/* End adding */
/* Deleting */
#include <stdbool.h>
//You will be able to remove by anything providing that you
//search the corresponding ID (then, same menu as for sorting)
bool remove_by_id(Library * const library, size_t id) {
bool ret = false;
for(size_t i = 0 ; i < library->inventory ; ++i) {
if(library->books[i].id == id) {
for(size_t j = i ; j < library->inventory-1 ; ++j) {
library->books[j] = library->books[j+1];
}
library->inventory--;
ret = true;
}
}
return ret;
}
void del(Library * const library) {
printf("ID ? ");
size_t id = get_int_num(ID_NUMBERS);
printf("Book %u %s.", id, remove_by_id(library, id) ?
"successfully deleted" :
"NOT deleted (probably wrong id)");
}
/* End deleting */
/* Sorting */
int cmp_by_price(void const *b1, void const *b2) {
return ((Book*)b1)->price >= ((Book*)b2)->price;
}
int cmp_by_author(void const *b1, void const *b2) {
return strcmp(((Book*)b1)->author, ((Book*)b2)->author);
}
int cmp_by_name(void const *b1, void const*b2) {
return strcmp(((Book*)b1)->name, ((Book*)b2)->name);
}
void sort(Library * const library) {
printf("Sort by :\n");
printf("1) Book name\n");
printf("2) Author name\n");
printf("3) Price\n");
printf("Your choice : ");
//Function pointer to use appropriate comparison function
int (*compare)(void const *, void const*) = NULL;
int choice = get_choice(1, 3);
switch(choice) {
case 3:
compare = cmp_by_price;
break;
case 2:
compare = cmp_by_author;
break;
case 1:
compare = cmp_by_name;
break;
default:
break;
}
qsort(library->books, library->inventory, sizeof(Book), compare);
printf("Sorted :\n");
print_library(library);
}
/* End sorting */
/** Main program ******************************************************/
#include <ctype.h>
bool stop() {
char c[1] = "";
printf("\nContinue (\'y\' for yes) ? ");
get_str(c, 1);
return tolower(c[0]) != 'y';
}
int main(void) {
//NEVER use global variables... Prefer to pass them through arguments
//(of course with pointers otherwise they won't be modified)
Library library = {{{0}}, 0, 0};
do {
printf("Actions available : \n");
printf("1) Add book\n");
printf("2) Delete book\n");
printf("3) Sort books\n");
printf("Your choice : ");
int choice = get_choice(1, 3);
switch(choice) {
case 1:
add(&library);
break;
case 2:
del(&library);
break;
case 3:
sort(&library);
break;
default:
break;
}
}while(!stop());
return 0;
}
Прокомментируйте, если вы чего-то не понимаете, мы здесь, чтобы помочь вам выучить C в конце концов.