SyntaxHighlighter.all();

피보나치 수열

F(n) = F(n-1) + F(n-2)

 

1. recursive를 이용한 구현

재귀호출을 이용하면 간단하게 구현할 수 있지만, n이 커질수록 연산량이 크게 증가한다. 

시간복잡도 : O(2^n) 

 

2. memoization을 이용한 구현

연산 결과를 저장하는 배열이 필요하지만, 재귀적 구현에 비해 월등히 빠른 속도를 낼 수 있다.

시간복잡도 : O(n) 

3. 간단한 성능 비교

* 15에 대한 피보나치 수를 구하는 실험 진행

recursive 기반 알고리즘은 180,428 cycle이 소요됨

memoization 기반 알고리즘은 6148 cycle이 소요됨

 

memoization 기법이 약 2900% 효율적

* CPU 성능이나 주어진 수에 따라 차이가 있을 수 있습니다.

반응형

1) 1은 소수가 아님

2) 소수인지 판단할 수 param을 2부터 param-1까지 나누어봄

    한번이라도 나머지가 0이면 param은 소수가 아님 

 

반응형

greatest common divisor algorithm in C

 

>> (u, v)

1) u가 v보다 크면 v와 u를 바꾼다. (음수 방지)

2) u = u - v

3) u == 0 이면, v가 최대공약수

   아니라면 1)로 돌아감

 

 

반응형

이어서 멀티 쓰레드 채팅프로그램의 chat_server.c 입니다.


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
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<pthread.h>
#include<time.h>
 
#define BUF_SIZE 100
#define MAX_CLNT 100
#define MAX_IP 30
 
void * handle_clnt(void *arg);
void send_msg(char *msg, int len);
void error_handling(char *msg);
char* serverState(int count);
void menu(char port[]);
 
 
/****************************/
 
int clnt_cnt=0;
int clnt_socks[MAX_CLNT];
pthread_mutex_t mutx;
 
int main(int argc, char *argv[])
{
    int serv_sock, clnt_sock;
    struct sockaddr_in serv_adr, clnt_adr;
    int clnt_adr_sz;
    pthread_t t_id;
 
    /** time log **/
    struct tm *t;
    time_t timer = time(NULL);
    t=localtime(&timer);
 
    if (argc != 2)
    {
        printf(" Usage : %s <port>\n", argv[0]);
        exit(1);
    }
 
    menu(argv[1]);
 
    pthread_mutex_init(&mutx, NULL);
    serv_sock=socket(PF_INET, SOCK_STREAM, 0);
    
    memset(&serv_adr, 0sizeof(serv_adr));
    serv_adr.sin_family=AF_INET;
    serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
    serv_adr.sin_port=htons(atoi(argv[1]));
 
    if (bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
        error_handling("bind() error");
    if (listen(serv_sock, 5)==-1)
        error_handling("listen() error");
 
    while(1)
    {
        t=localtime(&timer);
        clnt_adr_sz=sizeof(clnt_adr);
        clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);
 
        pthread_mutex_lock(&mutx);
        clnt_socks[clnt_cnt++]=clnt_sock;
        pthread_mutex_unlock(&mutx);
 
        pthread_create(&t_id, NULL, handle_clnt, (void*)&clnt_sock);
        pthread_detach(t_id);
        printf(" Connceted client IP : %s ", inet_ntoa(clnt_adr.sin_addr));
        printf("(%d-%d-%d %d:%d)\n", t->tm_year+1900, t->tm_mon+1, t->tm_mday,
        t->tm_hour, t->tm_min);
        printf(" chatter (%d/100)\n", clnt_cnt);
    }
    close(serv_sock);
    return 0;
}
 
void *handle_clnt(void *arg)
{
    int clnt_sock=*((int*)arg);
    int str_len=0, i;
    char msg[BUF_SIZE];
 
    while((str_len=read(clnt_sock, msg, sizeof(msg)))!=0)
        send_msg(msg, str_len);
 
    // remove disconnected client
    pthread_mutex_lock(&mutx);
    for (i=0; i<clnt_cnt; i++)
    {
        if (clnt_sock==clnt_socks[i])
        {
            while(i++<clnt_cnt-1)
                clnt_socks[i]=clnt_socks[i+1];
            break;
        }
    }
    clnt_cnt--;
    pthread_mutex_unlock(&mutx);
    close(clnt_sock);
    return NULL;
}
 
