c - 如何在通过 hcreate/hsearch 按值(而不是按引用)实现的 C 中存储关联数组的键?

标签 c posix associative-array

使用通过 POSIX hcreate/hsearch 函数实现的关联数组(如 here 所述,我遇到了一些意想不到的行为,发现了我从未输入过的键,或者相反. 我追踪到一些按引用存储而不是按值存储的实例。 这让我感到惊讶,因为在示例中使用字符串文字作为键:

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. */

这是一个显示我的问题的 MWE:

#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);
 }

编译并执行上面的 C 代码会产生以下输出:

a is here.
b is not.
But if we adjust a to match b, we find both.

我将需要读取一个文件并存储大量的字符串:整数对,然后我将需要读取第二个文件来检查更大数量的字符串以获取先前存储的值。

如果通过引用比较键,我不明白这怎么可能。

如何更改我的关联数组实现以按值存储键?

如果这不可能,我该如何解决上述用例中的问题?


编辑:

这个问题只涉及输入但未找到的键。 相反的问题也出现了,在 this question 中有详细描述。

最佳答案

编辑:

事实证明,store() 需要strdup() key 来解决这个问题和another problem .


我发现通过使用相同的变量进行存储和查找,我实际上可以检索数组中的所有值:

void main(){
 char a[4]="foo";
  char b[4]="bar";
  char c[4]="baz";
  char t[4]="";
  intptr_t x=NULL;

  if(!hcreate(50)) exit_with_error("no hash");

  strcpy(t,a); store(t, 1); /* a -->  1 */
  strcpy(t,b); store(t,-1); /* b --> -1 */
  strcpy(t,c); store(t, 0); /* c -->  0 */

  if(!fetch(a,&x)) puts("a is not here.");
  if(!fetch(b,&x)) puts("Neither is b.");
  if( fetch(c,&x)) puts("c is in (and equal to t).");

  strcpy(t,a); if(fetch(t,&x)&&x== 1) puts("t can retrieve a.");
  strcpy(t,b); if(fetch(t,&x)&&x==-1) puts("It also finds b.");
  strcpy(t,c); if(fetch(t,&x)&&x== 0) puts("And as expected c.");

  exit(EXIT_SUCCESS);
}

这会产生以下输出:

a is not here.
Neither is b.
c is in (and equal to t).
t can retrieve a.
It also finds b.
And as expected c.

但是,我还是不明白为什么会这样。

不知何故, key 似乎需要位于相同的位置(引用)并且包含相同的内容(值)才能被找到。

关于c - 如何在通过 hcreate/hsearch 按值(而不是按引用)实现的 C 中存储关联数组的键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34749026/

相关文章:

c - fscanf 导致段错误

java - 如何将n个数字相加,相乘到数组中的给定范围,并以O(n)时间反转数组中的范围?

php - mysql_fetch_assoc() 报错

C posix套接字,无法将数据从客户端发送到服务器

c - 有没有办法到管道的最后位置而不是读取直到什么都没有?

c - 在关联数组中查找此数据的最佳算法?

php - 从关联数组中回显特定数据?

c - Not null terminated string - 没有可理解原因的 KlocWork 错误

为 MinGW 编译 glew32s.lib?

c - POSIX pthread 编程