나 이거 오류 하나뜨는데
삭제알고리즘좀 고쳐줘;;
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
typedef struct BTree { // 트리 노드 구조체 선언
int lkey, rkey; // key 값
int tkey; // 임시 키값이 저장
int nkey; // 키값의 수
struct BTree *onechild, *twochild, *threechild; // 서브트리 노드
struct BTree *tempchild, *parent; // 노드 분할이 이루어질때 임시적으로 노드를 저장, 부모 노드
} treeNode;
////////////////////////////////////////////////////////////////////////////////
int isChild(treeNode *pNode);
treeNode *create(int data);
int searchData(treeNode *pnode, int data);
treeNode *searchNode(treeNode *pnode, int data);
treeNode *merger(treeNode *pNode);
treeNode *split(treeNode *pNode);
treeNode *remove(treeNode *root, int data);
treeNode *insert(treeNode *root, int data);
void displayData(treeNode *root, int data);
void treeDisplay(treeNode *pNode, int level);
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// 새노드를 생성한다.
treeNode *create(int data)
{
treeNode *temp; // 임시노드 생성
temp = (treeNode *)malloc(sizeof(treeNode)); // 트리 구조체를 동적 할당으로 메모리를 잡아준다.
temp->lkey = data; // 인자로 들어온 값을 왼쪽 키에 삽입한다.
temp->nkey = 1; // 키의 개수를 1개로 설정한다.
temp->twochild = NULL; // 서브트리는 NULL 값으로 설정한다
temp->onechild = NULL; // 서브트리는 NULL 값으로 설정한다..
temp->threechild = NULL; // 서브트리는 NULL 값으로 설정한다.
temp->tempchild = NULL; // 임시트리도 NULL 값으로 설정한다.
temp->parent = NULL; // 부모트리도 NULL 값으로 설정한다.
temp->rkey = temp->tkey = 0; // 오른쪽 key와 임시 키를 0으로 설정한다.
return temp; // 생성한 노드를 리턴한다.
}
// 자식 노드 존재 하는지 확인하는 함수
int isChild(treeNode *pNode)
{
if(pNode->onechild == NULL) // 첫번째 서브트리가 없으면 자식이 없는걸로 간주하고 0을 리턴
return 0;
if(pNode->twochild == NULL) // 두번째 부터는 무조건 자식이 있는 걸로 간주할 수 있다.
return 1;
if(pNode->threechild == NULL)
return 1;
if(pNode->tempchild == NULL)
return 1;
return 1;
}
// key 값을 검색한다음 트리 내부에 있으면 1을 리턴하고 없으면 0을 리턴한다.
int searchData(treeNode *pNode, int data)
{
if(pNode != NULL)
{
if(pNode->nkey == 0) // 현재 노드의 키의 개수가 0이란 말은 키가 하나도 없다는 말이어서 0을 리턴한다.
return 0;
if((pNode->nkey == 1) && (data == pNode->lkey))
return 1;
if((pNode->nkey == 2) && ((data == pNode->lkey) || (data == pNode->rkey)))
return 1;
if(data < pNode->lkey)
return searchData(pNode->onechild, data);
else if((pNode->nkey == 1) || ((pNode->nkey == 2) && (data < pNode->rkey)))
return searchData(pNode->twochild, data);
else if((pNode->nkey == 2) && (data > pNode->rkey))
return searchData(pNode->threechild, data);
else
return 0;
}
return 0;
}
// key값을 검색한 다음 트리 내부에 있으면 데이터가 들어있는 노드를 리턴하고 없으면 NULL을 리턴한다.
treeNode *searchNode(treeNode *pNode, int data)
{
if(pNode != NULL) // 현재 노드의 키의 개수가 0이란 말은 키가 하나도 없다는 말이어서 NULL을 리턴한다.
{
if(pNode->nkey == 0)
return NULL;
if((pNode->nkey == 1) && (data == pNode->lkey))
return pNode;
if((pNode->nkey == 2) && (data == pNode->lkey) || (data == pNode->rkey))
return pNode;
if(data < pNode->lkey)
return searchNode(pNode->onechild, data);
else if((pNode->nkey == 1) || ((pNode->nkey == 2) && (data < pNode->rkey)))
return searchNode(pNode->twochild, data);
else if((pNode->nkey == 2) && (data > pNode->rkey))
return searchNode(pNode->threechild, data);
else
return NULL;
}
return NULL;
}
// 특정 데이터 검색과 출력
void displayData(treeNode *root, int data)
{
treeNode *pNode; // 임의 노드 생성
pNode = (treeNode *)malloc(sizeof(treeNode));
pNode = root; // 인자값으로 받은 루트주소를 임의의 노드에 대입한다.
// key값이 있는지 확인한다음 참이면 값 을 출력한다.
if(searchData(pNode, data))
{
printf("\\n%d (을/를) 찾았습니다...\\n", data);
}
// 찾지 못할 경우 에러값 출력
else
{
printf("\\n%d (을/를) 찾을수 없습니다..\\n", data);
}
}
// 분할.. 데이터 삽입시 노드가 꽉차 있을때 실시한다.
treeNode *split(treeNode *pNode)
{
int one, two, three; // 임의의 변수 생성
treeNode *new1; // 분할시 작은 key값을 가진 노드를 대입
treeNode *new2; // 분할시 큰 key값을 가진 노드를 대입
treeNode *pTemp; // 임의 노드 생성
pTemp = (treeNode *)malloc(sizeof(treeNode));
one = pNode->lkey; // 분할시 3개의 key값중 가장 작은값을 대입
two = pNode->rkey; // 분할시 3개의 key값중 가장 중간값을 대입
three = pNode->tkey; // 분할시 3개의 key값중 가장 가장큰값을 대입
new1 = create(one); // 새로운 노드에 작은 key값을 대입
new2 = create(three); // 새로운 노드에 큰 key값을 대입
if (pNode->parent == NULL) // 분할이 발생한 노드의 부모가 없을경우이다. 즉 루트이다.
{
// 임의의 노드에 중간 key 값을 가지는 노드를 생성해서 대입
pTemp = create(two);
// 임의의 노드의 첫번째 서브 노드에 작은 key 값을 가지는 노드 대입
pTemp->onechild = new1;
// 임의의 노드의 두번째 서브 노드에 큰 key 값을 가지는노드 대입
pTemp->twochild = new2;
// 임의의 노드의 세번째 서브 노드와 부모를 가리키는 곳을 NULL 값 대입
pTemp->threechild = pTemp->parent = NULL;
}
// 현재 노드가 루트가 아닐 경우
else
{
// 임의의 노드에 분할한 노드의 부모 노드를 대입
pTemp = pNode->parent;
// 분할이 발생한 노드가 부모 노드의 첫번째 서브노드 일경우
if (pTemp->onechild == pNode)
{
// 부모노드의 임시 노드에 세번째 노드 대입
pTemp->tempchild = pTemp->threechild;
// 부모노드의 두번째 노드를 세번째에 대입
pTemp->threechild = pTemp->twochild;
// 부모노드의 첫번째 서브노드에 분할한 작은 노드 대입
pTemp->onechild = new1;
// 부모노드의 두번째 서브노드에 분할한 큰 노드 대입
pTemp->twochild = new2;
// 부모노드의 임시 key값에 오른쪽 key값 대입
pTemp->tkey = pTemp->rkey;
// 부모노드의 오른쪽 key값에 왼쪽 키값 대입
pTemp->rkey = pTemp->lkey;
// 부모노드의 중간 key값에 분할한 노드의 key중 중간값 대입
pTemp->lkey = two;
}
// 분할이 발생한 노드가 부모 노드의 두번째 서브노드 일경우
else if (pTemp->twochild == pNode)
{
// 부모노드의 두번째 서브노드에 분할한 작은 노드 대입
pTemp->twochild = new1;
// 부모노드의 임시 노드에 부모노드의 세번째 서브노드대입
pTemp->tempchild = pTemp->threechild;
// 부모노드의 세번째 서브노드에 분할한 큰노드 대입
pTemp->threechild = new2;
// 부모노드의 임시 key값에 큰 key값 대입
pTemp->tkey = pTemp->rkey;
// 부모노드의 오른쪽key값에 분할한 노드의 중간 key값 대입
pTemp->rkey = two;
}
// 분할이 발생한 노드가 부모 노드의 세번째 서브노드 일 경우
else if (pTemp->threechild == pNode)
{
pTemp->threechild = new1;
pTemp->tempchild = new2;
pTemp->tkey = two;
}
pTemp->nkey++; // 분할로 때문에 분할이 발생한 노드의 부모노드의 key 개수 1 증가
pNode->rkey = pNode->tkey;
pNode->nkey--; // 분할이 발생한 노드의 key 개수 1 감소
}
// 새롭게 생성된 자식노드의 부모노드를 지정해준다.
new1->parent = new2->parent = pTemp;
// 새롭게 생성된 자식노드의 세번째 서브노드와 임시노드를 NULL 로 세팅
new1->threechild = new1->tempchild = new2->threechild = new2->tempchild = NULL;
// 분할이 발생한 노드의 부모노드가 자식노드를 가지고 있을 경우
if (isChild(pTemp))
{
// 새롭게 생성된 자식노드에 분할이 발생한 노드의 자식노드를 연결한다.
new1->onechild = pNode->onechild;
new1->twochild = pNode->twochild;
new2->onechild = pNode->threechild;
new2->twochild = pNode->tempchild;
if (new1->onechild) // 연결된 자식노드의 부모노드를 지정해준다.
new1->onechild->parent = new1;
if (new1->twochild)
new1->twochild->parent = new1;
if (new2->onechild)
new2->onechild->parent = new2;
if (new2->twochild)
new2->twochild->parent = new2;
}
// 분할이 발생한 노드는 새롭게 생성된 노드로 분배가 모두 이루어졌으므로, 노드를 삭제시킨다.
pNode->onechild = pNode->twochild = pNode->threechild = pNode->tempchild = pNode->parent = NULL;
free(pNode);
// 임시노드가 있다면 다시 분열이 일어나야 하므노 분할함수인 split를 호출한다.
if (pTemp->tempchild)
{
return split(pTemp);
}
// 임시노드가 필요 없으므로 NULL로 세팅한다.
pTemp->tempchild = pNode->tempchild = NULL;
// root까지 올라가서 root를 return 한다.
while (pTemp->parent)
{
pTemp = pTemp->parent;
}
return pTemp;
}
// 합병
treeNode *merger(treeNode *pNode)
{
treeNode *pTemp = (treeNode *)malloc(sizeof(treeNode));
int nsub; // 서브 노드의 개수
// 현재 노드의 부모노드가 없을경우 즉 루트에서 언더플로우 발생할 경우이다.
if (pNode->parent == NULL)
{
if (pNode->onechild)
{
pNode->onechild->parent = NULL;
return pNode->onechild;
}
else
return NULL;
}
// 루트가 아닌 노드에서 언더플로우가 발생할 경우이다.
else
{
// pTemp는 언더플로우가 발생한 노드의 부모 노드로 설정한다.
pTemp = pNode->parent;
if (pTemp->onechild == pNode)
nsub = 1; // nsub = 1이란 첫번째 서브트리에서 언더플로우가 발생했다는 말이다.
else if (pTemp->twochild == pNode)
nsub = 2; // nsub = 2이란 첫번째 서브트리에서 언더플로우가 발생했다는 말이다.
else if (pTemp->threechild == pNode)
nsub = 3; // nsub = 3이란 첫번째 서브트리에서 언더플로우가 발생했다는 말이다.
else
printf("에러에용\\n");
// underflow 가 mchild 에서 발생하고 형제노드인 lchild가 2개의 value를 가지고 있을 경우
if ((nsub == 2) && (pTemp->onechild->nkey == 2))
{
pNode->lkey = pTemp->lkey;
pNode->nkey++;
pTemp->lkey = pTemp->onechild->rkey;
pTemp->onechild->nkey--;
pNode->twochild = pNode->onechild;
if (pTemp->onechild->threechild)
{
pNode->onechild = pTemp->onechild->threechild;
if(pNode->onechild)
pNode->onechild->parent = pNode;
}
else
{
pNode->onechild = pTemp->onechild->twochild;
if(pNode->onechild)
pNode->onechild->parent = pNode;
}
pTemp->onechild->threechild = NULL;
}
// 언더플로우가 2번째 서브노드에서 발생하고 시블링노드인 threechild가 2개의 key를 가지고 있을 경우
else if ((nsub == 2) && (pTemp->threechild) && (pTemp->threechild->nkey == 2))
{
pNode->lkey = pTemp->lkey;
pNode->nkey++;
pTemp->lkey = pTemp->threechild->lkey;
pTemp->threechild->nkey--;
if (pNode->twochild)
{
pNode->threechild = pTemp->threechild->onechild;
if (pNode->threechild)
pNode->threechild->parent = pNode;
}
else
{
pNode->twochild = pTemp->threechild->onechild;
if (pNode->twochild)
pNode->twochild->parent = pNode;
}
pTemp->threechild->onechild = pTemp->threechild->twochild;
pTemp->threechild->twochild = pTemp->threechild->threechild;
pTemp->threechild->threechild = NULL;
}
// 언더플로우가 1번째 서브노드에서 발생하고 시블링노드인 twochild가 2개의 key를 가지고 있을 경우
else if ((nsub == 1) && (pTemp->twochild) && (pTemp->twochild->nkey == 2))
{
pNode->lkey = pTemp->lkey;
pNode->nkey++;
pTemp->lkey = pTemp->twochild->lkey;
pTemp->twochild->lkey = pTemp->twochild->rkey;
pTemp->twochild->nkey--;
if (pNode->twochild)
{
pNode->threechild = pTemp->twochild->onechild;
if (pNode->threechild)
pNode->threechild->parent = pNode;
}
else
{
pNode->twochild = pTemp->twochild->onechild;
if (pNode->twochild)
pNode->twochild->parent = pNode;
}
pTemp->twochild->onechild = pTemp->twochild->twochild;
pTemp->twochild->twochild = pTemp->twochild->threechild;
pTemp->twochild->threechild = NULL;
}
// 언더플로우가 3번째 서브노드에서 발생하고 형제노드인 threechild가 2개의 key를 가지고 있을 경우
else if ((nsub == 3) && (pTemp->twochild->nkey == 2))
{
pNode->lkey = pTemp->rkey;
pNode->nkey++;
pTemp->rkey = pTemp->twochild->rkey;
pTemp->twochild->nkey--;
pNode->threechild = pNode->twochild;
pNode->twochild = pNode->onechild;
if(pTemp->twochild->threechild)
{
pNode->onechild = pTemp->twochild->threechild;
if (pNode->onechild)
pNode->onechild->parent = pNode;
}
else
{
pNode->onechild = pTemp->twochild->twochild;
if (pNode->onechild)
pNode->onechild->parent = pNode;
}
pTemp->twochild->threechild = NULL;
}
else // 위의 모든경우가 아니라면 합병이 발생한다.
{
switch(nsub)
{
// 언더플로우가 발생한 노드가 부모노드의 1번째 서브노드일 경우
case 1:
if (pTemp->twochild == 0)
printf("에러에용\\n");
pTemp->twochild->rkey = pTemp->twochild->lkey;
pTemp->twochild->lkey = pTemp->lkey;
pTemp->twochild->nkey++;
pTemp->lkey = pTemp->rkey;
pTemp->nkey--;
pTemp->twochild->threechild = pTemp->twochild->twochild;
pTemp->twochild->twochild = pTemp->twochild->onechild;
pTemp->twochild->onechild = pNode->onechild;
if (pTemp->twochild->onechild)
pTemp->twochild->onechild->parent = pTemp->twochild;
pTemp->onechild = pTemp->twochild;
pTemp->twochild = pTemp->threechild;
pTemp->threechild = 0;
break;
// 언더플로우가 발생한 노드가 부모노드의 2번째 서브노드일 경우
case 2:
pTemp->onechild->rkey = pTemp->lkey;
pTemp->onechild->nkey++;
pTemp->lkey = pTemp->rkey;
pTemp->nkey--;
if (pTemp->onechild->twochild)
{
pTemp->onechild->threechild = pNode->onechild;
if (pTemp->onechild->threechild)
pTemp->onechild->threechild->parent = pTemp->onechild;
}
else
{
pTemp->onechild->twochild = pNode->onechild;
if (pTemp->onechild->twochild)
pTemp->onechild->twochild->parent = pTemp->onechild;
}
pTemp->twochild = pTemp->threechild;
pTemp->threechild = NULL;
break;
// 언더플로우가 발생한 노드가 부모노드의 3번째 서브노드일 경우
case 3:
pTemp->twochild->rkey = pTemp->rkey;
pTemp->twochild->nkey++;
pTemp->nkey--;
if (pTemp->twochild->twochild)
{
pTemp->twochild->threechild = pNode->onechild;
if (pTemp->twochild->threechild)
pTemp->twochild->threechild->parent = pTemp->twochild;
}
else
{
pTemp->twochild->twochild = pNode->onechild;
if (pTemp->twochild->twochild)
pTemp->twochild->twochild->parent = pTemp->twochild;
}
pTemp->threechild = NULL;
break;
}
// 트리를 재구성 하다가 부모노드의 key개수가 0이되면 다시 merge를 재귀호출 한다.
if(pTemp->nkey == 0)
return (merger(pTemp));
}
}
// pTemp에 root노드 넣어준다음 pTemp가 root가되면 리턴한다.
while (pTemp->parent)
pTemp = pTemp->parent;
return pTemp;
}
// 데이터 삽입
treeNode *insert(treeNode *root, int data)
{
// 루트의 key가 0개일 경우 루트를 생성하고 key값을 대입한다. 즉 루트가 존재하지 않을경우.
if(root->nkey == 0)
{
root = create(data);
}
// 루트가 존재할경우.
else
{
// 임의의 노드 생성
treeNode *pNode;
pNode = (treeNode *)malloc(sizeof(treeNode));
pNode = root; // 루트를 임의의 노드로 대치
// 자식 노드가 존재할 경우, 삽입할 자식노드 위치 결정
while(isChild(pNode))
{
// 넣으려는 key 값이 lkey 값보다 작고 1번째 서브노드가 존재할 경우 1번째 서브노드에 삽입
if((data < pNode->lkey) && (pNode->onechild))
pNode = pNode->onechild;
// lkey 보다는 크고 3번째 서브노드가 존재하지 않을 경우 2번째 서브노드에 삽입
else if(pNode->threechild == NULL)
pNode = pNode->twochild;
// 3번째 서브노드가 존재하고 key가 rkey보다 작을 경우 2번째노드에 삽입
else if(data < pNode->rkey)
pNode = pNode->twochild;
// 위의 경우에 속하지 않을경우 3번째 노드에 삽입
else if(pNode->threechild != NULL)
pNode = pNode->threechild;
}
// 삽입하려는 위치의 노드의 key 개수가 1일경우
if(pNode->nkey == 1)
{
if(pNode->lkey <= data)
{
pNode->rkey = data;
pNode->nkey++;
}
else
{
pNode->rkey = pNode->lkey;
pNode->lkey = data;
pNode->nkey++;
}
}
// 삽입하려는 위치의 노드의 key 개수가 2인 경우
else
{
if (pNode->rkey <= data)
pNode->tkey = data;
else if (pNode->lkey <= data)
{
pNode->tkey = pNode->rkey;
pNode->rkey = data;
}
else {
pNode->tkey = pNode->rkey;
pNode->rkey = pNode->lkey;
pNode->lkey = data;
}
pNode->nkey++;
root = split(pNode); // 삽입하려는 위치의 key개수가 2개이므로 분할 한다.
}
}
return root;
}
// key 삭제
treeNode *remove(treeNode *root, int data) {
int temp;
treeNode *pNode = (treeNode *)malloc(sizeof(treeNode));
// key가 속해있는 노드를 찾아서 isNode 에 대입
treeNode *isNode = searchNode(root, data);
// 삭제할려는 key가 속해 있는 노드 즉, isNode 의 자식노드가 있을 경우
if(isChild(isNode)) {
if(isNode->lkey == data) // key값이 isNnode의 lkey
pNode = isNode->twochild;
else // key 값이 isNnode의 rkey
pNode = isNode->threechild;
while(pNode->onechild) // pNode은 pNode의 onechild의 단말노드
pNode = pNode->onechild;
if(isNode->lkey == data) { // isNode의 lkey가 삭제하고자하는 key 일 경우
temp = isNode->lkey;
isNode->lkey = pNode->lkey;
pNode->lkey = temp;
}
else {
temp = isNode->rkey;
isNode->rkey = pNode->lkey;
pNode->lkey = temp;
}
}
// isNode의 자식노드가 없을 경우
else
pNode = isNode; // pNode는 key가 속해있는 노드이다.
if(pNode->rkey == data) { // rkey일경우 key의 개수를 1 감소
pNode->rkey = 0;
pNode->nkey--;
}
else if(pNode->lkey == data) { // lkey일 경우 rkey를 lkey로 옮기고 key의 개수 1 감소
pNode->lkey = pNode->rkey;
pNode->rkey = 0;
pNode->nkey--;
}
if (pNode->nkey == 0) { // key의 개수가 0이면 트리합병 및 재 구축해준다.
root = merger(pNode);
}
return root;
}
// 트리 전체 보기
void treeDisplay(treeNode *pNode, int level)
{
int i;
if(pNode)
{
for(i = 0; i < level; i++)
printf("\\t");
if(isChild(pNode)) // 자식노드가 있을 경우
{
if(pNode->nkey == 2)
printf("( [%d] , [%d] :",pNode->lkey, pNode->rkey);
else
printf("( [%d] :", pNode->lkey);
}
else // 자식노드가 없을 경우
{
if(pNode->nkey == 2)
printf("( [%d] , [%d] )", pNode->lkey, pNode->rkey);
else
printf("( [%d] )",pNode->lkey);
}
printf("\\n");
treeDisplay(pNode->onechild, (level + 1)); // 왼쪽 자식노드로 재귀호출
treeDisplay(pNode->twochild, (level + 1)); // 중간 자식노드로 재귀호출
treeDisplay(pNode->threechild, (level + 1)); // 오른쪽 자식노드로 재귀호출
}
}
///////////////////////////////////////////////////////////////////////////////
int main(void) { //메인메뉴
char end[1], datach[1];
int status, data, menu=0;
// 루트 노드 생성 및 초기화
treeNode *root;
root = (treeNode *)malloc(sizeof(treeNode));
root->nkey = root->lkey = root->rkey = root->tkey = 0;
root->onechild = root->twochild = root->threechild = root->tempchild = root->parent = NULL;
while(menu != 5){
fflush(stdin);
printf("===메뉴===\\n");
printf("1. 삽입\\n");
printf("2. 삭제\\n");
printf("3. 검색\\n");
printf("4. 보기\\n");
printf("5. 종료\\n");
printf("원하시는 메뉴를 고르세요 : ");
scanf("%d",&menu);
switch(menu) {
case 1:
printf("Inserting Data : ");
gets(datach);
fflush(stdin);
data = atoi(datach);
if(1 <= data && data <= 100) {
if(searchData(root, data)) {
printf("\\n%d (은/는) 이미 저장되어 있습니다.\\n", data);
getch();
fflush(stdin);
break;
}
else {
root = insert(root, data);
printf("\\n%d (이/가) 저장되었습니다.\\n", data);
getch();
fflush(stdin);
}
}
else {
printf("\\n잘못 입력하셨습니다.\\n\\n1~100 사이의 숫자를 입력 하세요.\\n");
getch();
fflush(stdin);
}
break;
case 2:
printf("Deleting Data : ");
gets(datach);
fflush(stdin);
data = atoi(datach);
if(1 <= data && data <= 100) {
if(searchData(root, data)) {
root = remove(root, data);
printf("\\n%d (을/를) 삭제 했습니다.\\n", data);
getch();
fflush(stdin);
}
else {
printf("\\n%d (은/는) BTree상에 존재 하지 않습니다.\\n", data);
getch();
fflush(stdin);
}
}
else {
printf("\\n잘못 입력하셨습니다.\\n\\n1~100 사이의 숫자를 입력 하세요.\\n");
getch();
fflush(stdin);
}
break;
case 3:
printf("Finding Data : ");
gets(datach);
fflush(stdin);
data = atoi(datach);
if(1 <= data && data <= 100) {
displayData(root, data);
getch();
fflush(stdin);
}
else {
printf("\\n잘못 입력하셨습니다.\\n\\n1~100 사이의 숫자를 입력 하세요.\\n");
getch();
fflush(stdin);
}
break;
case 4:
printf("\\nBtree의 현재 상태를 보여줍니다.\\n\\n");
treeDisplay(root, 0);
printf("\\n");
getch();
fflush(stdin);
break;
case 5:
printf("종료합니다.\\n");
break;
default:
printf("잘못입력하였습니다.\\n");
}
}
return 0;
}
댓글 영역
획득법
① NFT 발행
작성한 게시물을 NFT로 발행하면 일주일 동안 사용할 수 있습니다. (최초 1회)
② NFT 구매
다른 이용자의 NFT를 구매하면 한 달 동안 사용할 수 있습니다. (구매 시마다 갱신)
사용법
디시콘에서지갑연결시 바로 사용 가능합니다.