void send_msg(char* msg, int len)
{
    int i;
    pthread_mutex_lock(&mutx);
    for (i=0; i<clnt_cnt; i++)
        write(clnt_socks[i], msg, len);
    pthread_mutex_unlock(&mutx);
}
 
void error_handling(char *msg)
{
    fputs(msg, stderr);
    fputc('\n', stderr);
    exit(1);
}
 
char* serverState(int count)
{
    char* stateMsg = malloc(sizeof(char* 20);
    strcpy(stateMsg ,"None");
    
    if (count < 5)
        strcpy(stateMsg, "Good");
    else
        strcpy(stateMsg, "Bad");
    
    return stateMsg;
}        
 
void menu(char port[])
{
    system("clear");
    printf(" **** moon/sun chat server ****\n");
    printf(" server port    : %s\n", port);
    printf(" server state   : %s\n", serverState(clnt_cnt));
    printf(" max connection : %d\n", MAX_CLNT);
    printf(" ****          Log         ****\n\n");
}
cs


서버를 오픈하면 기본적으로 다음과 같은 화면을 출력해줍니다.


테스트한 port는 9190이고 최대 접속인원은 100명으로 제한을 두었습니다.


이 부분은 필요에 따라 변경해 사용하시면 됩니다.


* linux에서 포트를 사용할 때 한번 사용한 포트는 보안문제 때문에 당분간 사용할 수 없다고 합니다.

  서버를 오픈하실 때 마다 포트번호를 달리 하셔야 오류가 발생하지 않습니다.



log의 아래에는 접속한 클라이언트를 표시해 주는 부분입니다. 

반응형

리눅스에서 멀티쓰레드를 이용한 채팅프로그램을 만들어 보았습니다.


TCP/IP 소켓프로그래밍을 공부하면서 만든 프로그램인데, 기본적인 네트워크에서 통신과정을


이해하는데 도움이 됬습니다. 



* 설명

멀티 쓰레드를 이용한 다중 접속 채팅프로그램입니다. 


Ubuntu 16.04 64bit 환경에서 C언어로 작성하였습니다^^.


chat_server.c 와 chat_client.c 두 파일로 구성되어있고 이름에서도 알 수 있지만 


server.c는 서버의 역할을 하고 client.c 를 통해 접속하는 방식입니다.


사실 암호화 통신을 적용하고 싶었지만 이 부분은 좀더 공부가 필요할 것 같습니다. ㅎㅎ



* chat_client.c 클라이언트 


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
/**    chat_client **/
 
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<pthread.h>
#include<time.h>
 
#define BUF_SIZE 100
#define NORMAL_SIZE 20
 
void* send_msg(void* arg);
void* recv_msg(void* arg);
void error_handling(char* msg);
 
void menu();
void changeName();
void menuOptions(); 
 
char name[NORMAL_SIZE]="[DEFALT]";     // name
char msg_form[NORMAL_SIZE];            // msg form
char serv_time[NORMAL_SIZE];        // server time
char msg[BUF_SIZE];                    // msg
char serv_port[NORMAL_SIZE];        // server port number
char clnt_ip[NORMAL_SIZE];            // client ip address
 
 
int main(int argc, char *argv[])
{
    int sock;
    struct sockaddr_in serv_addr;
    pthread_t snd_thread, rcv_thread;
    void* thread_return;
 
    if (argc!=4)
    {
        printf(" Usage : %s <ip> <port> <name>\n", argv[0]);
        exit(1);
    }
 
    /** local time **/
    struct tm *t;
    time_t timer = time(NULL);
    t=localtime(&timer);
    sprintf(serv_time, "%d-%d-%d %d:%d", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour,
    t->tm_min);
 
    sprintf(name, "[%s]", argv[3]);
    sprintf(clnt_ip, "%s", argv[1]);
    sprintf(serv_port, "%s", argv[2]);
    sock=socket(PF_INET, SOCK_STREAM, 0);
 
    memset(&serv_addr, 0sizeof(serv_addr));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_addr.s_addr=inet_addr(argv[1]);
    serv_addr.sin_port=htons(atoi(argv[2]));
 
    if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1)
        error_handling(" conncet() error");
 
    /** call menu **/
    menu();
 
    pthread_create(&snd_thread, NULL, send_msg, (void*)&sock);
    pthread_create(&rcv_thread, NULL, recv_msg, (void*)&sock);
    pthread_join(snd_thread, &thread_return);
    pthread_join(rcv_thread, &thread_return);
    close(sock);
    return 0;
}
 
