SyntaxHighlighter.all();

안녕하세요 ㅎㅎ 


많이 사용하는 자료구조중 하나인 tree 구조의 순회법인 이진탐색을 이용해서 메모장을 만들어 보았습니다.



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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
// 이진 탐색 트리를 이용한 메모 저장 프로그램.
#include <stdio.h>
#include <stdlib.h> // malloc
#include <string.h> // srcmp
#include <conio.h>  // _getch()
#define MAX_NAME 50   // 최대 제목 길이 50
#define MAX_TEXT 300  // 최대 내용 길이 300
 
/** 메모 데이터 정의(데이터노드) **/
typedef struct DataType
{
    char Name[MAX_NAME]; // 메모의 제목
    char Text[MAX_TEXT]; // 메모의 내용
}DataType;
 
/** 메모장 구조 정의(트리) **/
typedef struct MyMemo {
    DataType Memo;
    struct MyMemo* left;
    struct MyMemo* right;
}MyMemo;
 
/** 문자열 비교 함수 **/
int Compare(DataType A, DataType B) //strcmp 를 한번에 할수 없기 때문에 비교결과를 반환하는 함수를 만듦.
{
    return strcmp(A.Name, B.Name); // 각 문자열의 아스키코드 값을 비교
}
 
/** 메모 삽입 함수 **/
void AddMemo(MyMemo** Root, DataType Memo)
{
    MyMemo* Current = (*Root); // 현재노드. 처음엔 루트를 넣음
    MyMemo* Parent = NULL;     // 부모노드
    MyMemo* NewNode = NULL;    // 새로운 노드
 
    while (Current != NULL) // 자식이 없는 노드를 찾는 알고리즘
    {
        if (Compare(Memo, Current->Memo) == 0)
        {
            printf("  > 메모 생성 실패. 동일한 제목이 존재합니다.\n");
            return;
        }
        Parent = Current;
        if (Compare(Memo, Current->Memo) < 0//작으면 왼쪽
            Current = Current->left;
        else
            Current = Current->right;  // 크면 오른쪽
    }
 
    NewNode = (MyMemo*)malloc(sizeof(MyMemo)); // 새로운 노드 생성!
    if (NewNode == NULL)
        return;
    NewNode->Memo = Memo;
    NewNode->left = NULL;
    NewNode->right = NULL;
 
    if (Parent != NULL) // 위 알고리즘에서 부모를 찾은 경우
    {
        if (Compare(Memo, Parent->Memo) < 0)
            Parent->left = NewNode;
        else
            Parent->right = NewNode;
    }
    else // 부모노드를 못찾은 경우는 새 노드가 루트가 된다.
        *Root = NewNode;
}
 
/** 메모 삭제 함수 **/
void DeleteMemo(MyMemo** Root, DataType Target) // 아니왜삭제가안돼개짜증나게
{
 
    MyMemo* Current = (*Root);
    MyMemo* Parent = NULL;
    MyMemo* Child;
    MyMemo* succ;
    MyMemo* succ_p;
 
    while (Current != NULL && Compare(Current->Memo, Target) != 0// 타켓 노드의 바로 위까지 검색!
    {
        Parent = Current; // 삭제하고자 하는 노드의 부모를 찾는다.
 
        if (Compare(Current->Memo, Target) < 0// 노드가 비교대상 보다 작으면 -1, 크면 1
            Current = Current->right;
        else
            Current = Current->left;
    }
    if (Current == NULL) {// 예외
        //printf(" :: 메모가 존재하지 않습니다!\n\n");
        return;
    }
 
    // 자식 노드가 없는 경우 -> Parent 는 Current 의 부모노드이다.
    if ((Current->left == NULL) && (Current->right == NULL)) //and연산 -> 지우고자 하는 Current 노드의 자식이 없는 경우.
    {
        if (Parent != NULL)
        {
            if (Parent->left == Current)
                Parent->left = NULL;
            else
                Parent->right = NULL;
        }
        else // 부모 노드가 없으므로 루트노드이다.
            *Root = NULL;
    }
 
    //하나의 자식 노드가 있는 경우
    else if ((Current->left == NULL) || (Current->right == NULL)) //or연산
    {
        if (Current->left != NULL) // 왼쪽, 오른쪽 노드 중 존재하는 노드를 자식으로 대입.
            Child = Current->left;
        else
            Child = Current->right;
 
        if (Parent != NULL)
        {
            if (Parent->left == Current) // 현재 노드의 자식을 부모에게 연결한다.
                Parent->left = Child;
            else
                Parent->right = Child;
        }
        else
            *Root = Child; // 부모가 없는 경우 자식이 루트로 된다.
    }
 
    // 자식이 2개인 경우. 
    else
    {
        succ_p = Current;
        succ = Current->right;
 
        while (succ->left != NULL)
        {
            succ_p = succ;
            succ = succ->left;
        }
        if (succ_p->left = succ)
            succ_p->left = succ->right;
        else
            succ_p->right = succ->right;
 
        Current->Memo = succ->Memo;
        Current = succ;
    }
    printf("\n * ─────────────────── *\n");
    printf(" :: %s > 삭제완료 \n\n", Current->Memo.Name);
    free(Current); // 노드 공간 반환.
}
 
/** 전체 메모 출력(제목만 출력됨) **/
int PrintMemo(MyMemo* Root)
{
    MyMemo* Current = Root;
    if (Current != NULL)
    {
        printf(" > %s\n", Current->Memo.Name); // 전위순회
 
        if (Current->left != NULL)
            PrintMemo(Current->left);
        if (Current->right != NULL)
            PrintMemo(Current->right);
    }
    else
    {
        printf(" > 메모가 존재하지 않습니다!\n\n");
        return 0;
    }
    return 1;
}
 
/** 전위 출력**/
void Preorder(MyMemo* Root)
{
    MyMemo* Current = Root;
    if (Current != NULL)
    {
        printf(" > %s\n", Current->Memo.Name);
        Preorder(Current->left);
        Preorder(Current->right);
    }
}
/** 중위 출력**/
void Inorder(MyMemo* Root)
{
    MyMemo* Current = Root;
    if (Current != NULL)
    {
        Preorder(Current->left);
        printf(" > %s\n", Current->Memo.Name);
        Preorder(Current->right);
    }
}
/** 후위 출력**/
void Postorder(MyMemo* Root)
{
    MyMemo* Current = Root;
    if (Current != NULL)
    {
        Preorder(Current->left);
        Preorder(Current->right);
        printf(" > %s\n", Current->Memo.Name);
    }
}
 
/** 메모 검색(제목입력 -> 본문출력) **/
MyMemo* SerchMemo(MyMemo* Root, DataType Target)
{
    MyMemo* Current = Root;
 
    if (Root = NULL)
        return Root;
 
    while (Current != NULL)
    {
        switch (Compare(Current->Memo, Target))
        {
        case 1:
            Current = Current->left; //노드 값이 더 크면 왼쪽.
            break;
        case 0:
            return Current;
            break;
        case -1:
            Current = Current->right; // 노드값이 더 작으면 오른쪽.
            break;
        }
    }
}
 
/** 메모 개수 카운트 **/
int CountMemo(MyMemo* Root)
{
    MyMemo* Current = Root;
    int Count = 0;
 
    if (Current != NULL)
        Count = + CountMemo(Current->left) + CountMemo(Current->right);
 
    return Count;
}
 
/** 화면 정리 대기 **/
void CLS()
{
    printf("\n\n 메뉴로 돌아가려면 Enter 입력.");
    _getch(); // Enter 을 입력받으면 화면을 지운다.
    system("cls"); // 화면을 지우는 명령어.
}
 
int main(void)
{
 
    DataType MemoData;   // 메모의 데이터
    MyMemo* Root = NULL; // 트리 생성 
    MyMemo* Temp;        // 메모의 데이터를 임시 저장하는 노드.
    FILE* file;
    int UserSelect, exit = 0// 스위치 변수, 메뉴 종료 변수.
    while (exit != 1)
    {
        fflush(stdin); // 버퍼비움.
        printf(" *────  메모장 ────*\n");
        printf("│    1.메모작성    │\n");
        printf("│    2.메모삭제    │\n");
        printf("│    3.메모검색    │\n");
        printf("│    4.전체메모    │\n");
        printf("│    5.메모개수    │\n");
        printf("│    6.순회출력    │\n");
        printf("│    7.내보내기    │\n");
        printf("│    8.종료        │\n");
        printf(" *─────────────────*\n");
        printf(" :: 명령입력 > ");
        scanf_s("%d"&UserSelect);
        putchar('\n');
        switch (UserSelect)
        {
        case 1// 메모작성
            getchar(); // 버퍼를 비워준다.
            printf(" :: 메모를 작성합니다. \n\n");
            printf(" :: 제목 > ");
            gets(MemoData.Name);
            printf("\n :: 내용 > ");
            gets(MemoData.Text);
            AddMemo(&Root, MemoData);
            printf(" * ─────────────────── *\n");
            printf(" :: 제목 >   [%s]\n\n", MemoData.Name);
            printf(" :: 내용 >   %s", MemoData.Text);
            CLS();
            break;
        case 2// 메모 삭제
            getchar();
            printf("\n :: 메모를 삭제합니다. \n\n");
            if (PrintMemo(Root))
            {
                printf("\n :: 제목 > ");
                gets(MemoData.Name);
                DeleteMemo(&Root, MemoData);
            }
            CLS();
            break;
        case 3// 메모 검색(내용보기)
            getchar();
            if (PrintMemo(Root)) // PrintMemo -> 보여줄 메모가 있으면 1을 반환. 없으면 0을 반환.
            {// 검색 전 모든 메모를 보여준다.
                printf("\n :: 검색할 메모의 제목 입력 > ");
                gets(MemoData.Name);
                Temp = SerchMemo(Root, MemoData);
                if (Temp != NULL) //예외처리 조건문. 함수에서 오류메세지를 빼냄.
                {
                    printf("\n * ────  %s ──── *\n", Temp->Memo.Name);
                    printf(" %s\n\n", Temp->Memo.Text);
                }
            }
            CLS();
            break;
        case 4// 메모 전체 출력
            getchar();
            PrintMemo(Root);
            CLS();
            break;
        case 5// 메모 개수 카운트
            getchar();
            printf(" :: 메모의 개수 > %d", CountMemo(Root));
            CLS();
            break;
        case 6// 출력 순회 변경
            getchar();
            printf(" *───  출력순회 ───*\n");
            printf("  :: 1.전위순회\n");
            printf("  :: 2.중위순회\n");
            printf("  :: 3.후위순회\n");
            printf(" *─────────────────*\n");
            printf(" :: 명령입력 > ");
            scanf("%d"&UserSelect);
            putchar('\n');
            if (UserSelect == 1)
                Preorder(Root);
            else if (UserSelect == 2)
                Inorder(Root);
            else if (UserSelect == 3)
                Postorder(Root);
            else
                printf(" :: 올바른 메뉴를 입력하세요!\n");
            CLS();
            break;
        case 7// 파일 출력
            getchar();
            if (PrintMemo(Root)) 
            {
                printf("\n :: 파일로 만들 메모의 제목 입력 > ");
                gets(MemoData.Name);
                Temp = SerchMemo(Root, MemoData);
                if (Temp != NULL)
                {
                    file = fopen(Temp->Memo.Name, "w");
                    fprintf(file,Temp->Memo.Text);
                    printf("\n :: %s < 저장성공!\n",Temp->Memo.Name);
                    fclose(file);
                }
                else
                    printf(" :: 내용이 없습니다!\n");
            }
            CLS();
            break;
        case 8// 종료
            getchar();
            printf(" :: 프로그램을 종료합니다. \n\n");
            exit = 1;
            return 0;
        default// 예외
            getchar();
            printf(" :: 올바른 메뉴를 입력하세요!\n");
            CLS();
            break;
        }
    }
}
cs

코드는 대부분 주석을 달아놓아서 이해가 안되시는 부분은 없을거라 생각합니다.


제가 공부를 더 해서 코드던져놓기 말고 자료구조에 대해 포스팅하는 기회도 생기면 좋겠습니다.  ㅎㅎ 

반응형

[블록체인] Linux 에서 Electroneum node 설치하기 -1 : https://good-coding.tistory.com/12


이전에 설치했던 Electroneum 을 실행하고 블록을 synchronization 하는 과정과 wallet 실행 후 지갑주소 발행까지 해보도록 하겠습니다.


일렉트로니움을 설치한 폴더에서 build -> release -> bin 폴더로 이동합니다.


1
2
3
4
5
cd build
cd release
cd bin
 
./electroneumd
cs



이후 실행파일인 electroneumd 를 실행합니다.


그러면 daemon 이 실행되며 일렉트로니움 네트워크에 블록들을 동기화하기 시작합니다. 



아래와 같이 블록들을 다운받게 되는데, 대부분의 블록체인이 synchronization 과정을 거쳐야만 노드로서 인정받고 활동할 수 있습니다.


이 과정은 상당히 오래걸리며 블록체인이 해결해야할 과제중 하나라고 생각합니다ㅜㅜ. 저도 테스트용 리눅스로 설치를 했기 때문에 모든 블록을 동기화하


기까지 얼마나 걸리는지는 실험해 보지 못했지만 몇일 ~ 1주일 정도까지 걸리는 것으로 알고 있습니다.


블록체인 네트워크든 사람이든 어디선가 인정받고 살아가려면 험난한 사회화 과정을 거쳐야 한다는 점을 간접적으로나마 느끼는 순간입니다.


이러한 이유로 백그라운드에서 작업을 해주시면 되겠습니다.



* 백그라운드 실행


1
2
3
ctrl + z 
jobs
bg %1 (electroeumd 의 프로세스 번호)
cs

동기화 되는 동안 저희는 일렉트로니움 지갑을 만들어 보겠습니다.

우선 같은 폴더에서 electroneum-wallet-cli 를 실행합니다. 

지갑 이름, 비밀번호, 비밀번호 확인, 언어선택 순으로 진행이 됩니다. 


저는 당연히 1 : English 로 선택을 했습니다. 대부분의 프로그램들에서 한국어도 볼 수 있으면 좋겠어요 ㅜㅜ


해당 과정을 마치면 아래와 같이 지갑 주소를 얻게됩니다.



지갑이 실행된 상태에서 help 명령어를 입력하면 다양한 지갑의 명령어를 볼 수 있습니다.


저는 balance 명령어를 실행해서 현재 잔고를 확인해보겠습니다.



따흑 ㅜㅜ 0원이네요... 당연합니다 아직 동기화도 되지 않았기 때문이요 ㅎㅎ (no daemon 상태)

* 참고로 ETN은 일정 단위의 ETN이 모이면 지급이 된다고 합니다. 즉 unlocked balance 는 당장 사용할 수 없는 자산입니다.


기회가 된다면 직접 리눅스에서 채굴을 하여 자산이 늘어나는 것을 보여드리고 싶지만 ㅎㅎ.. 가난한 제 pc환경에서는 벅차서 아쉽습니다.


다음 포스팅에는 직접 암호화폐를 간단하게 만들어 보는 내용을 다루고자 합니다. 감사합니다.

반응형


이번 포스팅에서는 이전에 소개했던 암호화폐 일렉트로니움을 


실제 리눅스 환경에서 설치 후 구동하는 방법을 소개하겠습니다. 


1. VirtualBox 설정의 권장사양


18-07-05 기준 일렉트로니움의 블록 길이는 약 350,000개 입니다. 


여유있게 50GB 정도 공간을 할당해 주시면 될 것 같습니다. (테스트는 해보지 못했습니다.)


메모리는 4GB, 코어는 3개 정도 할당해 주시면 되겠습니다.



2. 필요한 패키지 다운로드


우선 구동에 필요한 패키지를 다운로드합니다. 


사실 모든 패키지가 필요하지는 않은 것으로 보이나 개발팀이 권장하는 사항이니 만큼 모든 기능을 사용하려면 설치하는것이 좋아보입니다.


아래 사진에 패키지들이 어떤 것인지 설명되어 있으니 파악하시면 되겠습니다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sudo apt-get update
sudo apt-get upgrade

sudo apt-get install git
sudo apt-get install vim
 
sudo apt-get install bulid-essential
sudo apt-get install cmake
sudo apt-get install pkg-config
sudo apt-get install libboost-all-dev
sudo apt-get install libssl-dev
sudo apt-get install libunbound-dev
sudo apt-get install libminiupnpc-dev
sudo apt-get install libunwind8-dev
sudo apt-get install liblzma-dev
sudo apt-get install libldns-dev
sudo apt-get install libexpat1-dev
sudo apt-get install libgtest-dev
sudo apt-get install doxygen
sudo apt-get install graphviz
cs


설치과정에서 git 과 vi에디터가 필요함으로 함께 설치해 주시면 됩니다 ㅎㅎ


3. 프로젝트 소스 다운로드 및 컴파일

이후 폴더를 만들어 줍니다. 저는 downloads 라고 하였는데 이름은 딱히 상관없습니다.

해당 폴더로 이동하신 뒤, git 주소로 일렉트로니움 소스를 가져옵니다.


1
2
3
4
5
6
mkdir /downloads
cd /downloads
git clone https://github.com/electroneum/electroneum
 
cd /electroneum
make 
cs


위의 명령어를 실행하면 downloads 폴더에 프로젝트 파일이 복사됩니다.

이후 downloads 폴더 안에 electroneum 폴더로 이동하시면 아래와 같이 Makefile 이 있습니다. 


make 해 주시면 25분정도 컴파일이 되는데 make -j<number of threads> 로 스레드를 여러개로 수행하면 

좀 더 빠르게 진행됩니다.  ex) make -j3

* 컴파일이 완료된 모습


4. 오류 해결


컴파일 도중 터미널 창이 멈추고 반응이 없는 경우가 있습니다.

해당 소스를 컴파일 하기 위해서는 ubuntu-64bit 환경에서 테스트 해본 결과 메모리가 4GB 이상으로 여유가 있는 상태어야 합니다.

메모리가 부족한 경우 (VirtualBox 의 기본설정 메모리는 1GB) 설정에서 메모리를 더 할당해 주신 후, 재부팅 해주시면 됩니다.

다른 이슈가 발생할 경우 https://github.com/electroneum/electroneum/issues 에서 찾아보시거나 댓글로 남겨 주세요.

                                         

다음 포스팅에서는 wallet 실행과 메인넷 동기화를 진행하겠습니다.

[블록체인] Linux 에서 Electroneum node 설치하기 -2 : https://good-coding.tistory.com/13


반응형

+ Recent posts