티스토리 뷰

이번 학교 프로젝트 과제로 일정관리 프로그램을 만들었습니다. 

간단한 기능들 위주로 구현되어있으며 유닉스 시스템콜(저장,불러오기에 집중적으로 사용됨)을 C언어에 첨가하여 만들어봤습니다. UI를 화려하게 만들진 않았습니다 단순히 콘솔용 프로그램이라 생각하시면됩니다. 

혹시 학교 과제 하시는 분들 사용하셔도 좋습니다. 터미널에서 vi 모드로 파일에 코드를 붙여넣고 gcc를 사용하여 실행할 수 있습니다~

 

#프로젝트 설명

프로그램에는 일정등록, 등록된 일정 수정 삭제 조작 기능, 우선순위 등록 기능을 구현했습니다. 우선순위 등록은 일정등록할때 이루어지며 나중 등록된 일정들을 우선순위별로 구분하여 조회할 있습니다. 일정 조작 기능에서 수정 삭제는 말그대로 수정 삭제입니다. 외의 조작 기능으로는 벌써 수행한 일정은 수행한 일정끼리, 아직 수행하지 않은 미수행 일정들은 미수행 일정끼리 모아 있는 기능이 있습니다.

 

#코드

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
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
 
 
const int MAX = 100;
int MIM = 0;
 
char inputdate(void);
void mainscreen(char inputalpha);
void datescreen(void);
void datedoit(int doitinput);
void doitscreen(void);
void pirscreen(void);
void modifyscreen(void);
void savedata(void);
void readdata(void);


typedef struct schedule
{
    int year, month, date, time; //날짜
    char title[50]; //제목
    char content[1000]; //내용
    int priority; //우선순위
    int doit; //수행여부
 
}schdule;
//일정 구조체 
 
struct schedule sc[100];
 
 
char inputdate()
{
    int yesorno = 2;
    printf("일정 등록 화면입니다.\n");
    printf("제목을 입력한뒤 enter 키를 누르세요.\n");
    scanf("%s", sc[MIM].title);
    printf("제목:%s\n", sc[MIM].title);
 
 
    while (yesorno == 2) {
        printf("날짜를 년 월 일 로 입력하세요.\nex) 2020/9/3\n");
        int a = scanf("%d/%d/%d"&sc[MIM].year, &sc[MIM].month, &sc[MIM].date);
        if (a != 3) {
            continue;
        }
        printf("시간을 입력하세요.\nex) 21\n");
        scanf("%d"&sc[MIM].time);
 
        printf("%d년 %d월 %d일 %d시 : 맞으면 1 아니면 2를 입력하세요.\n", sc[MIM].year, sc[MIM].month, sc[MIM].date, sc[MIM].time);
        scanf("%d"&yesorno); 
 
        if (yesorno == 2) {
            printf("재입력 합니다.\n");
            getchar();
        }
 
 
    }
    getchar(); // 버퍼에 남은 개행문자 없애는 용도
    printf("내용을 입력하세요.\n");
 
    scanf("%s", sc[MIM].content);
 
    while(1) {
        printf("우선순위를 숫자로 입력하세요. ( 1 ~ 5 )\n");//************우선순위를 1~5로 받는거 아주중요. 아래 함수에서 초기화된 구조체배열과 그렇지 않은애를 이거로 구분했음!*********이게 0이면 빈애로 판단.
        scanf("%d"&sc[MIM].priority);
        if (sc[MIM].priority > 0 && sc[MIM].priority < 6) {
            break;
        }
        }
 
 
    sc[MIM].doit = 1;
 
    MIM++;
 
    return 0;
 
}
 
 
void mainscreen(char inputalpha)//메인화면함수
{
    printf("====================================\n\n");
 
    printf("A. 일정등록\n\n");
    printf("B. 미수행 일정보기\n\n");
    printf("C. 수행한 일정보기\n\n");
    printf("D. 일정 수정 및 삭제\n\n");
    printf("E. 미수행 일정 우선순위 보기\n\n");
    printf("F. 프로그램 종료\n\n");//KILL 시스템콜?
 
 
    printf("====================================\n");
    printf("메인메뉴 ++++++ 알파벳을 입력하세요.\n\n");
    // 여기까지가 시작화면 출력
    // 여기부터 출력 화면에서 입력받은 메뉴 실행
 
 
    if (inputalpha == 'A')
    {
 
        inputdate();
        getchar();
 
    }
    if (inputalpha == 'B')
    {
 
        datescreen();
        getchar();
 
    }
    if (inputalpha == 'C')
    {
 
        doitscreen();
        getchar();
 
    }
    if (inputalpha == 'D')
    {
        modifyscreen();
        getchar();
    }
    if (inputalpha == 'E')
    {
 
        pirscreen();
        getchar();
 
    }
    if (inputalpha == 'F')
    {
 
        savedata();
        exit(1);
 
    }
 
 
}
 