void* send_msg(void* arg)
{
    int sock=*((int*)arg);
    char name_msg[NORMAL_SIZE+BUF_SIZE];
    char myInfo[BUF_SIZE];
    char* who = NULL;
    char temp[BUF_SIZE];
 
    /** send join messge **/
    printf(" >> join the chat !! \n");
    sprintf(myInfo, "%s's join. IP_%s\n",name , clnt_ip);
    write(sock, myInfo, strlen(myInfo));
 
    while(1)
    {
        fgets(msg, BUF_SIZE, stdin);
 
        // menu_mode command -> !menu
        if (!strcmp(msg, "!menu\n"))
        {
            menuOptions();
            continue;
        }
 
        else if (!strcmp(msg, "q\n"|| !strcmp(msg, "Q\n"))
        {
            close(sock);
            exit(0);
        }
 
        // send message
        sprintf(name_msg, "%s %s", name,msg);
        write(sock, name_msg, strlen(name_msg));
    }
    return NULL;
}
 
void* recv_msg(void* arg)
{
    int sock=*((int*)arg);
    char name_msg[NORMAL_SIZE+BUF_SIZE];
    int str_len;
 
    while(1)
    {
        str_len=read(sock, name_msg, NORMAL_SIZE+BUF_SIZE-1);
        if (str_len==-1)
            return (void*)-1;
        name_msg[str_len]=0;
        fputs(name_msg, stdout);
    }
    return NULL;
}
 
 
void menuOptions() 
{
    int select;
    // print menu
    printf("\n\t**** menu mode ****\n");
    printf("\t1. change name\n");
    printf("\t2. clear/update\n\n");
    printf("\tthe other key is cancel");
    printf("\n\t*******************");
    printf("\n\t>> ");
    scanf("%d"&select);
    getchar();
    switch(select)
    {
        // change user name
        case 1:
        changeName();
        break;
 
        // console update(time, clear chatting log)
        case 2:
        menu();
        break;
 
        // menu error
        default:
        printf("\tcancel.");
        break;
    }
}
 
 
/** change user name **/
void changeName()
{
    char nameTemp[100];
    printf("\n\tInput new name -> ");
    scanf("%s", nameTemp);
    sprintf(name, "[%s]", nameTemp);
    printf("\n\tComplete.\n\n");
}
 
void menu()
{
    system("clear");
    printf(" **** moon/sum chatting client ****\n");
    printf(" server port : %s \n", serv_port);
    printf(" client IP   : %s \n", clnt_ip);
    printf(" chat name   : %s \n", name);
    printf(" server time : %s \n", serv_time);
    printf(" ************* menu ***************\n");
    printf(" if you want to select menu -> !menu\n");
    printf(" 1. change name\n");
    printf(" 2. clear/update\n");
    printf(" **********************************\n");
    printf(" Exit -> q & Q\n\n");
}    
 
void error_handling(char* msg)
{
    fputs(msg, stderr);
    fputc('\n', stderr);
    exit(1);
}
cs

  


클라이언트를 실행하면 아래처럼 클라이언트 메뉴가 등장합니다. 


허접한 영어로 되어있지만 사실은 인코딩오류를 방지하기 위해 그랬습니다. ㅎㅎ



채팅창에 !menu 명령어를 통해 닉네임 변경과 화면 새로고침을 할 수 있습니다.


맞습니다.  사실 없어도 되는 기능입니다.


다음 포스팅에 chat_server.c 을 소개하겠습니다.



반응형

[ Visual Studio 2017 환경에서 작성하였습니다. ]


비주얼스튜디오로 처음 C언어를 배우면서 한가지 어려웠던 기억이 있습니다.


학교에서는 분명히 win32 콘솔응용프로그램이 있었는데 집에서 설치하니 보이지가 않더군요 ㅜㅜ..


그리하여! 오늘은 Visual Studio 에서 win32 가 없는 문제를 간단하게 해결하는 포스팅을 해봅니다.


해결하기


파일 -> 새로 만들기 -> 프로젝트 또는 Ctrl + Shift + N 을 입력합니다.



여기까지는 학교와 동일합니다. 문제는 다음이었죠.


비슷하게 생긴 Windows 콘솔 응용프그램으로 만들게 되면 뭔가 안됩니다 ㅜㅜㅜ 우리가 하고자 하는 프로그램은 win32 콘솔 응용프로그램입니다.


비슷하지만 다르죠.



Visual C++ -> Windows 데스크톱 -> Windows 데스크톱 마법사 로 들어가줍니다.


그러면 아래의 사진처럼 응용 프로그램 종류를 선택할 수 있는 창이 나오는데


콘솔 응용프로그램(.exe) 를 선택해 주시고 빈프로젝트를 체크해 주시면 학교에서 실습하던 환경으로 코딩을 하실 수 있습니다 ㅎㅎ 



정보) SDL 검사는 보안이슈가 존재하는 함수들을 컴파일 오류를 통해 사용을 금하는 기능입니다. ex) scanf

       scanf의 경우 scanf_s 와 같이 대체함수를 사용하거나 #define _crt_secure_no_warnings 처리를 해주시면 그대로 사용이 가능합니다.


