C - 分配内存并将字符串复制到哈希表的数组中

时间:2016-08-22 09:51:19

标签: c arrays pointers hashtable

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

#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密钥数组大小的索引。如果索引为null,则没有任何内容,因此分配足够的内存并插入字符串,或者如果有相同的字符串增加频率。错误被抛弃:

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中的指针,我确信这是基于错误的问题。

2 个答案:

答案 0 :(得分:1)

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

char *keys;

但是在你的代码中,你要指定一个指向一个char的指针:

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

由于h->keys的类型为char *h->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

答案 1 :(得分:0)

首先,你所展示的不是编译器看到的错误,而只是警告。

你所做的不是你想要的,因为:

:default => ''h->keys[initial_index],而char返回空指针。