Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为hashmap创建可变数量的链接列表_C_Loops_Linked List_Hashtable - Fatal编程技术网

C 为hashmap创建可变数量的链接列表

C 为hashmap创建可变数量的链接列表,c,loops,linked-list,hashtable,C,Loops,Linked List,Hashtable,以下是我的代码中重要的部分,其中一些无用的部分被注释掉了: #include <stdio.h> #include <ctype.h> #include <stdlib.h> #include <string.h> #include "hmap.h" struct val_word{ char *final_word; struct val_word* next; }; int main (int argc, char **argv){

以下是我的代码中重要的部分,其中一些无用的部分被注释掉了:

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

#include "hmap.h"

struct val_word{
char *final_word;
struct val_word* next;
};


int main (int argc, char **argv){

  //Check if dictionary file is given 

  FILE *fp1;
  char key [125];
  char val [125];
  char temp;
  struct val_word *storage;
  char c;
  int i;
  int j;
  int l;


  HMAP_PTR dictionary = hmap_create(0, 0.75);

  fp1 = fopen(argv[1], "r");

  do{
    c = fscanf(fp1, "%s", key);


    // Convert string to lowercase

    strcpy(val, key);

    //Alphabetically sort string


    struct val_word* word_node = malloc(sizeof(struct val_word));
    word_node->final_word = val;
    word_node->next = NULL;

    storage = hmap_get(dictionary, key);


    if(storage == NULL){
        hmap_set(dictionary, key, word_node);
    }
    else{
        struct val_word *temp2 = storage;

        while(temp2->next != NULL){
            temp2 = temp2->next;
        }

        word_node->final_word = val;
        word_node->next = NULL;

        temp2->next = word_node;

        hmap_set(dictionary, key, storage);

    }


  } while (c != EOF);

  fclose(fp1);

  while(storage->next != NULL){
    printf("The list is %s\n", storage->final_word);
    storage = storage->next;
  }


  return 0;

}
#包括
#包括
#包括
#包括
#包括“hmap.h”
结构val_词{
字符*最后一个单词;
结构val_word*下一步;
};
int main(int argc,字符**argv){
//检查是否提供了字典文件
文件*fp1;
字符键[125];
char-val[125];
焦炭温度;
结构val_word*存储;
字符c;
int i;
int j;
int l;
HMAP_PTR dictionary=HMAP_create(0,0.75);
fp1=fopen(argv[1],“r”);
做{
c=fscanf(fp1,“%s”,键);
//将字符串转换为小写
strcpy(val,key);
//按字母顺序排序字符串
struct val_word*word_node=malloc(sizeof(struct val_word));
word\u节点->final\u word=val;
word\u node->next=NULL;
存储=hmap_get(字典、键);
if(存储==NULL){
hmap_集(字典、关键字、单词_节点);
}
否则{
struct val_word*temp2=存储;
while(temp2->next!=NULL){
temp2=temp2->next;
}
word\u节点->final\u word=val;
word\u node->next=NULL;
temp2->next=word\u节点;
hmap_集(字典、密钥、存储);
}
}而(c!=EOF);
fclose(fp1);
while(存储->下一步!=NULL){
printf(“列表是%s\n”,存储->最终单词);
存储=存储->下一步;
}
返回0;
}
我得到了一个长度未知的字典文件,以及一个我无法触摸的哈希表实现文件。哈希表存储单词的混乱版本,键是按字母顺序排序的单词版本。例如:

字典的一部分包括:莱洛,你好,哦,霍勒

关键是:ehllo

val将是存储上述4个单词的链表

hmap_get获取给定键处的值,hmap_set设置给定键处的值

我的代码处理一切都很好,直到我尝试打印位于某个键处的列表。 列表大小正确,但只存储作为输入的最后一个值。因此,再加上上面的例子,我的列表将是(按时间顺序):

  • 莱洛
  • 哎哟->哎哟
  • 霍尔->霍尔->霍尔
  • ehllo->ehllo->ehllo->ehllo
  • 出于某种原因,它还将按正确字母顺序排列的字符串存储为最后一个字符串,我没有提供hmap_set函数。对此我很困惑

    然而,这个列表非常有意义。我只有一个节点,它在for循环中。我不更改变量名,因此指针都指向同一个节点,节点在循环的每次迭代中都会更改它包含的字符串

    所以,我想知道我将如何解决这个问题。 我不能动态地命名变量,我不能仅仅创建一个链表的动态数组,因为我觉得这样做会破坏哈希表的用途。 我不知道我会用什么样的数据类型来存储它

    非常感谢您的帮助,谢谢

    将注释转换为答案-代码更易于阅读


    问题是,我认为,您一直在将新值读入
    val
    (从
    key
    复制),但您只有一个变量

    在将字符串存储在哈希映射中之前,需要复制这些字符串。因此,使用
    strdup()
    而不是
    strcpy()
    查找函数并在
    key
    中复制字符串。将从
    strdup()
    返回的值分配给
    word\u节点->final\u word

    如果不允许您使用strdup(),请编写您自己的变体:

    char *dup_str(const char *str)
    {
        size_t len = strlen(str) + 1;
        char *dup = malloc(len);
        if (dup != 0)
            memmove(dup, str, len);
        return dup;
    }
    

    使用
    do…而像这样的循环是不好的。使用
    while(fscanf(fp1,“%s”,key)==1)
    作为
    while
    循环。代码在循环中运行,最后一行在到达EOF时重复。这不是一个好主意。我认为问题是,您不断地将新值读入
    val
    (从
    key
    复制),但您只有一个变量。在将字符串存储在哈希映射中之前,需要复制这些字符串。因此,查找
    strdup()
    函数,并使用
    strdup()
    而不是
    strcpy()
    键中复制字符串。将从
    strdup()
    返回的值分配给
    word\u节点->final\u word
    。如果您不允许使用strdup,请编写您自己的变体:
    char*dup\u str(const char*str){size\t len=strlen(str)+1;char*dup=malloc(len);If(dup!=0)memmove(dup,str,len);return dup;}
    @JonathanLeffler是的,我希望您能将其作为答案提交,以便我可以选择它,但非常感谢您!令人惊叹的。看到复制品和复制品之间的区别很有趣。我以为我用strcpy是万无一失的!非常感谢。也可以使用memcpy(),此处不需要memmove():字符串不能重叠。@joop:我使用
    memmove()
    ,因此我不必记住使用
    memcpy()
    什么时候可以,什么时候不可以。你说得对,但在我看来,简单是有益的。但对初学者来说,它让人困惑。非初学者应该知道记忆对象何时可以/不可以重叠。(还有一个(愚蠢的)性能论证)什么让初学者感到困惑?一个作业有两个功能?对这是可笑的。因此,我使用了一个不管怎样都有效的方法,这样初学者就不会弄错。虚假(或大部分虚假)的效率论证不值得使用——它让初学者感到困惑。因此,“使用
    memmove()
    ,因为它总是有效的”对于初学者来说比涵盖
    memcpy()
    所需的黄鼠狼措辞更简单。在AIAC中,
    memcpy()
    不存在,除了作为初学者的陷阱,就像
    gets()
    strtok()
    sprintf()
    和…不存在一样(sorta-
    gets()
    算作核心转储