Using associative arrays implented via the POSIX hcreate
/hsearch
functions (as described here, I struggled some unexpected behaviour finding keys I've never entered or the other way around.
I tracked it down to some instance of store-by-reference-instead-of-value.
This was surprising to me, since in the example uses string literals as keys:
store("red", 0xff0000);
store("orange", 0x123456); /* Insert wrong value! */
store("green", 0x008000);
store("blue", 0x0000ff);
store("white", 0xffffff);
store("black", 0x000000);
store("orange", 0xffa500); /* Replace with correct value. */
Here is an MWE that shows my problem:
#include <inttypes.h> /* intptr_t */
#include <search.h> /* hcreate(), hsearch() */
#include <stdio.h> /* perror() */
#include <stdlib.h> /* exit() */
#include <string.h> /* strcpy() */
void exit_with_error(const char* error_message){
perror(error_message);
exit(EXIT_FAILURE);
}
int fetch(const char* key, intptr_t* value){
ENTRY e,*p;
e.key=(char*)key;
p=hsearch(e, FIND);
if(!p) return 0;
*value=(intptr_t)p->data;
return 1;
}
void store(const char *key, intptr_t value){
ENTRY e,*p;
e.key=(char*)key;
p = hsearch(e, ENTER);
if(!p) exit_with_error("hash full");
p->data = (void *)value;
}
void main(){
char a[4]="foo";
char b[4]="bar";
char c[4]="";
intptr_t x=NULL;
if(!hcreate(50)) exit_with_error("no hash");
store(a,1); /* a --> 1 */
strcpy(c,a); /* remember a */
strcpy(a,b); /* set a to b */
store(a,-1); /* b --> -1 */
strcpy(a,c); /* reset a */
if(fetch(a,&x)&&x==1) puts("a is here.");
if(!fetch(b,&x)) puts("b is not.");
strcpy(a,b); printf("But if we adjust a to match b");
if(fetch(a,&x)&&x==-1&&fetch(b,&x)&&x==-1) puts(", we find both.");
exit(EXIT_SUCCESS);
}
Compiling and executing above C
code results in the following output:
a is here.
b is not.
But if we adjust a to match b, we find both.
I will need to read a file and store a a large number of string:int pairs and then I will need to read a second file to check an even larger number of strings for previously stored values.
I don't see how this would be possible if keys are compared by reference.
How can I change my associative array implementation to store keys by value?
And if that's not possible, how can I work around that problem given the above use case?
edit:
This question just deals with keys entered but not found. The opposite problem also appears and is described in detail in this question.