무슨 일로 C 하셨습니까?

[C] 자료구조::딕셔너리 (Dictionary) 본문

C - 이걸 굳이?/유틸리티

[C] 자료구조::딕셔너리 (Dictionary)

OJJJ 2020. 10. 13. 23:18

파이썬을 사용하다보면 은근히 많이 사용되는게 바로 딕셔너리다

 

key - value 로 값을 접근하고 저장할 수 있다는 점이 상당히 매력적이다

 

그런 매력적인 자료형을 C에서 사용하지 아니할 수 없다 

 

고로 구현해보자


 

typedef struct _DICTIONARY {
    char* key;
    void* value;
    struct _DICTIONARY* link;

}_dictionary;

typedef struct DICTIONARY {
    int count;
    struct _DICTIONARY* head;
}dictionary;

우선 구조체 부터 만들면 다음과 같다

 

전체적인 부분은 연결 리스트와 동일하나

value 값으로 문자열 뿐만아니라 숫자 다른 구조체 등 

여러 자료형을 동시에 받을 수 있도록 void형 포인터를 사용해보겠다

 


연결 리스트 때 데이터 확인하는데 고생한 기억이 있기 때문에

 

이번엔 출력함수 부터 구현하겠다

void DICTIONARY_Show(dictionary dic) {
    _dictionary* temp = dic.head;
    int i = 0;

    printf("--- total count : %d\n", dic.count);
    while (temp != NULL) {
        printf("[%d] %s\n", i, temp->key);
        i++; temp = temp->link;
    }
}

value 값엔 어떠한 자료형의 데이터가 들어갈지 모르기 때문에

 

따로 출력은 하지 않겠다


그 다음은 데이터 추가 함수다

 

int DICTIONARY_Add(dictionary* head, char* key, void* value) {
    return true;
}

keyvalue를 매개변수로 전달해서 입력해주면 되겠다.

 

value를 제외하면 linked list의 함수와 크게 다를 것이 없으니

    _dictionary* temp = head->head;

    while (1) {
        // 헤더가 비었을 때
        if (head->count == 0/*temp == NULL*/) {
            temp = (_dictionary*)malloc(sizeof(_dictionary));
            temp->key = key;
            temp->link = NULL;
            head->head = temp;
            break;
        }

        // 헤더(현재 노드)가 마지막 일때
        else if (temp->link == NULL) {
            temp->link = (_dictionary*)malloc(sizeof(_dictionary));
            temp->link->key = key;
            temp->link->link = NULL;
            break;
        }

        // 다음 노드가 존재할 때
        else {
            temp = temp->link;
        }
    }
    head->count++;
    return true;

이름만 조금 바꿔서 똑같이 사용하겠다.

 

다만 추가로

value값을 추가해주며

key 값이 기존에 존재할 경우 예외처리를 해주면 된다.

 

      	// 현재 노드의 키가 새로 추가하려는 키와 같을 때
        if (StringCompare(temp->key, key) == COMPARE_SAME) {
            return false;
        }
        
        // value 값을 추가하는 코드
        temp->value = value;

위 두 코드를 적절히 배치시켜주면 되겠다.

 

int DICTIONARY_Add(dictionary* head, char* key, void* value) {
    _dictionary* temp = head->head;

    while (1) {
        // 헤더가 비었을 때
        if (head->count == 0/*temp == NULL*/) {
            temp = (_dictionary*)malloc(sizeof(_dictionary));
            //temp->key = StringAdd1("", key);
            temp->key = key;
            temp->value = value;
            temp->link = NULL;
            head->head = temp;
            break;
        }

        // 현재 노드의 키가 새로 추가하려는 키와 같을 때
        else if (StringCompare(temp->key, key) == COMPARE_SAME) {
            return false;
        }

        // 헤더(현재 노드)가 마지막 일때
        else if (temp->link == NULL) {
            temp->link = (_dictionary*)malloc(sizeof(_dictionary));
            //temp->link->key = StringAdd1("", key);
            temp->link->key = key;
            temp->link->value = value;
            temp->link->link = NULL;
            break;
        }

        // 다음 노드가 존재할 때
        else {
            temp = temp->link;
        }
    }
    head->count++;
    return true;
}

드디어 false 를 사용할 수 있게 되었다.


 

void main() {
    dictionary dic;
    DICTIONARY_Init(&dic);
    
    DICTIONARY_Add(&dic, "key1", "value2");
    DICTIONARY_Add(&dic, "key2", "value1");
    DICTIONARY_Show(dic);
    
}

각 함수가 잘 돌아가는지 테스트 해보자

 

Comments