Example:
Code:
/****************************************************************************
* *
* I doubt this is much help, but I thought I would write this for giggles. *
* *
****************************************************************************/
/* Don't worry too much about what this structure is for. Just consider it magic */
struct name_token_t
{
struct name_token_t *next, *prev;
unsigned refs;
char value[];
};
static name_token_t *tokpool = 0;
/*
* This is a tree that stores contact names. Why? Because a contact should be allowed more
* than one email, correct?
*/
struct name_t
{
struct name_t *left, *right;
const char *first, *last;
};
/*
* This is the heart of your initial question.
*/
struct contact_info_t
{
struct contact_info_t *left, *right;
struct name_t *name;
const char *email;
};
/*
*
const char *tokdup(const char *s)
{
struct name_token_t *next, *prev, *tmp;
size_t i;
for(prev = 0, next = tokpool; next; next = next->next)
{
i = stricmp(s, next->value);
if(!i)
{
++next->refs;
return next->value;
}
if(i < 0)
break;
prev = next;
}
/* Ok, if this point is reached, the token needs to be added */
tmp = malloc(sizeof(*tmp) + strlen(s) + 1);
if(tmp)
{
strcpy(tmp->value, s);
tmp->prev = prev;
tmp->next = next;
tmp->refs = 1;
if(!tokpool)
tokpool = tmp;
} else
{
fputs("*** Out of memory ***\n", stderr);
return 0;
}
if(prev)
prev->next = tmp;
if(next)
next->prev = tmp;
return tmp->value;
}
void tokfree(const char *tok)
{
struct name_token_t *p = (struct name_token *)tok - 1;
if(!tok)
return;
if(!--p->refs)
{
struct name_token *prev = p->prev, *next = p->next;
if(prev)
p->prev->next = next;
if(next)
p->next->prev = prev;
if(p == tokpool)
tokpool = next;
free(p);
}
}
void tokfree_all(void)
{
}
/* Ok all that string memory management stuff can go on the back burner, I just put that
* to conserve duplicate strings. Its just a memory saver is all :)
*/
struct name_t *make_name(const char *first, const char *last)
{
struct name_t *name = malloc(sizeof(*name));
if(name)
{
name->first = tokdup(first);
name->last = tokdup(last);
name->right = name->left = 0;
} else
fputs("*** Out of memory ***\n", stderr);
return name;
}
void remove_names(struct name_t *name)
{
if(name)
{
remove_names(name->left);
remove_names(nams->right);
tokfree(name->first);
tokfree(name->last);
free(name);
}
}
/* I am sorting by first name, but you can change it to be by last if you wish. */
struct name_t *update_names(struct name_t *root, const char *first, const char *last)
{
int cmp;
if(!root)
return make_name(first, last);
cmp = strcmp(root->value, first);
if(i == 0)
return root;
if(i < 0)
root->left = update_names(root->left, first, last);
if(i > 0)
root->right = update_names(root->right, first, last);
}
struct contact_info_t *make_contact_info(struct name_t *name, const char *email)
{
struct contact_info_t *info = malloc(sizeof(*info));
if(info)
{
info->name = name;
info->email = tokdup(email);
}
return name;
}
/* Sorting this by email address, of course ;) */
struct contact_info_t *update_contacts(constact_info_t *root, struct name_t *name, const char *email)
{
int cmp;
if(!root)
return make_contact_info(name, email);
cmp = strcmp(root->email, email);
if(i == 0)
return root;
if(i < 0)
root->left = update_contacts(root->left, name, email);
if(i > 0)
root->right = update_contacts(root->right, name, email);
}
void remove_contacts(struct contact_info_t *info)
{
if(info)
{
remove_contacts(info->left);
remove_contacts(info->right);
tokfree(info->email);
free(info);
}
}
/* This should be enough to get someone started, imo. Now you have the ability to scan for contacts via
* their name and email address.
*/
Perhaps from here you could write a simple "find" function.
Example:
Code:
struct name_t *find(struct contact_info_t *root, const char *email)
{
if(root)
{
int cmp = strcmp(root->email, email);
if(i < 0)
return find(root->right, email);
if(i > 0)
return find(root->left, email);
if(i == 0)
return root->name;
}
return 0;
}