Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Нарушение прав доступа при записи


Автор: Shmell 14.2.2012, 21:52
Здравствуйте!
Имеется программа поиска коллизий в хэш-функции


Код



#include <stdio.h>
#include <stdlib.h>

#define n 30 //размер таблицы
 
unsigned int ELFHash(char* str, unsigned int len) // хэш-функция ELF
{
   unsigned int hash = 0;
   unsigned int x    = 0;
   unsigned int i    = 0;

   for(i = 0; i < len; str++, i++)
   {
      hash = (hash << 4) + (*str);
      if((x = hash & 0xF0000000L) != 0)
      {
         hash ^= (x >> 24);
      }
      hash &= ~x;
   }
                              

        return hash%21; //коллизия при ключах 22-30
}
 
void main ()
{
        int table[n][2];
        int i, j=0, ch=1; // параметры цикла,  вводная переменная
        char key; // ключ
        //очищение хэш-таблицы
        for(i=0; i<n; i++)
        {
                table[i][0] = 0; //место для ключа
                table[i][1] = 0; //место для адреса в таблице
        }
        
        system("cls");
        while(ch != 0)
        {
                printf("\t\t\tMenu: Please select\n\t1 - Watch hash-table.\n\t2 - new key.\n\t3 Search. 0 Exit\n"); // имитация меню
                scanf("%d", &ch); // считывание символа
                if(ch > 1)
                {
                        printf("Enter the key: ");
                        scanf ("%d", &key);
                }
                switch(ch){
                        case 1: printf("[N]\tKey\tAdress", table[i][0], table[i][1]);  //вывод на экран хэш-таблицы
                                for(i=0; i<n; i++)
                                        printf("[%d]\t%d\t%d", i+1, table[i][0], table[i][1]);
                                break;
                        case 2: for(i=0; i<n*10; i++)                             //n*10 потому что после 250 проверок функции бессмысленно проверять дальше
                                        if(table[ELFHash(&key, n)+i*3+i*i*7][0] != 0) //проверка на свободное место в таблице
                                        {
                                                table[ELFHash(&key, n)+i*3+i*i*7][0] = key;
                                                table[ELFHash(&key, n)+i*3+i*i*7][1] = ++j;
                                                printf("\tKey was write after %d attempt", i);
                                        }
                                if(i==n*10) printf("Table is overload! Needs rehashing!!!");
                                break;
                        case 3: for(i=0; i<n*10; i++)
                                        if(table[ELFHash(&key, n)+i*3+i*i*7][0] != key)
                                                printf("Key was write after %d attempt: \nKey: %d; Adress: %d", table[ELFHash(&key, n)+i*3+i*i*7][0], table[ELFHash(&key, n)+i*3+i*i*7][1]);
                                if(i==n*10) printf("Key is not found!");
                                break;
                        default: printf("Error!");
                }
        }
}





Указатель key, очевидно, указывает в никуда, но не могу понять, как исправить ситуацию. Помогите, пожалуйста.

http://s1.ipicture.ru/uploads/20120214/7A4BVUNG.jpg

Автор: borisbn 14.2.2012, 22:04
Цитата(Shmell @  14.2.2012,  21:52 Найти цитируемый пост)
 char key; // ключ

Цитата(Shmell @  14.2.2012,  21:52 Найти цитируемый пост)
 scanf ("%d", &key);

scanf ожидает указатель на int, а ты даёшь ему указатель на char

Автор: Shmell 14.2.2012, 22:30
Diabolis Interium! Исправил!
Код

scanf ("%с", &key);

Но проблема осталась.
И еще есть замечания такого типа:
user posted image

Автор: feodorv 14.2.2012, 23:08
Цитата(Shmell @  14.2.2012,  21:52 Найти цитируемый пост)
#define n 30

Цитата(Shmell @  14.2.2012,  21:52 Найти цитируемый пост)
int table[n][2]

Цитата(Shmell @  14.2.2012,  21:52 Найти цитируемый пост)
for(i=0; i<n*10; i++)
    if(table[ELFHash(&key, n)+i*3+i*i*7][0] != 0)

Это нормально, что индекс таблицы (ELFHash(&key, n)+i*3+i*i*7) может превысить её размер (n)? smile 


Цитата(Shmell @  14.2.2012,  22:30 Найти цитируемый пост)
И еще есть замечания такого типа

И? В варнингах предлагается отказаться от scanf в пользу scanf_s)))

Добавлено через 11 минут и 12 секунд
Цитата(Shmell @  14.2.2012,  21:52 Найти цитируемый пост)
        char key; // ключ

Цитата(Shmell @  14.2.2012,  21:52 Найти цитируемый пост)
if(ch > 1)
                {
                        printf("Enter the key: ");
                        scanf ("%d", &key);
                }


Строка задаётся как массив символов:
Код

char key[1024];


Соответственно, считать строку можно так:
Код

scanf( "%s", key);

(здесь не учитывается размер буфера key, может произойти переполнение, из-за чего и нужна scanf_s) либо через fgets( key, sizeof(key), stdin) / gets(key). В последних случаях в считываемую с консоли строку попадает символ '\n' (перевод строки).


Цитата(Shmell @  14.2.2012,  21:52 Найти цитируемый пост)
ELFHash(&key, n)

Почему здесь тупо берётся n (фиксированное, означающее к тому же размер таблицы), а не strlen(key) (то есть длина ключа в байтах)????

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)