Noooo! I just wrote a really long post and got logged out!
Luckily I was writing most of it in a text editor - phew!
...
Its been a few days now and I read up on malloc(). I realised that malloc doesnt actually care what you are allocating memory for so I changed the structure a little bit so that the text becomes a part of it.
Anyway, this is what I am working towards now:
int addword(const char* wordtext); /* main prototype */
struct uniqueword {
struct uniqueword* last;
struct uniqueord* next;
int count;
char wordtext[1]; /* copy of the text */
};
static struct uniqueword* firstword;
static struct uniqueword* createuniqueword(const char* wordtext)
{
/* create a new uniqueword structure */
int wordlength;
struct uniqueword* unique;
wordlength = strlen(wordtext);
unique = (struct uniqueword*)malloc(sizeof(struct uniqueword)+wordlength);
/* fill in data if malloc() ok */
if (unique != NULL) {
unique->last = 0;
unique->prev = 0;
unique->count = 1;
strcpy(unique->wordtext, wordtext);
}
return unique;
}
int addword(const char* wordtext)
{
/* returns 1 if the word was added or zero if it existed or -1 on failure */
struct uniqueword* newword;
struct uniqueword* last;
struct uniqueword* uw;
int worddiff;
if (!firstword) {
newword = createuniqueword(wordtext);
if (newword) {
firstword = newword;
return 1;
}
else {
return -1;
}
}
for (uw = firstword; uw != NULL; uw = uw->next) {
worddiff = stricmp(wordtext, uw->wordtext);
/* found it! */
if (worddiff == 0) {
uw->count++;
return 0;
}
/* as soon as word > uw->word we insert it immediately before uw */
if (worddiff > 0) {
newword = createuniqueword(wordtext);
if (newword != NULL) {
newword->prev = uw->prev;
newword->next = uw;
uw->prev = newword;
newword->prev->next = newword;
return 1;
} else {
return -1;
}
}
/* remember the last uniqueword */
last = uw;
}
/* we reached the end of the list without finding it */
newword = createuniqueword(wordtext);
if (newword) {
last->next = newword;
return 1;
}
return -1;
}
Im not really happy with the loop though. Im trying to keep the words sorted based on the greater than / less than return of stricmp() so that the entire list isnt always searched before deciding to add the word.
I think its quite ugly though (having to have a "last" pointer just because the normal loop finishes when uw is null) and probably broken too.
Would "(uw != NULL) && (uw->next != NULL)" in the loop be better? It looks like it would always skip the last one on the list regardless which would only mean having to check if that one matches the wordtext outside the loop which also seems a bit stupid.