2015-11-29 5 views
0

Я строил эту функцию хеш-таблицы, которой задан массив, из которого он получает слово, и указатель на массив, который он заполняет моей связанной структурой списков. Он правильно компилируется, но я получаю ошибку сегментации при - * hashTable [hashVal] = * newNode; ,C: Помогите понять указатели

void hashTableCreate(char *array, list *hashTable[]) { 

while(arrayPos < getArrayLength(array)) { 

    char *temp = getWord(array); 
    int hashVal = hashingFunc(temp); 
    if((*hashTable[hashVal]).word == temp) { 
     (*hashTable[hashVal]).count = (*hashTable[hashVal]).count+1; 
    } 
    else { 
     list *newNode = malloc(sizeof(list)); 
     strcpy(newNode->word,temp); 
     newNode->count = 1; 
     *hashTable[hashVal] = *newNode; 
    } 
} 
} 

Это называется так:

void timeStructures(char *newArray) { 
    list *hashTable[3000]; 
    hashTableCreate(newArray, hashTable); 
} 

Я знаю, что это делать с тем, как я использую мои указатели, но я не могу понять это. Любая помощь будет оценена по достоинству.

+0

Вы хотите 'hashTable [hashVal] = newNode'. То, что у вас есть, '* hashTable [hashVal]', неверно, потому что оно вызывает «hashTable [hashVal]», но ни одна из ваших записей массива не инициализируется. Фактически, вам нужно запустить свой 'hashTable', чтобы все его записи были NULL, чтобы вы могли проверить это, а не разыменовывать любые записи NULL. В настоящий момент ваш код получает доступ к недопустимой памяти по всему месту. – kaylum

ответ

0

Есть несколько проблем, по этому коду:

  1. Вы, кажется, вы используете дополнительные звездочки при назначении newNode в hashTable.
  2. Оператор ++ для увеличения числа count и используйте -> для доступа к элементу указателя к структуре.
  3. getWord мне неизвестна, но кажется невозможным, что может вернуть указатель на строку, заключенную внутри элемента hashTable, что означает, что следующий if всегда будет ложным (newNode «s word является копироваться строка, а не указатель на array), поскольку он сравнивает адреса памяти вместо строк.
  4. Вы никогда не освобождаете temp ни hashTable элементов, которые кажутся еще одним неправильным представлением о том, что вы здесь делаете.
  5. Как отмечено @kaylum, вы должны инициализировать hashTable, чтобы избежать сравнения с неназначенными элементами массива, не изменяя на них count.
  6. hashTable должен быть передан как указатель на hashTableCreate, или это будет работать на скопированной версии этого:

Попробуйте это:

void hashTableCreate(char *array, list *(*hashTable[])) { 

    while(arrayPos < getArrayLength(array)) { 

     char *temp = getWord(array); 
     int hashVal = hashingFunc(temp); 

     if((*hashTable)[hashVal] != NULL && 
     strcmp((*hashTable)[hashVal]->word, temp) == 0) { 
     (*hashTable)[hashVal]->count++; 
     } 
     else { 
     list *newNode = malloc(sizeof(list)); 
     strcpy(newNode->word,temp); 
     newNode->count = 1; 
     (*hashTable)[hashVal] = newNode; 
     } 

     free(temp); 
    } 
} 

void timeStructures(char *newArray) { 
    list *hashTable[3000]; 
    int i; 

    // Initialize hashTable pointers to NULL 
    for(i = 0; i < 3000; i++) { 
     hashTable[i] = NULL; 
    } 

    hashTableCreate(newArray, &hashTable); 

    // Free hashTable elements, malloc'ed at hashTableCreate 
    for(i = 0; i < 3000; i++) { 
     if(hashTable[i] != NULL) { 
     free(hashTable[i]); 
     } 
    } 
} 

Примечание 1: вы никогда не проверить, если hashVal является выше 3000, что может быть хорошо, если вы знаете, что делаете, ака, вы знаете, hashingFunc никогда не вернется 3000 или выше. Если вы этого не сделаете, вам нужно будет заботиться о том, чтобы расти hashTable соответственно.

Примечание 2: Выполнение getArrayLength на каждом цикле может быть проблемой производительности для больших списков. Вероятно, вы предпочитаете создавать переменную, чтобы содержать ее значение и выполнять ее только один раз.

Примечание 3: Это может быть несколько проще, если вы объявите hashTable как простой список элементов, а не список указателей на элементы, например list hashTable[3000];, но я не знаю точно, что вы ищете. Кроме того, он всегда будет тратить 3000 list элементов памяти, поэтому может возникнуть проблема с производительностью.