【问题标题】:C - Allocating memory and copying string in to an array for hash tableC - 分配内存并将字符串复制到哈希表的数组中
【发布时间】:2016-12-28 19:36:23
【问题描述】:

我正在尝试创建一个哈希表结构,其中包含一个键(字符串)数组和每次键出现时的频率数组。我正在运行的代码如下所示:

#include <stdio.h>
#include <stdlib.h>
#include "mylib.h"
#include "htable.h"

int main(void){
    htable h = htable_new(18143);
    char word[256];
    while(getword(word, sizeof word, stdin) !=EOF){
        htable_insert(h, word);
    }

    htable_print(h);
    htable_free(h);


    return EXIT_SUCCESS;
}

它创建一个新的哈希表,读入并存储单词,然后打印。例如,如果输入是“一”“二”“三”,则输出将如下所示:

1    one
1    two
1    three

左列是频率,右列是关键。下面是实际的哈希表代码。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "mylib.h"
#include "htable.h"

struct htablerec{
    int capacity;
    int num_keys;
    int *frequencies;
    char *keys;
};


htable htable_new(int n){
        int i;
        htable result = emalloc(sizeof *result);
        result->capacity = n;
        result->num_keys = 0;
        result->frequencies = emalloc(result->capacity * sizeof result->frequencies[0]);
        result->keys = emalloc(result->capacity * sizeof result->keys[0]);
        for(i=0;i<result->capacity;i++){
            result->frequencies[i] = 0;
            result->keys[i] = '\0';
        }
        return result;  
}

static unsigned int htable_word_to_int(char *word){
    unsigned int result = 0;
    while(*word != '\0'){
        result = (*word++ + 31 * result);
    }
    return result;
}


int htable_insert(htable h, char *str){
    unsigned int key = htable_word_to_int(str);
    unsigned int initial_index = (key % h->capacity);


    if(h->keys[initial_index] == '\0'){
            h->keys[initial_index] = emalloc(strlen(str)+1 * sizeof str[0]);
            strcpy(h->keys[initial_index], str);
            h->frequencies[initial_index] = 1;
            h->num_keys++;
            return 1;
        }

    else if(h->keys[initial_index] == *str){
            h->frequencies[initial_index]++;
            return h->frequencies[initial_index];
        }
    return 0;
    }

void htable_print(htable h){
    int i;    
    for(i=0;i<h->capacity;i++){
        if(h->frequencies[i] >0){
            printf("%d  %s\n", h->frequencies[i], h->keys[i]);
    }
}

}

void htable_free(htable h){
    free(h->frequencies);
    free(h->keys);
    free(h);
}

基本上,插入函数需要一个 htable 和一个字符串。它将字符串转换为整数并除以得到在 htable 的键数组大小内的索引。如果索引为空,则没有任何内容,因此分配足够的内存并插入字符串,或者如果存在相同字符串的事物会增加频率。错误被抛出:

assignment makes integer from pointer without a cast [-Wint-conversion]
h->keys[initial_index] = emalloc(strlen(str)+1 * sizeof str[0]);
                           ^
htable.c:44:11: warning: passing argument 1 of ‘strcpy’ makes pointer   from integer without a cast [-Wint-conversion]
strcpy(h->keys[initial_index], str);

有问题的 emalloc 函数:

void *emalloc(size_t s){
    void *result = malloc(s);
    if(NULL == result){
        fprintf(stderr, "Memory allocation error");
        exit(EXIT_FAILURE);
    }
    return result;
}

这也会导致打印错误,因为 %s 参数的类型为 int。我仍然习惯于 c 中的指针,我确信这是基于错误的问题。

【问题讨论】:

  • 什么是htable?它是htablerec 结构的不透明类型别名吗?
  • @JoachimPileborg 它甚至似乎是可怕的类型化指针......

标签: c arrays pointers hashtable


【解决方案1】:

首先,您显示的不是编译器看到的错误,而是警告。

你正在做的不是你想要的,因为:

h-&gt;keys[initial_index] 是一个 char 而malloc/emalloc 返回一个空指针。

【讨论】:

    【解决方案2】:

    char* 表示您有一个指向 char 的指针(可能是一个以 null 结尾的字符串)。

    char *keys;
    

    但在您的代码中,您将指针分配给单个字符:

    h->keys[initial_index] = emalloc(strlen(str)+1 * sizeof str[0]);
    

    因为h-&gt;keys 的类型是char *,所以h-&gt;keys[initial_index] 是char。您不能将 void *(或一般的指针)分配给 char(或至少期望任何有意义的结果)。

    如果您需要多个字符串(即char * 的数组,A.K.A. 字符串数组),则需要char **。您首先需要 malloc:

    // in the struct
    char **keys;
    
    // when creating the struct
        result->keys = emalloc(result->capacity * sizeof(char *));
        for(i=0;i<result->capacity;i++){
            result->frequencies[i] = 0;
            result->keys[i] = emalloc(1); // say by default 1, you'll realloc later.
            result->keys[i][0] = 0; // assign '\0' to it
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-16
      • 1970-01-01
      • 2018-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多