본문 바로가기
Computer Science

IoT Database

by OKOK 2018. 11. 21.

string 을 key 값으로 받을 때 처리하는 방법에 대해서 나옴

http://egloos.zum.com/rucaus/v/2348565

String Hash 함수에 대해



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <stdio.h>
#define MAXN 2400
#define SIZE 65536
#define LEN  12 // 길이가 이렇게 주어지는군
unsigned char mem[SIZE]; // mem 사이즈 이것 또한 65536, unsigned char로 한 이유가 있음
typedef enum COMMAND
{
    PUT = 100,
    DEL = 200,
    GET = 300,
    GET_KEY = 400,
    END = 900,
};
int N, M;
int ret = 100;
extern bool init(int N);
extern void put(unsigned char key_in[], unsigned char value_in[]);
extern void del(unsigned char key_in[]);
extern void get(unsigned char key_in[], unsigned char value_out[]);
extern void get_key(unsigned char value_in[], unsigned char key_out[]);
int mstrcmp(unsigned char arr[], unsigned char arr2[])
{
    register int i = 0;
    while (arr[i])
    {
        if (arr[i] != arr2[i++]) return 0;
    }
    if (arr2[i]) return 0;
    return 1;
}
void memread(unsigned char str[], int pos, int len)
{
    for (register int i = 0; i < len; i++)
    {
        str[i] = mem[pos + i];
    }
}
// pos 위치에서 len 만큼 str에 저장된 값을 메모리에 저장
void memwrite(unsigned char str[], int pos, int len)
{
    for (register int i = 0; i < len; i++)
    {
        mem[pos + i] = str[i]; // str 받은것을 pos + 1 부터 넣습니다
    }
}
void run()
{
    unsigned char key[LEN + 1]; // 총 12 + 1개 
    unsigned char value[LEN + 1]; // 총 12 + 1개
    int cmd;
    for (register int i = 0; i < M; i++)
    {
        scanf("%d"&cmd); // enum 을 사용해서 어떤 명령어가 들어오는지 표시함
        switch (cmd)
        {
        case PUT:
        {
            scanf("%s %s", key, value);
            put(key, value);
            break;
        }
        case DEL:
        {
            scanf("%s", key);
            del(key);
            break;
        }
        case GET:
        {
            unsigned char out[LEN + 1];
            scanf("%s %s", key, out);
            get(key, value);
            if (mstrcmp(value, out) == 0) ret = 0;
            break;
        }
        case GET_KEY:
        {
            unsigned char out[LEN + 1];
            scanf("%s %s", value, out);
            get_key(value, key); // key 가 여기에 있는 변수이므로 사용하는 것. key_out 과 공용으로
            if (mstrcmp(key, out) == 0) ret = 0;
            break;
        }
        case END:
        defaultreturn;
        }
    }
}
int main()
{
    int T;
    freopen("text.txt""r", stdin);
    scanf("%d"&T); // 테스크 케이스 겟수 1
    for (register int testcase = 1; testcase <= T; testcase++)
    {
        scanf("%d %d"&N, &M); // N : 데이터 입력 수 M 
        if (init(N)) run();
        printf("#%d %d\n", testcase, ret);
    }
    return 0;
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
extern void memread(unsigned char str[], int pos, int len);
extern void memwrite(unsigned char str[], int pos, int len);
#define MAX 65536 // 비휘발성 메모리 사이즈를 입력
#define MAX_TABLE (MAX/2)
#define DIFF 15
 
// 해시 이렇게 만드는 이유
unsigned int hash(unsigned char *str)
{
    unsigned int hash = 5381// 이 값은 무엇
    int c;
 
    while (c = *str++)
    {
        hash = (((hash << 5+ hash) + c) % (MAX_TABLE / DIFF);
    }
 
    return hash % (MAX_TABLE / DIFF);
}
 
 
bool init(int N)
{
    unsigned char s[MAX] = { '\0', }; // 비휘발성 메모리에 최대치를 정적할당함 그리고 초기화해둠
    memwrite(s, 0, MAX); // 0의 위치에서 MAX만큼 s에 저장된 값을 mem에 저장함
    return true// init 의 결과를 true 로 반환함
}
 
void put(unsigned char key_in[], unsigned char value_in[]) // 키인과 밸류인을 입력받음 배열로, 문자열
{
    // database에 필드를 저장.
 
    //int temp = (idx[1] * 256) + idx[0];
    unsigned int k_index = hash(key_in) * DIFF; //  위의 해시가 어떻게 나오는것? 이 공식이 정해져 있는 것인가
    unsigned int v_index = hash(value_in) * DIFF + MAX_TABLE; // 위의 것 동일
    unsigned char idx[2];
    idx[0= ((v_index << 24& 0xff000000>> 24// ??
    idx[1= ((v_index << 16& 0xff000000>> 24// ??
    memwrite(key_in, k_index, 13); // 받아서 넣음
    memwrite(idx, k_index + 132); // idx ? k_index+13, 2?
    idx[0= ((k_index << 24& 0xff000000>> 24// k_index 값을 넣은 후에 왜 변경?
    idx[1= ((k_index << 16& 0xff000000>> 24;
    memwrite(value_in, v_index, 13); // v_index 위치에 13길이 만큼의 value_in 을 넣고
    memwrite(idx, v_index + 132);// v_indexd + 13 위의 mem 바로 뒤에 2길이 만큼의 idx를 넣음
}
 
 
/*
k_index, v_index 를 설정해서 이것을 넣어다가 뺏다가 사용함
해쉬 인덱스를 계산하는 방법이 궁금함
*/
void del(unsigned char key_in[])
{
    // key 값으로 주어진 문자열을 통해 database에서 삭제.
    unsigned char delstr[DIFF];
    for (register int i = 0; i < DIFF; i++) {
        delstr[i] = '\0'// 초기화 시킴
    }
    unsigned char idx[2];
    int k_index = hash(key_in) * DIFF;
    memread(idx, k_index + 132);
    memwrite(delstr, k_index, DIFF);
    int v_index = (idx[1* 256+ idx[0];
    memwrite(delstr, v_index, DIFF); 
}
 
void get(unsigned char key_in[], unsigned char value_out[])
{
    // key값을 input으로 value를 찾아서 value_out에 기록.
    unsigned char idx[2];
    int k_index = hash(key_in) * DIFF;
    memread(idx, k_index + 132); //  idx 에 읽어옴
    unsigned char result[13];
    int v_index = (idx[1* 256+ idx[0];
    memread(result, v_index, 13); // result에 읽어옴
    for (register int i = 0; i < 13; i++) {
        value_out[i] = result[i];
    }
}
 
void get_key(unsigned char value_in[], unsigned char key_out[])
{
    // value값을 input으로 value를 찾아서 key_out에 기록.
    unsigned char idx[2];
    int v_index = hash(value_in) * DIFF + MAX_TABLE;
    memread(idx, v_index + 132);
    unsigned char result[13];
    int k_index = (idx[1* 256+ idx[0];
    memread(result, k_index, 13);
    for (register int i = 0; i < 13; i++) {
        key_out[i] = result[i];
    }
}
 
cs


- main, user code

- hash 를 어떻게 사용하는지

- 명확히 파악하고

- 키와 배류를 어떻게 받아들이고 쓰는지 알아볼 것


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
user.cpp 작성하기
흐름 파악
*/
 
#define MEMORY_SIZE 65536
#define MAX_LEN 12
#define MAX_TABLE 2400 //  65536/2/15 이것인가? MAX_TABLE 결정하는 방법에 대해서
#define MAP_INDEX 57600 // 이것은 무엇
 
extern void memread(unsigned char str[], int pos, int len);
extern void memwrite(unsigned char str[], int pos, int len);
extern int mstrcmp(unsigned char str[], unsigned char[]);
 
int mystrlen(unsigned char * str) {
    int len = 0;
    while (*str++) len++;  // str의 값이 빌때까지 ++ 해서 '\0' 을 만나면 종료됨
    return len;
}
 
void mystrcpy(unsigned char * tgt, unsigned char * src) {
    while (*src) { // 복사를 진행한 후
        *tgt++ = *src++;
    }
    *tgt = '\0'// 문자열을 완성함
}
 
// 정형적인 해쉬함수 string을 입력받아서 hash 값을 리턴함
unsigned short myhash(unsigned char *str) { // 리턴 형태 0~65,535 해쉬값이 이 사이에 존재함
    unsigned short hash = 5381;
    int c; // str 값을 하나씩 입력 받음
    while (c = *str++) {
        hash = (((hash << 5+ hash) + c) % MAX_TABLE;
    }
    return hash % MAX_TABLE;
}
 
/*
mem을 null로 초기화함
*/
bool init(int N) 
{
    unsigned char zero[MEMORY_SIZE] = { '\0', };
    memwrite(zero, 0, MEMORY_SIZE);
    return true;
}
 
/*
1. key의 hash값을 구해서 그 위치에서 1byte를 읽어서 NULL인지 확인함
2. NULL 이라면 12byte buffer에 key를 copy해서 저장함
3. NULL 아니면 NULL을 찾을 때까지 다음 위치를 넣어봄 (hash + 1)%MAX_TABLE
4. value 에 대해서도 1~3의 작업을 진행함
5. 4번에서 구한 value_hash 값을 mem 배열의 key_hash *2 + MAP_INDEX 의 위치에 길이 2바이트 크기만큼 저장함
*/
unsigned short memsave(unsigned char str[])
{
    unsigned short hash;
    hash = myhash(str);
    unsigned char temp_buff[MAX_LEN] = { '\0', };
    memread(temp_buff, hash * MAX_LEN, 1);
 
    while (1) {
        if (temp_buff[0== '\0') {
            memwrite(str, hash * MAX_LEN, MAX_LEN);
            break;
        }
        else {
            hash = (hash + 1) % MAX_TABLE;
            memread(temp_buff, hash * MAX_LEN, 1);
        }
    }
    return hash;
}
 
void put(unsigned char key_in[], unsigned char value_in[])
{
    unsigned short key_hash;
    unsigned short value_hash;
    key_hash = memsave(key_in);
    value_hash = memsave(value_in);
    memwrite((unsigned char*)&value_hash, key_hash * 2 + MAP_INDEX, 2);
}
 
/*
1. key의 hash 값을 구해서 hash 에 해당하는 index에서 12바이트를 읽어와서 key 와 동일한지 비교함
2. 동일하지 않으면 hash + 1 % MAX_TABLE 처리해서 key 와 동일한 12바이트가 나올 때까지 memread를 반복함
3. 그렇게 구한 hash 값으로 index해서 2바이트 저장된 value의 id를 가져옴
4. 키값을 지우고, value의 id를 이용해서 value 값도 지움
*/
 
unsigned short find_str(unsigned char * str) {
    unsigned short hash = myhash(str);
    unsigned char temp_buff[MAX_LEN] = { '\0', };
    memread(temp_buff, hash * MAX_LEN, MAX_LEN);
 
    while (1) {
        if (mstrcmp(temp_buff, str) == 1)
            return hash;
        else {
            hash = (hash + 1) % MAX_TABLE;
            memread(temp_buff, hash * MAX_LEN, MAX_LEN);
        }
    }
}
 
void del(unsigned char key_in[])
{
    unsigned short key_hash = find_str(key_in);
    unsigned short value_hash = 0;
    unsigned char delete_buff[MAX_LEN] = { '\0', };
 
    memread((unsigned char *)&value_hash, key_hash & 2 + MAP_INDEX, 2);
    memwrite(delete_buff, key_hash * MAX_LEN, MAX_LEN);
    memwrite(delete_buff, value_hash * MAX_LEN, MAX_LEN);
}
 
/*
1. delte의 3번까지 수행함
2. value id 값을 이용해 value 값을 가져와 return 함
*/
void get(unsigned char key_in[], unsigned char value_out[])
{
    unsigned short key_hash = find_str(key_in);
    unsigned short value_hash = 0;
    memread((unsigned char *)&value_hash, key_hash * 2 + MAP_INDEX, 2);
    
    memread(value_out, value_hash * MAX_LEN, MAX_LEN); // hash 값에서 12바이트를 곱하면 그 위치인가 봄
}
 
/*
1. delete의 3번까지 하되 key가 아닌 value 값으로 찾음
2. value의 id 값을 가지고 mapping tabble에서 key의 id를 찾음
3. key의 id를 이용해 index*12바이트를 하여 retrun 함
*/
void get_key(unsigned char value_in[], unsigned char key_out[])
{
    unsigned short value_hash = find_str(value_in);
    unsigned short value_find = 0;
    register int i = 0;
    for (i = 0; i < MAX_TABLE; i++) {
        memread((unsigned char *)&value_find, i * 2 + MAP_INDEX, 2);
        if (value_find == value_hash)
            break;
    }
    memread(key_out, i*MAX_LEN, MAX_LEN);
}
 
 
 
cs

 

-vita5000 code


'Computer Science' 카테고리의 다른 글

proxy server setting  (0) 2018.11.22
숫자 야구 게임  (0) 2018.11.21
IoT Database  (0) 2018.11.20
연락처 DB  (0) 2018.11.20
백준 트리 1991 트리 순회  (0) 2018.11.16

댓글