#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NO 1
#define NAME 2

typedef enum{
    Occupied,Empty,Deleted
} Status;

typedef struct{
    int no;
    char name[10];
}Data;

typedef struct{
    Data data;
    Status stat;
} Bucket;

typedef struct{
    int size;
    Bucket *table;
} Hash;

int hash(int key){
    return(key%13);
}

int rehash(int key){
    return((key+1)%13);
}

void SetBucket(Bucket *n, Data x, Status stat){
    n->data=x;
    n->stat=stat;
}

int InitHash(Hash *h,int size){
    int i;
    h->size = 0;
    if ((h->table = calloc(size, sizeof(Bucket))) == NULL) {
        return 0;
    }
    h->size = size;
    for (i = 0; i < size; i++) {
        h->table[i].stat = Empty;
    }
    return 1;
}

void TermHash(Hash *h){
    free(h->table);
}

Bucket *SearchBucket(Hash *h, Data *x){
    int i;
    int key = hash(x->no);
    Bucket *p = &h->table[key];
    for (i = 0; p->stat != Empty && i < h->size; i++) {
        if (p->stat == Occupied && p->data.no == x->no)
            return p;
        key = rehash(key);
        p = &h->table[key];
    }
    return NULL;
}

int InsertBucket(Hash *h, Data *x){
    int i;
    int key = hash(x->no);
    Bucket *p = &h->table[key];
    if (SearchBucket(h, x))
        return 1;
    for (i = 0; i < h->size; i++) {
        if (p->stat == Empty || p->stat == Deleted){
            SetBucket(p, *x, Occupied);
            return 0;
        }
        key = rehash(key);
        p = &h->table[key];
    }
    return 2;
}

int DeleteBucket(Hash *h,Data *x){
    Bucket *p = SearchBucket(h, x);
    if (p == NULL)
        return 1;
    p->stat = Deleted;
    return 0;
}

void PrintData(Data x){
    printf("%d (%s)\n", x.no, x.name);
}

void DumpHash(Hash *h){
    int i;
    for (i = 0; i < h->size; i++) {
        printf("%02d :", i);
        switch (h->table[i].stat) {
            case Occupied : PrintData(h->table[i].data);break;//////////////////
            case Empty :    printf("--未登録--\n");break;
            case Deleted :  printf("--削除済--\n");break;
        }
    }
}

//Data Read(char *message,int sw){//////////////////
//}                               //////////////////

int main(){
    int i, result, flag = 0;
    Hash hash;
    Data x;
    Bucket *temp;
    InitHash(&hash, 13);
    while(flag != 1) {
        printf("１．追加　２．削除　３．探索　４．ダンプ　５．終了\n");
        printf("処理を選択してください");
        scanf("%d", &i);
        switch (i) {
            case 1:
                printf("追加するデータを入力してください\n");
                printf("番号");
                scanf("%d",&x.no);
                printf("名前");
                scanf("%s", x.name);
                result=InsertBucket(&hash, &x);

                if (result != 0) {
                    printf("追加に失敗しました(%s) \n",(result==1) ? "登録済み":"満杯");
                }
                break;
            case 2:
                printf("削除するデータを入力してください\n");
                printf("番号");
                scanf("%d", &x.no);
                result = DeleteBucket(&hash,&x);
                if(result == 1) {
                    printf("その番号はありません\n");
                }
                break;
            case 3:
                printf("番号");
                scanf("%d", &x.no);
                temp = SearchBucket(&hash, &x);//////////////////
                if (temp == NULL){
                    printf("探査に失敗しました\n");
                } else {
                    printf("探査に成功しました\n");
                    PrintData(temp->data);
                }
                break;
            case 4:
                DumpHash(&hash);
                break;
            case 5:
                flag = 1;
                break;
            default:
                printf("正しい数値を入力してください\n");
                break;
        }
    }
    TermHash(&hash);
    return 0;
}
