/******************************************************************************
Online C Compiler.
Code, Compile, Run and Debug C program online.
Write your code in this editor and press "Run" button to compile and execute it.
*******************************************************************************/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN3(a, b, c) ((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c)))
unsigned int DistanceLevenshtein(const char *s1, const char *s2)
{
unsigned int s1len, s2len, x, y, lastdiag, olddiag;
s1len = strlen(s1);
s2len = strlen(s2);
unsigned int *column = malloc((s1len + 1) * sizeof(int));
unsigned int distance;
for (y = 1; y <= s1len; y++)
column[y] = y;
for (x = 1; x <= s2len; x++) {
column[0] = x;
for (y = 1, lastdiag = x - 1; y <= s1len; y++) {
olddiag = column[y];
column[y] = MIN3(column[y] + 1, column[y - 1] + 1, lastdiag + (s1[y-1] == s2[x - 1] ? 0 : 1));
lastdiag = olddiag;
}
}
distance = column[s1len];
free(column);
return distance;
}
typedef struct Person_t
{
char Nom[32];
char Prenom[32];
char AdresseEmail[64];
char Ville[96];
char Pays[64];
} Person;
static int compare_field(const char *record, const char *query, float *percentage) {
int DLev;
if (strlen(query) == 0) {
return 0;
}
DLev = DistanceLevenshtein ( record, query );
*percentage = (1.0f - DLev/((float)(MAX (strlen(record) , strlen(query))))) * 100.0f;
return 1;
}
float PersonScore( Person *record, Person *query) {
float total_match_percentage = 0, temp_percentage;
int total_match_fields = 0;
#define COMPAREFIELD(field) if (compare_field(record->field, query->field, &temp_percentage)) ({ total_match_percentage += temp_percentage; total_match_fields++; })
COMPAREFIELD (Prenom);
COMPAREFIELD (Nom);
COMPAREFIELD (AdresseEmail);
COMPAREFIELD (Ville);
COMPAREFIELD (Pays);
#undef COMPAREFIELD
return total_match_percentage / (float)total_match_fields;
}
void printPerson( Person *person )
{
printf(
"Nom: %s\n"
"Prenom: %s\n"
"Email: %s\n"
"Ville: %s\n"
"Pays: %s\n",
person->Nom,
person->Prenom,
person->AdresseEmail,
person->Ville,
person->Pays
);
}
void printPersons( Person *persons, size_t len )
{
printf("----------------\n");
for (int i = 0; i < len; ++i)
{
printPerson(&persons[i]);
printf("\n");
}
printf("----------------\n");
}
int comparePersons( const void *person_a, const void *person_b, void *query )
{
Person *a = (Person *)person_a;
Person *b = (Person *)person_b;
Person *q = (Person *)query;
float a_score = PersonScore(a, q);
float b_score = PersonScore(b, q);
// printf("\ncomparePersons()\n");
// printPerson(a);
// printPerson(b);
// printPerson(q);
// printf("################\n\n");
if (a_score < b_score)
return -1;
else if (a_score > b_score)
return 1;
else
return 0;
}
const Person Paperino = {
"Donald",
"Duck",
"
[email protected]",
"Paperopoli",
"Calisota"
};
const Person Paperina = {
"Daisy",
"Duck",
"
[email protected]",
"Paperopoli",
"Calisota"
};
const Person Paperone = {
"Scrooge",
"McDuck",
"
[email protected]",
"Paperopoli",
"Calisota"
};
const Person Qui = {
"Huey",
"Duck",
"
[email protected]",
"Paperopoli",
"Calisota"
};
const Person Quo = {
"Dewey",
"Duck",
"
[email protected]",
"Paperopoli",
"Calisota"
};
const Person Qua = {
"Louie",
"Duck",
"
[email protected]",
"Paperopoli",
"Calisota"
};
Person Ducks[6];
int main()
{
memcpy(&Ducks[0], &Paperino, sizeof(Person));
memcpy(&Ducks[1], &Paperina, sizeof(Person));
memcpy(&Ducks[2], &Paperone, sizeof(Person));
memcpy(&Ducks[3], &Qui, sizeof(Person));
memcpy(&Ducks[4], &Quo, sizeof(Person));
memcpy(&Ducks[5], &Qua, sizeof(Person));
printf("Original\n");
printPersons(Ducks, 6);
Person query = {.Prenom = "Jamk", .Ville = "Pondon", .Pays = "United K"};
qsort_r(Ducks, sizeof(Ducks)/sizeof(Ducks[0]), sizeof(Person), comparePersons, &query);
printf("Sorted\n");
printPersons(Ducks, 6);
return 0;
}