void pirscreen(void)
{
   
    int w = 0;
    int i = 0;
    int checkpriority[6= { 0 };
   
    for (i ; i < 100; i++) {
        int n = sc[i].priority;
 
        if (n >0&&n<6&& (sc[i].doit == 1)) {
            checkpriority[n]++;
        }
    }
 
    
    printf("미수행 일정 우선순위 보기 화면입니다.\n");
    printf("====================================\n\n");
    int t = 1;
    for ( t ; t < 6; t++) {
        printf("%d순위 일정 : %d개\n", t, checkpriority[t]);
    }
    printf("====================================\n\n");
 
   
    while (1) {
        printf("\n보고 싶은 우선순위를 입력하세요.(1~5)\n");
        scanf("%d"&w);
        if (w > 0 && w < 6)
            break;
    }
    
    
        printf("%d 순위 미수행 일정 리스트\n", w);
        printf("\n");
        printf("****************************************\n");
        printf("\n");
        int k = 0;
        for (k; k < 100; k++)
        {
            if ((sc[k].doit == 1&& (sc[k].priority == w))
            {
                printf("----------------------------------------\n");
                printf("제목 : %s\n", sc[k].title);
                printf("날짜 : % d년 / % d월 / % d일 / %d시\n", sc[k].year, sc[k].month, sc[k].date, sc[k].time);
                printf("내용 : %s\n", sc[k].content);
                printf("우선순위 : %d\n", sc[k].priority);
                printf("----------------------------------------\n");
                printf("\n");
            }
 
        }
 
    
    printf("\n");//포문으로 반복
 
    printf("========================================\n");
 
    getchar();
 
    printf("메인메뉴로 나가려면 아무키나 눌러주세요\n");
 
}
 
 
void doitscreen(void)//수행한 일정리스트 출력함수
{
 
    printf("====================================\n");
    printf("메인메뉴로 나가려면 아무키나 눌러주세요\n");
    printf("====================================\n");
    int k = 0;
    for (k; k < 100; k++)
    {
        if (sc[k].doit == 2&&sc[k].priority!=0)
        {
            printf("번호 : %d\n", k);
            printf("제목 : %s\n", sc[k].title);
            printf("날짜 : % d년 / % d월 / % d일 / %d시\n", sc[k].year, sc[k].month, sc[k].date, sc[k].time);
            printf("내용 : %s\n", sc[k].content);
            printf("우선순위 : %d\n", sc[k].priority);
            printf("====================================\n");
        }
 
    }
    printf("\n");//포문으로 반복
 
    printf("====================================\n");
 
    getchar();
 
    printf("메인메뉴로 나가려면 아무키나 눌러주세요\n");
 
}
 
 
void modifyscreen() {
    printf("일정 수정 삭제 화면입니다.\n");
    printf("====================================\n\n");
    int i = 0;
    int n = 0;
    int menu = 0;
    int pr = 0;
    int yn = 1;
    for (i; i < MIM; i++) {
        if (sc[i].priority != 0) {
            printf("%d 번 일정 | 제목 %s \n",i, sc[i].title);
        }
    }
 
    while (1) {
        printf("수정/삭제 하고 싶은 일정의 번호를 입력하세요.\n\n");
        scanf("%d"&n);
        if (sc[n].priority != 0)
            break;
    }
    printf("====================================\n");
    printf("#.번호 : %d\n", n);
    printf("1.제목 : %s\n", sc[n].title);
    printf("2.날짜 : % d년 / % d월 / % d일 / %d시\n", sc[n].year, sc[n].month, sc[n].date, sc[n].time);
    printf("3.내용 : %s\n", sc[n].content);
    printf("4.우선순위 : %d\n", sc[n].priority);
    printf("====================================\n");
    
    while (1) {
        printf("수정하고자 하는 정보의 번호를 입력하세요.\n일정 삭제를 원한다면 5를 입력하세요.(1~5)\n");
        scanf("%d"&menu);
        if (menu > 0 && menu < 6)
            break;
    }
    switch (menu)
    {
    case 1:
            sc[n].title[0]='\0';
            
            while(1){
            printf("수정하고 싶은 제목을 입력하세요.\n");
            scanf("%s",sc[n].title);
                
                
                printf("%s 이 맞습니까? (맞으면 1/아니면 2)\n",sc[n].title);
                scanf("%d",&yn);
                getchar();
 
                if(yn==1){
                    break;
                }
            }
            break;
    case 2:
            sc[n].year = 0;
            sc[n].month = 0;
            sc[n].date = 0;
            sc[n].time = 0;
            
            while (1) {
                printf("날짜를 년 월 일 로 입력하세요.\nex) 2020/9/3\n");
                int a = scanf("%d/%d/%d"&sc[MIM].year, &sc[MIM].month, &sc[MIM].date);
                if (a != 3) {
                    continue;
                }
                printf("시간을 입력하세요.\nex) 21\n");
                scanf("%d"&sc[MIM].time);
 
                printf("%d년 %d월 %d일 %d시 : 맞으면 1 아니면 2를 입력하세요.\n", sc[MIM].year, sc[MIM].month, sc[MIM].date, sc[MIM].time);
                scanf("%d"&yn); // n이면 while문 다시돔. y면 다음으로 넘어감.
 
                if (yn == 2) {
                    printf("재입력 합니다.\n");
                    getchar();
                }
                else if(yn == 1){
                    break;
                }
 
 
            }
            break;
            
 
    case 3:
            
            sc[n].content[0]='\0';
            
            while(1){
                
            printf("수정하고 싶은 내용을 입력하세요.\n");
            scanf("%s",sc[n].content);
                
                printf("%s 이 맞습니까? (맞으면 1/아니면 2)\n",sc[n].content);
                scanf("%d",&yn);
                
                if(yn==1){
                    break;
                }
                
            }
            break;
 
    case 4:
            while(1){
            printf("변경하고자하는 우선순위를 입력하세요. (1~5)");
            
            scanf("%d",&pr);
                if(pr>0&&pr<6){
                    sc[n].priority = pr;
                    break;
                }
            }
            break;
    case 5:
            while(1){
                printf("일정을 삭제할까요? (맞으면 1/아니면 2)\n");
                scanf("%d",&yn);
                if(yn==1){
                    sc[n].priority = 0;
                    break;
                }else if(yn==2){
                    break;
                }
                
            }
            break;
    }
 
}
 
 
void datescreen(void)//미수행리스트 확인 함수 + 수행한 항목 옮기는 기능 함수
{
 
    char select = 'n';
    int changenum;
    printf("====================================\n");
    printf("메인메뉴로 나가려면 아무키나 눌러주세요\n");
    printf("수행일정으로 옮길 항목이 있으면 y 를 눌러주세요\n");
    printf("수행일정으로 옮길 항목이 없으면 아무키나 눌러주세요\n");
    printf("====================================\n");
    int k = 0;
    for (k; k < 100; k++)
    {
        if (sc[k].doit == 1 && sc[k].priority != 0)
        {
            printf("번호 : %d\n", k);
            printf("제목 : %s\n", sc[k].title);
            printf("날짜 : % d년 / % d월 / % d일 / %d시\n", sc[k].year, sc[k].month, sc[k].date, sc[k].time);
            printf("내용 : %s\n", sc[k].content);
            printf("우선순위 : %d\n", sc[k].priority);
            printf("====================================\n");
        }
 
    }
    printf("\n");//포문으로 반복
 
    printf("====================================\n");
 
    scanf("%c"&select);
    if (select == 'y')
    {
        printf("수행한 일정의 번호를 입력해주세요\n");
        scanf("%d"&changenum);
        datedoit(changenum);
        printf("%d번 일정이 수행처리 되었습니다.\n", changenum);
    }
 
    getchar();
 
    printf("메인메뉴로 나가려면 아무키나 눌러주세요\n");
 
 
}
 
 
void datedoit(int doitinput)//수행리스트로 넘기는 함수
{
 
    sc[doitinput].doit = 2;
}
 
 
void savedata() {
    unlink("datafile");
    int fd;
    fd = open("datafile", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd == -1)
    {
        perror("failed open datafile.");
        exit(1);
    }
    int re = 0;
    int i = 0;
    for (i; i < MIM; i++)
    {
        re = write(fd, &sc[i], sizeof(sc));
        if (re == -1)
        {
            perror("failed write ");
            exit(1);
        }
    }
 
 
}
 
 
void readdata() {
    struct schedule sc2;
    int fd = 0;
    fd = open("datafile", O_RDONLY | O_CREAT, 0644);
    if (fd == -1)
    {
        perror("failed open save file.");
        exit(1);
    }
    int re = 0;
    memset(&sc2, 0sizeof(struct schedule));
    while ((re = read(fd, &sc2, sizeof(struct schedule))) > 0)
    {
        if (sc2.priority == 0) {
            break;
        }
        sc[MIM].year = sc2.year;
        sc[MIM].month = sc2.month;
        sc[MIM].date = sc2.date;
        sc[MIM].time = sc2.time;
        strcpy(sc[MIM].title, sc2.title);
        strcpy(sc[MIM].content, sc2.content);
        sc[MIM].priority = sc2.priority;
        sc[MIM].doit = sc2.doit;
        MIM++;
 
    }
 
    close(fd);
}
 
 
int main()//메인함수
{
 
 
 
    char menu_alphabet = 'Z';
 
    readdata();
    while (1)
    {
        mainscreen('Z');
        scanf("%c"&menu_alphabet);
        getchar();
        mainscreen(menu_alphabet);
 
    }
    
}
cs

 

#코드 설명

 

-구조체 

schedule 구조체 : 일정등록시 기본이 되는 단위이다. 날짜, 제목, 내용, 우선순위, 수행여부 저장할 있다.

**schedule 구조체를 배열로 100개를 먼저 할당하고 프로그램이 실행됩니다.(37번 줄 참고) 즉, 프로그램내에서 이루어지는 일정 조작들은 이 구조체 배열들을 통해 이루어지는 것입니다. 저장, 삭제, 수정, 추가 등 모든 조작이 포함됩니다. 그러므로 혹시 100개이상의 일정이 동시에 저장될 수도 있는 실행이 예상된다면  선언하는 배열의 크기를 확장시켜야만합니다. 

 

구조체가 사용되는 흐름은 아래와 같습니다.

1. readdata() : 정보를 현재 선언된 구조체 배열에 하나씩 읽어서 할당해줍니다.

2. 프로그램실행 : 구조체 배열들만 조작

3. savedata() : readdata에서 사용된 파일과 같은 "datafile"을 사용합니다. 다만, 정보가 섞이지 않도록 원래있던 데이터들은 초기화를 시킨후 백지가된 "datafile"에 구조체 배열들에 있는 정보들을 저장합니다.

 

-함수

1. main 

readdata 저장데이터를 불러오고 시작합니다.

mainscreen 함수를 반복문안에서 계속 호출하여 메인화면이 띄워질 있도록 합니.

 

2. mainscreen

메인 화면.

메인 화면에서 메뉴를 선택할 있도록 입력까지 받습니다.

아래 설명되는 함수들을 호출하여 기능들이 실행되도록합니다.

 

3. pirscreen

우선순위별로 모아보는 함수입니다.

mainscreen 으로부터 호출을 받습니다.

 

4. doitscreen

수행한 일정들을 모아서 보는 함수입니다.

mainscreen 으로부터 호출을 받습니다.

 

5. datedoit

등록된 일정을 미수행에서 수행된 일정으로 바꿉니다.

doitscreen 으로부터 호출을 받는다.

 

6. modifyscreen

등록된일정을 수정하는 화면입니다. 삭제기능까지 구현되어있습니다.

mainscreen 으로부터 호출을 받습니다.

 

7. datescreen

미수행 일정들을 모아 있는 함수입니다. 수행한 항목으로 옮길때 datedoit 함수를 사용하여 옮기도록 하였습니다.

 

8. savedata

데이터 파일에 데이터를 저장하는 함수입니다. 구조체 단위로 저장이되며 프로그램이 종료될때 수행되는 함수입니다.

unlink 로 원래 있던 파일을 놔주고 처음부터 새로쓴다. open으로 파일디스크립터를 받아오고 write으로 그 파일에 정보를 저장한다.

 

9. readdata

데이터 파일에서 데이터를 읽어오는 함수입니다. 구조체 단위로 불러오며 프로그램이 실행될때 main 함수에서 호출되어 수행됩니다.

open으로 파일디스크립터를 받아온 뒤 read로 저장된 정보를 읽어들인다.

 

 

#주의사항

위에 74번 줄에도 주석으로 적어 놨습니다만 함수들에서 초기화된 구조체배열과 그렇지 않은애를 priority의 값으로 구분했기 때문에 우선순위를 정수 1~5로 받는게 아주 중요합니다.

, 만약 구조체의 priority변수가 0이라면 아직 초기화되지 않은 구조체로 판단을 합니다. 혹시 코드를 수정할땐 오류를 막기위해 이 부분을 주의 하셔야합니다!

이부분이 까다롭게 느껴지시면 아예 구조체안에 구조체 배열들중 초기화된 구조체를 구분해주는 변수를 선언하는 것도 좋습니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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
글 보관함