C hsearch发现之前未输入的值

时间:2016-01-12 20:13:27

标签: c posix associative-array

这是this question的后续问题。

由于我solved的一部分,我觉得剩下的问题与第一部分无关,我决定将这两部分分成两个问题。

我已根据建议here使用POSIX hcreate / hsearch实现了关联数组。

为了完整起见,以下是除上一个问题的main()函数之外的所有代码:

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

这是一个稍微扩展的main()函数:

int main(){
  char a[4]="foo";
  char b[4]="bar";
  char c[4]="baz";
  char t[4]="";
  char y='\0';
  const char l[6]={'a','b','f','o','r','z'};
  intptr_t x=NULL;
  size_t i=0,j=0;

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

  strcpy(t,b);
  store(t,0);
  if(fetch(t,&x)) printf("stored %s-->%d\n",t,(int)x);
  else printf("%s not stored\n",t);

  for(i=0;i<3;++i){
    y=t[i];
    for(j=0;j<6;++j){
      if(l[j]==y) continue;
      t[i]=l[j];
      if(fetch(t,&x)) store(t,-1);
      else store(t,1);
      if(fetch(t,&x)) printf("stored %s-->%d\n",t,(int)x);
      else printf("%s not stored\n",t);
    }   
    t[i]=y;
  }

  strcpy(t,a); if(fetch(t,&x)) printf("read %s-->%d\n",t,(int)x); else printf("%s not found\n",t);
  strcpy(t,b); if(fetch(t,&x)) printf("read %s-->%d\n",t,(int)x); else printf("%s not found\n",t);
  strcpy(t,c); if(fetch(t,&x)) printf("read %s-->%d\n",t,(int)x); else printf("%s not found\n",t);

  exit(EXIT_SUCCESS);
}

如您所见,我接受字符串bar并将其与0相关联。 然后,我会将bar中只有一个字母的所有单词与1中的-1相关联,如果之前未添加,则为foo,否则为bar。 最后,我查找了bazstored bar-->0 stored aar-->1 stored far-->1 stored oar-->1 stored rar-->1 stored zar-->1 stored bbr-->-1 stored bfr-->1 stored bor-->1 stored brr-->1 stored bzr-->1 stored baa-->1 stored bab-->1 stored baf-->1 stored bao-->1 stored baz-->1 foo not found read bar-->0 read baz-->1 &amp; foo导致预期值:

bar

