背景:创建一个哈希表库,允许3个不同的实现2解决与开放寻址的冲突(一个是固定大小而另一个是动态的)和第三个使用链接列表单独链接
问题背景:通过创建固定大小的开放式寻址开始。起初,这种方法非常完美,但必须进行一些更改以适应库以满足其他两个实现。为此,我需要记录列表的大小(使用的结构)和void指针作为开放寻址的结构,并且单独的链接是不同的。
实际问题:由于某些原因,我的保存功能在调试时不再有效我发现有两个问题我无法辨别原因:
保存问题中的功能:
void hashtbl_savetofile(void* hashtbl, const char *path){
Hashtbl *temp;
temp = hashtbl;
int i;
FILE *f = fopen(path, "w");
if (f == NULL){
printf("FILE NOT FOUND!");
}else {
for(i = 0; i<SIZE; i++) {
fprintf(f, "%s", temp->data[i].subscript); // segmentation fault occurs
fprintf(f, "%s", temp->data[i].value);
}
fclose(f);
free(temp);
}
}
标题文件:
#ifndef TASK2_HASHTABLE_H
#define TASK2_HASHTABLE_H
#define SIZE 20
#define MAX_LENGTH 100
#define INIT_SIZE 64000
typedef struct Data_struct{
char *subscript;
char *value;
} Data;
typedef struct Hashtbls{
int numberOfEntries;
int allocatedEntries;
Data *data;
}Hashtbl;
int hashtbl_hashKey(void* hashtbl, const char *subscript ); // generates hash key for hash table
Data hashtbl_lookup(void* hashtbl, const char *subscript); //looks up and retrieves a given subscript and its value hash table
void* hashtbl_insert(void* hashtbl, const char *subscript, const char *value); //adds a given subscript and its value to hash table
void* hashtbl_delete(void* hashtbl, const char *subscript); //deletes a given subscript and its value from hash table
void hashtbl_savetofile(void* hashtbl, const char *path); //saves hash table to file
void* hashtbl_loadfromfile(void* hashtbl, const char *path); //loads hash table from file
void* hashtbl_init();
#endif //TASK2_HASHTABLE_H
测试驱动程序:
#include <stdio.h>
#include "hashtable.h"
int main() {
Hashtbl *nums;
Data d;
nums = hashtbl_init();
hashtbl_insert(nums, "tea", "40c");
hashtbl_insert(nums, "coffee", "50c");
hashtbl_insert(nums, "biscuit", "4c");
hashtbl_insert(nums, "tart", "30c");
d = hashtbl_lookup(nums, "tart");
printf("%s", d.subscript);
printf("%s", d.value);
hashtbl_savetofile(nums, "test.txt");
}
实施(供参考):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hashtable.h"
void* hashtbl_init(){ //initiates static 2D hash table when called
Hashtbl* hashtbl;
hashtbl = malloc(INIT_SIZE);
hashtbl->numberOfEntries = SIZE;
hashtbl->allocatedEntries = 0;
hashtbl->data = calloc(SIZE, sizeof(Data));
for(int i = 0; i<SIZE; i++){
hashtbl->data[i].subscript = malloc(MAX_LENGTH + 1);
strcpy(hashtbl->data[i].subscript, "ZERO\n");
hashtbl->data[i].value = malloc(MAX_LENGTH + 1);
strcpy(hashtbl->data[i].value, "ZERO\n");
}
return hashtbl;
}
Data hashtbl_lookup(void* hashtbl, const char *subscript){
Data item;
Hashtbl *temp;
temp = hashtbl;
int i = 0;
char *c;
c = malloc(MAX_LENGTH);
strcpy(c, subscript);
strct(c, "\n");
while (strcmp(temp->data[(hashtbl_hashKey(hashtbl, subscript)+i)].subscript, c) != 0){
i++;
if(hashtbl_hashKey(hashtbl, subscript)+i == temp->numberOfEntries){
break;
}
}
if(hashtbl_hashKey(hashtbl, subscript)+i != temp->numberOfEntries) {
if(strcmp(temp->data[(hashtbl_hashKey(hashtbl, subscript)+i)].subscript, c) == 0) {
item.subscript = temp->data[(hashtbl_hashKey(hashtbl, subscript) + i)].subscript;
item.value = temp->data[(hashtbl_hashKey(hashtbl, subscript) + i)].value;
}
}else{
for(i = 0; i<hashtbl_hashKey(hashtbl, subscript); i++){
if(strcmp(temp->data[i].subscript, c) == 0){
item.subscript = temp->data[i].subscript;
item.value = temp->data[i].value;
}
}
}
free(hashtbl);
free(c);
free(temp);
return item;//what if not found
}
void* hashtbl_insert(void* hashtbl, const char *subscript, const char *value){
Hashtbl *temp;
temp = hashtbl;
int i = 0;
char *c1;
c1 = malloc(MAX_LENGTH);
strcpy(c1, subscript);
strcat(c1, "\n");
char *c2;
c2 = malloc(MAX_LENGTH);
strcpy(c2, value);
strcat(c2, "\n");
if(temp->allocatedEntries == temp->numberOfEntries){
free(c1);
free(c2);
free(temp);
return hashtbl;
}else {
if (strcmp(temp->data[hashtbl_hashKey(hashtbl, subscript) + i].subscript, "ZERO\n") == 0) {
temp->data[hashtbl_hashKey(hashtbl, subscript)].subscript = c1;
temp->data[hashtbl_hashKey(hashtbl, subscript)].value = c2;
temp->allocatedEntries++;
} else {
while ((strcmp(temp->data[hashtbl_hashKey(hashtbl, subscript) + i].subscript, "ZERO\n") != 0)) {
i++;
if (hashtbl_hashKey(hashtbl, subscript) + i == temp->numberOfEntries) {
break;
}
}
if (hashtbl_hashKey(hashtbl, subscript) + i != temp->numberOfEntries) {
if ((strcmp(temp->data[hashtbl_hashKey(hashtbl, subscript) + i].subscript, "ZERO\n") == 0)) {
temp->data[(hashtbl_hashKey(hashtbl, subscript) + i)].subscript = c1;
temp->data[(hashtbl_hashKey(hashtbl, subscript) + i)].value = c2;
temp->allocatedEntries++;
}
} else {
for (i = 0; i < hashtbl_hashKey(hashtbl, subscript); i++) {
if (strcmp(temp->data[i].subscript, "ZERO\n") == 0) {
temp->data[i].subscript = c1;
temp->data[i].value = c2;
temp->allocatedEntries++;
}
}
}
}
free(c1);
free(c2);
return temp;
}
}
void* hashtbl_delete(void* hashtbl, const char *subscript){
Hashtbl *temp;
temp = hashtbl;
int i = 0;
int j = 0;
char *c;
c = malloc(MAX_LENGTH);
strcpy(c, subscript);
strcat(c, "\n");
while ((strcmp(temp->data[(hashtbl_hashKey(hashtbl, subscript)+i)].subscript, c) != 0)){
i++;
if((hashtbl_hashKey(hashtbl, subscript)+i) == temp->numberOfEntries) {
break;
}
}
if(hashtbl_hashKey(hashtbl, subscript)+i != temp->numberOfEntries) {
if(strcmp(temp->data[(hashtbl_hashKey(hashtbl, subscript)+i)].subscript, c) == 0) {
temp->data[(hashtbl_hashKey(hashtbl, subscript) + i)].subscript = "ZERO\n";
temp->data[(hashtbl_hashKey(hashtbl, subscript) + i)].value = "ZERO\n";
temp->allocatedEntries--;
}
}else{
for(j = 0; j<hashtbl_hashKey(hashtbl, subscript); j++){
if(strcmp(temp->data[j].subscript, c) == 0){
temp->data[j].subscript = "ZERO\n";
temp->data[j].value = "ZERO\n";
temp->allocatedEntries--;
}
}
}
hashtbl=temp;
free(c);
free(temp);
return hashtbl;
}
void hashtbl_savetofile(void* hashtbl, const char *path){
//provided above
}
void* hashtbl_loadfromfile(void* hashtbl, const char *path){
Hashtbl *temp;
temp = hashtbl;
temp->allocatedEntries=0;
int i = 0;
int j =0;
int c = 0;
char line[100];
char* string[temp->numberOfEntries];
FILE *f = fopen(path, "r");
if(f == NULL){
free(temp);
return NULL;
}else {
while(fgets(line, sizeof line, f)){
j++;
}
if((j/2)>temp->numberOfEntries){
free(temp);
return NULL;
}else {
while (fgets(line, sizeof line, f)) {
string[i] = malloc(strlen(line) + 1);
if (string[i] == NULL) {
break;
return NULL;
} else {
strcpy(string[i], line);
i++;
if (i == sizeof string / sizeof *string) {
break;
}
}
}
fclose(f);
for (i = 0; i < (SIZE * 2); i++) {
if (strlen(string[i]) >= MAX_LENGTH) {
char *k = realloc(temp->data[c].subscript, strlen(string[i]));
if (k == NULL) {
break;
return NULL;
} else {
temp->data[c].subscript = k;
strcpy(temp->data[c].subscript, string[i]);
if(temp->data[c].subscript != "ZERO\n"){
temp->allocatedEntries++;
}
i++;
c++;
}
} else {
temp->data[c].subscript = malloc(strlen(string[i]) + 1);
strcpy(temp->data[c].subscript, string[i]);
if(temp->data[c].subscript != "ZERO\n"){
temp->allocatedEntries++;
}
i++;
c++;
}
}
c = 0;
for (i = 1; i < (SIZE * 2); i++) {
if (strlen(string[i]) >= MAX_LENGTH) {
char *k = realloc(temp->data[c].value, strlen(string[i]));
if (k == NULL) {
break;
return NULL;
} else {
temp->data[c].value = k;
strcpy(temp->data[c].value, string[i]);
i++;
c++;
}
} else {
temp->data[c].value = malloc(strlen(string[i]) + 1);
strcpy(temp->data[c].value, string[i]);
i++;
c++;
}
}
hashtbl=temp;
free(temp);
free(string);
return hashtbl;
}
}
}
int hashtbl_hashKey(void* hashtbl, const char *subscript){
int i;
int h = 0;
for(i = 0; subscript[i]; i++){
h += subscript[i];
}
h = h%SIZE;
return h;
}