为什么这会传递if语句?

时间:2012-05-06 01:23:01

标签: c pointers segmentation-fault structure

您好,有人可以帮我找到导致问题的原因吗?由于某种原因,find_hash函数给我带来了问题。它应该是if(table -> buckets_array[i] != NULL){if(table -> buckets_array[i] != '\0'){失败,但它不是,它会进行下一次检查,这会给我一个分段错误。自从我最初将其设置为表格后,可能导致前2个if语句通过的原因 - > buckets_array [i] = NULL?

编辑:感谢wildplasser我为find_hash函数提出了一个更好的解决方案。

if(table->buckets_array[table->hash_func(key)] == NULL){
    return NULL;
  }else{
    return table -> buckets_array[table->hash_func(key)] -> data;
  }

谢谢大家的帮助。

/*hash.h*/
#include<stdio.h>
#include<stdlib.h>

typedef struct data_{
  char *key;
  void *data;
  struct data_ *next;
}data_el;

typedef struct hash_table_ {
  void **order;
  int *number_next_calls;
  int *number_buckets;
  int *buckets_size;
  int *worst;
  int *total;
  float *average;
  int (*hash_func)(char *);
  int (*comp_func)(void*, void*);
  data_el **buckets_array;
} hash_table, *Phash_table;

Phash_table new_hash(int size, int (*hash_func)(char *), int (*cmp_func)(void *, void *));
void free_hash(Phash_table table);
void insert_hash(Phash_table table, char *key, void *data);
void *find_hash(Phash_table table, char *key);
void stat_hash(Phash_table table, int *total, int *largest, float *average);
void *start_hash_walk(Phash_table table);
void *next_hash_walk(Phash_table table);

static void lower_case_word(char *w);

/*hash.c*/
#include"hash.h"

Phash_table new_hash(int size, int (*hash_func)(char *), int (*cmp_func)(void *, void *)){
  int i;

  Phash_table table_p;
  hash_table hash_table;

  table_p = (Phash_table)malloc(sizeof(hash_table));

  /*Setting function pointers*/
  table_p->hash_func = hash_func;
  table_p->comp_func = cmp_func;

  /*Create buckets array*/
  table_p->buckets_array = (data_el **)malloc(sizeof(data_el *)*(size+1));
  table_p->buckets_size = (int *)malloc(sizeof(int)*(size+1));

  /*Setting order array*/
  table_p->order = NULL;

  /*Setting inital condictions*/
  table_p->worst = (int *)malloc(sizeof(int));
  table_p->total = (int *)malloc(sizeof(int));
  table_p->average = (float *)malloc(sizeof(float));
  table_p->number_buckets = (int *)malloc(sizeof(int));

  *(table_p->number_buckets) = size;

  for(i = 0; i < size; i++){
    table_p->buckets_array[i] = NULL;
  }
  return table_p;
}

void free_hash(Phash_table table){

  int i;
  i = 0;
  data_el *cur;
  data_el *prev;

  /*Free order array*/
  if(table->order != NULL){
    free(table->order);
  }

  /*Free Buckets array and buckets_size array*/
  if(table ->buckets_array != NULL){
    for(i=0; i < *(table->number_buckets); i++){
      if(table->buckets_array[i] != NULL){

    /*Travers the linked list and free it*/
    cur = table->buckets_array[i];
    prev = cur;

    while((cur = cur->next) != NULL){
      free(prev);
      prev = cur;
    }
    /*Free the last node*/
    free(cur);
    }
    }
  }
  free(table);
}

void insert_hash(Phash_table table, char *key, void *data){
  int index;
  data_el *p, *cur;

  index = table->hash_func(key);

  /*Head insertion*/
  if(table->buckets_array[index] == NULL){
    table->buckets_array[index] = (data_el *)malloc(sizeof(data_el));
    table->buckets_array[index]->data = data;
    table->buckets_array[index]->next =  NULL;
    table->buckets_array[index]->key = key;
  }else{
    cur = table->buckets_array[index];
    p = (data_el *)malloc(sizeof(data_el));
    p->key = key;
    p->data = data;
    p->next = cur;
    cur = p;
    table->buckets_array[index] = cur;
  }

  /*Update Total*/
  *table->total += 1;

  /*Update Bucket Size*/
  (table->buckets_size[index]) +=1;

  /*Updates Worst Case*/
  if((table->buckets_size[index]) > *(table->worst)){
    *(table->worst) = (table->buckets_size[index]);
  }else{
    *(table->worst) +=1;
  }

  /*Update Average*/
  int temp_total,temp_buckets;

  temp_total = *(table->total);
  temp_buckets = *(table->number_buckets);
  *(table->average)= (float)temp_total/(float)temp_buckets;
}

void *find_hash(Phash_table table, char *key){
  int i;
  i = 0;

  while(1){
    if(table->buckets_array[i] == '\0'){
      printf("End of Array");
      break;
    }
    if(table->buckets_array[i] != NULL){
      printf("%Checking");
      if(table->buckets_array[i] != '\0'){
    if(table->buckets_array[i]->key != NULL){
      if( strcmp(table->buckets_array[i]->key,key) == 0 ){
        printf("Found it\n");
        break;
      }
    }
      }
    }
    i++;
  }

  if(table->buckets_array[i] != NULL){
    printf("new asdasd %d", *((int *)table->buckets_array[i]->data));
    return table->buckets_array[i]->data;
  }else{
    return NULL;
  }
}

void stat_hash(Phash_table table, int *total, int *largest, float *average){
  total =  (table->total);
  largest = (table->worst);
  average =  (table->average);
}

void *start_hash_walk(Phash_table table){
  int i, max_buckets,step,next_calls;
  step = 0;
  data_el *cur;
  next_calls = 0;

  max_buckets = *(table ->number_buckets);
  table->order = (void**)malloc(sizeof(void *)*(*(table->total)));

  /*Set number_next_calls to 0*/
  table->number_next_calls = &next_calls;
  *(table->number_next_calls) = 0;

  /*Traverse the ADT and put all data into order array*/
  for(i = 0; i < max_buckets; i++){
    if(table->buckets_array[i] != NULL){
      cur = table->buckets_array[i];
      while(cur){
    table->order[step] = cur->data;
    step ++;
    cur = cur->next;
      }
    }
  }

  /*Bubble Short*/
  int j,k;

  for(j = 0; j < (step - 1);j++){
    for(k = 0;k < (step -(j+1));k ++){
      if((table->comp_func)(table->order[j],table->order[j+1]) < 5){
    void *temp;

    temp = table->order[j];
    table->order[j] = table->order[j+1];
    table->order[j+1] =  temp;
    printf("Swaping %s with %s\n",table->order[j],table->order[j+1]);
      }
    }
  }
  return table->order;
}

void *next_hash_walk(Phash_table table){

  /*
    Check the amount of times next_has_walk has been
    if higher than total, it will return null
  */

  if(*(table->number_next_calls) >= *(table->total)){
    return NULL;
  }else{
    *(table->number_next_calls) = *(table->number_next_calls) + 1;
    return table->order[*(table->number_next_calls)];
  }
}

/*project4.c*/

#include"hash.h"

#define WORD_SIZE 40
#define DICTIONARY_SIZE 1000
#define TRUE 1
#define FALSE 0

int hash_function(char *word){

  int sum,i;
  i = 0;
  sum = 0;
  while(word[i] != '\0'){
    sum = sum + word[i];
    i++;
  }
  return sum%1000;
}

int main(void){

  /*Creating buckets array*/
  Phash_table dictionary;
  void *test;

  dictionary = new_hash(DICTIONARY_SIZE,hash_function,comp);

  int i;
  i = 0;
  void *frequency[DICTIONARY_SIZE];
  int char_index = 0, dictionary_size = 0, num_words = 0;
  char c, word[WORD_SIZE];

  printf("Parsing input ...\n");

  while ((c = getchar()) != EOF) {
    if ((c == ' ') || (c == ',') || (c == '.') || (c == '!') || (c == '"') ||
    (c == ':') || (c == '\n')) {

      /* End of a word */
      if (char_index) {
    /* Word is not empty */
    word[char_index] = '\0';
    lower_case_word(word);
    if(!find_hash(dictionary,word) ){
      insert_hash(dictionary,word,frequency[hash_function(word)]);
    }
    frequency[hash_function(word)]++;
    char_index = 0;
    num_words++;
      }
    }else{
      word[char_index++] = c;
    }
  }

  printf("There were %d words; %d unique words.\n", num_words,dictionary_size);
}

void lower_case_word(char *w){
  int i = 0;

  while (w[i] != '\0') {
    w[i] = tolower(w[i]);
    i++;
  }
}

2 个答案:

答案 0 :(得分:1)

这太复杂了。我会在代码中发表评论。

void *find_hash(Phash_table table, char *key){
  int i;
  i = 0;

  while(1){

for()循环的绝佳位置。

    if(table->buckets_array[i] == '\0'){

- &gt; buckets_array []是指向data_el指针数组的指针 '\ 0'是一个int(一个字符常量是C中的int)

      printf("End of Array");
      break;
    }
    if(table->buckets_array[i] != NULL){

你已经测试过了,并且已经退出了循环。条件总是如此。

      printf("%Checking");
      if(table->buckets_array[i] != '\0'){

无需第三次测试。

    if(table->buckets_array[i]->key != NULL){

啊!现在我们到了节点的有效载荷

      if( strcmp(table->buckets_array[i]->key,key) == 0 ){
        printf("Found it\n");
        break;
      }
    }
      }
    }

这里有大括号,我懒得读书,或算数(4)或加工它们。

    i++;
  }


  if(table->buckets_array[i] != NULL){

你似乎真的喜欢这种情况。

    printf("new asdasd %d", *((int *)table->buckets_array[i]->data));
    return table->buckets_array[i]->data;

啊!有效载荷得到传递。您可以将打印保留给来电者。

  }else{
    return NULL;
  }
}

缩小版本:

void *find_hash(Phash_table table, char *key){
      int i;
      unsigned i;

      for (i=0; i < *table_p->number_buckets; i++){
         data_el *cur;

         for (cur = table->buckets_array[i]; cur != NULL; cur = cur->next ) {
            if( strcmp(cur->key,key) ) continue;

            return cur->data; /* found it ! */
            }
         }
    return NULL;
}

另外:malloc int-size对象(如 table_p-&gt; number_buckets)更实际的是将定义更改为:

typedef struct hash_table_ {
  void **order;  /* This might be intended as a permutation array ? */
  unsigned number_next_calls;
  unsigned int number_buckets;

  unsigned int *buckets_size; /* I think this was intended as a histogram */
  unsigned int worst;
  unsigned int total;
  float average;
  int (*hash_func)(char *);
  int (*comp_func)(void*, void*);
  data_el **buckets_array;
} hash_table, *Phash_table;

隐藏在typedef后面的指针(比如你的Phash_table)在一般被认为是不好的做法。

正如我昨天评论的那样,你的哈希函数很危险,因为它返回一个signed int。它可能会产生负面指数。 (这也是非常糟糕的,碰撞方面,因为“ABC”,“ACB”,“CAB”都散列到相同的值。更好地使用K&amp; R,FNV或Jenkins。)

答案 1 :(得分:0)

也许您可以更正代码,以便它是您正在测试的内容。也许包括所有必要的位,以便我们可以编译它(我喜欢)。

请注意,find_hash没有返回值,但在调用insert_hash之前调用它会给您带来麻烦。

编辑(现已显示完整代码)

函数compnew_hash的调用中 - 因此无法编译。

你在做什么与mallocs:

table_p->worst = (int *)malloc(sizeof(int));
table_p->total = (int *)malloc(sizeof(int));
table_p->average = (float *)malloc(sizeof(float));
table_p->number_buckets = (int *)malloc(sizeof(int));

无论如何都不应该从malloc返回,但是在这里你要为int分配空间然后告诉编译器你为int *分配了空间。这些字段实际上需要成为指针吗?

在你的find_hash中,循环应该是for:

for (i=0; table->buckets_array[i] == ...; ++i) {
    etc
}

但是,正如sarnold所说,为什么对table->buckets_array[i](0)和NULL(0)进行'\0'测试。这是非常奇怪的事情。

我不会花太多时间调试它。相反,我建议对代码进行审查(或让同事审查它)并整理出一些问题。其中包括:

  • 搞清楚什么表 - &gt; buckets_array [i]应该包含
  • 取消播放malloc返回
  • 没有为整数数据建立空间
  • 格式化
  • const添加到未更改的参数
  • 尽可能提取嵌套循环
  • 使用正确的循环