现在我稍微修改替换bazCCCTTCTTATCG&amp; CCCTTCATTGCG int main(){ char a[13]="CCCTTCTTATCG" /*|||||| | ||*/ char b[13]="CCCTTCATTGCG"; char t[13]=""; char y='\0'; const char l[4]={'A','C','G','T'}; intptr_t x=NULL; size_t i=0,j=0; if(!hcreate(150)) exit_with_error("no hash"); strcpy(t,a); store(t,0); if(fetch(t,&x)) printf("stored %s-->%d\n",t,(int)x); else printf("%s not stored\n",t); for(i=0;i<12;++i){ y=t[i]; for(j=0;j<4;++j){ if(l[j]==y) continue; t[i]=l[j]; if(fetch(t,&x)) store(t,-1); else store(t,1); if(fetch(t,&x)) printf("stored %s-->%d\n",t,(int)x); else printf("%s not stored\n",t); } t[i]=y; } strcpy(t,a); if(fetch(t,&x)) printf("read %s-->%d\n",t,(int)x); else printf("%s not found\n",t); strcpy(t,b); if(fetch(t,&x)) printf("read %s-->%d\n",t,(int)x); else printf("%s not found\n",t); exit(EXIT_SUCCESS); } diff 29,32c29,32 < char a[4]="foo"; < char b[4]="bar"; < char c[4]="baz"; < char t[4]=""; --- > char a[13]="CCCTTCTTATCG"; > /*|||||| | ||*/ > char b[13]="CCCTTCATTGCG"; > char t[13]=""; 34c34 < const char l[6]={'a','b','f','o','r','z'}; --- > const char l[4]={'A','C','G','T'}; 38c38 < if(!hcreate(50)) exit_with_error("no hash"); --- > if(!hcreate(150)) exit_with_error("no hash"); 40c40 < strcpy(t,b); --- > strcpy(t,a); 45c45 < for(i=0;i<3;++i){ --- > for(i=0;i<12;++i){ 47c47 < for(j=0;j<6;++j){ --- > for(j=0;j<4;++j){ 60d59 < strcpy(t,c); if(fetch(t,&x)) printf("read %s-->%d\n",t,(int)x); else printf("%s not found\n",t);

CCCTTCATTGCG

为清楚起见,这里是相应的CCCTTCTTATCG

foo

正如您所看到的,barstored CCCTTCTTATCG-->0 stored ACCTTCTTATCG-->1 stored GCCTTCTTATCG-->1 stored TCCTTCTTATCG-->1 stored CACTTCTTATCG-->1 stored CGCTTCTTATCG-->1 stored CTCTTCTTATCG-->1 stored CCATTCTTATCG-->1 stored CCGTTCTTATCG-->1 stored CCTTTCTTATCG-->1 stored CCCATCTTATCG-->1 stored CCCCTCTTATCG-->1 stored CCCGTCTTATCG-->1 stored CCCTACTTATCG-->1 stored CCCTCCTTATCG-->1 stored CCCTGCTTATCG-->1 stored CCCTTATTATCG-->1 stored CCCTTGTTATCG-->1 stored CCCTTTTTATCG-->1 stored CCCTTCATATCG-->1 stored CCCTTCCTATCG-->1 stored CCCTTCGTATCG-->1 stored CCCTTCTAATCG-->1 stored CCCTTCTCATCG-->1 stored CCCTTCTGATCG-->1 stored CCCTTCTTCTCG-->-1 stored CCCTTCTTGTCG-->-1 stored CCCTTCTTTTCG-->-1 stored CCCTTCTTAACG-->-1 stored CCCTTCTTACCG-->-1 stored CCCTTCTTAGCG-->-1 stored CCCTTCTTATAG-->-1 stored CCCTTCTTATGG-->-1 stored CCCTTCTTATTG-->-1 stored CCCTTCTTATCA-->-1 stored CCCTTCTTATCC-->-1 stored CCCTTCTTATCT-->-1 read CCCTTCTTATCG-->-1 read CCCTTCATTGCG-->1 的3次修改(如CCCTTCTTATCG中的-1),因此不应在哈希表中找到。

但是,这是相应的输出:

-1

如您所见,bbrhsearch相关联,即使它从未存储过。

对于在存储上分配1的所有字符串也是如此,因为它们在即将插入时已经在哈希中。

在上面较小的示例中,gpcl6win64-9.18.exe -sDEVICE=pdfwrite -sOutputFile=%1.pdf -dNOPAUSE %1.txt 也是如此。

为什么table = df[fields] width = pandas.util.terminal.get_terminal_size() # find the width of the user's terminal window pandas.set_option('display.width', width[0]) # set that as the max width in Pandas print(table) 会为这些密钥返回error /IndentationError/ ,即使它们从未插入过来?

1 个答案:

答案 0 :(得分:5)

手册页指示key应该是分配有malloc的字符串。以下是手册页中的几个相关引用

  

hdestroy()函数为每个比较键调用free(3)   搜索表,但不是与密钥关联的数据项。

  

必须分配比较密钥(作为item.key传递给hsearch())   如果action是ENTER并且调用了hdestroy(),则使用malloc(3)。

因此,使用action hsearch调用ENTER会在散列中存储指针,并且该指针应指向稍后可以释放的字符串。在您的代码中,您有一个单独的字符串缓冲区,每次向哈希表添加一个条目时,都会传递相同的指针(指向您的字符串缓冲区)。这会弄乱哈希表。

解决问题很简单。在store函数中,在将条目添加到表之前,使用key制作strdup的副本。换句话说,替换

e.key=(char*)key;

e.key=strdup(key);