체크를 해제하면 이러한 함수들을 단순히 경고로 표시해줍니다. 


                                                                                                                             


참고 : https://msdn.microsoft.com/ko-kr/library/ms235629.aspx [win32 콘솔응용프로그램 만들기]


반응형

안녕하세요 ㅎㅎ 


많이 사용하는 자료구조중 하나인 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

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


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

반응형

C언어로 작성한 피보나치 수열 프로그램입니다.

대학교 1학년때 과제로 작성했던 프로그램인데 지금 보니 부족한 것이 많지만 수정하지 않고 올립니다.


혹시 필요하신 분들은 수정해서 사용하시면 될것 같습니다 ㅎㅎ



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
#include<stdio.h>
#include<conio.h>   // _getch()
#include<windows.h> // cls
 
int main(){
    int arr[30];    //30인 배열을 선언. 
    int i, j;       //변수 i와 j 선언. 
    int *= arr;   // 배열 arr을 포인터 p로 지정. 
    
    void CLS() {
    printf("\n\n계속하려면 Enter 입력하세요.");
    _getch(); // Enter 을 입력받으면 화면을 지운다.
    system("cls"); // 화면을 지우는 명령어.
    }
    
    int exit = 0;
    while(exit == 0){
        printf("수열의 수를 입력하세요.(30 이하, 종료는 100) : \n");  //수의 범위를 정해준다. 
        scanf("%d",&j);
        
        // 음수나 0을 입력시 오류를 알려줌.
        if(j <= && 100) {
            if (j == 100)
                return 0;
            
            system("cls");
            printf("1 이상의 수를 입력해 주세요!!");  
            CLS();
            continue
        }
        
        //피보나치 수열의 1번 2번항을 지정.
        p[0]=0
        p[1]=1;
        
         //피보나치 수열 연산. 
        for(i = 2; i < j+1; i++) {
             p[i] = p[i-1+ p[i-2];
        }
        
        printf("피보나치 수열 : \n");
        
        for(i = 1; i < j+1; i++) {
        
             printf("\n%d 번째 피보나치 수열 : %d ", i ,p[i]);
        }
        CLS();     // 엔터 입력받기 함수 호출. 
    }
    return 0;
}
 
 
cs

반응형

+ Recent posts