addressbook_v1.c

Download
c 395 lines 11.3 KB
  1/*
  2 * addressbook_v1.c
  3 *
  4 * μ£Όμ†Œλ‘ ν”„λ‘œκ·Έλž¨ - μ™„μ „ν•œ CRUD κΈ°λŠ₯ κ΅¬ν˜„
  5 *
  6 * κΈ°λŠ₯:
  7 *   1. μ—°λ½μ²˜ μΆ”κ°€ (Create)
  8 *   2. μ—°λ½μ²˜ λͺ©λ‘ 보기 (Read)
  9 *   3. μ—°λ½μ²˜ 검색 (Read)
 10 *   4. μ—°λ½μ²˜ μˆ˜μ • (Update)
 11 *   5. μ—°λ½μ²˜ μ‚­μ œ (Delete)
 12 *   6. 파일 μ €μž₯/뢈러였기 (Persistence)
 13 *
 14 * 컴파일: gcc -Wall -Wextra -std=c11 addressbook_v1.c -o addressbook
 15 * μ‹€ν–‰: ./addressbook
 16 */
 17
 18#include <stdio.h>
 19#include <string.h>
 20#include <stdlib.h>
 21
 22/* μƒμˆ˜ μ •μ˜ */
 23#define MAX_CONTACTS 100
 24#define NAME_LEN 50
 25#define PHONE_LEN 20
 26#define EMAIL_LEN 50
 27#define FILENAME "contacts.dat"
 28
 29/* μ—°λ½μ²˜ ꡬ쑰체 */
 30typedef struct {
 31    int id;
 32    char name[NAME_LEN];
 33    char phone[PHONE_LEN];
 34    char email[EMAIL_LEN];
 35} Contact;
 36
 37/* μ£Όμ†Œλ‘ ꡬ쑰체 */
 38typedef struct {
 39    Contact contacts[MAX_CONTACTS];
 40    int count;      // ν˜„μž¬ μ €μž₯된 μ—°λ½μ²˜ 수
 41    int next_id;    // λ‹€μŒμ— ν• λ‹Ήν•  ID
 42} AddressBook;
 43
 44/* ν•¨μˆ˜ μ„ μ–Έ */
 45void init_addressbook(AddressBook *ab);
 46void print_menu(void);
 47void add_contact(AddressBook *ab);
 48void list_contacts(AddressBook *ab);
 49void search_contact(AddressBook *ab);
 50void edit_contact(AddressBook *ab);
 51void delete_contact(AddressBook *ab);
 52int save_to_file(AddressBook *ab);
 53int load_from_file(AddressBook *ab);
 54void clear_input_buffer(void);
 55int find_by_id(AddressBook *ab, int id);
 56
 57/* 메인 ν•¨μˆ˜ */
 58int main(void) {
 59    AddressBook ab;
 60    int choice;
 61
 62    /* μ£Όμ†Œλ‘ μ΄ˆκΈ°ν™” */
 63    init_addressbook(&ab);
 64
 65    /* νŒŒμΌμ—μ„œ κΈ°μ‘΄ 데이터 뢈러였기 */
 66    if (load_from_file(&ab) == 0) {
 67        printf("κΈ°μ‘΄ 데이터λ₯Ό λΆˆλŸ¬μ™”μŠ΅λ‹ˆλ‹€. (%dλͺ…)\n", ab.count);
 68    }
 69
 70    /* ν”„λ‘œκ·Έλž¨ μ‹œμž‘ λ©”μ‹œμ§€ */
 71    printf("\n╔═══════════════════════════════╗\n");
 72    printf("β•‘      πŸ“’ μ£Όμ†Œλ‘ ν”„λ‘œκ·Έλž¨       β•‘\n");
 73    printf("β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•\n");
 74
 75    /* 메인 루프 */
 76    while (1) {
 77        print_menu();
 78        printf("선택: ");
 79
 80        /* 메뉴 선택 μž…λ ₯ */
 81        if (scanf("%d", &choice) != 1) {
 82            clear_input_buffer();
 83            printf("숫자λ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”.\n");
 84            continue;
 85        }
 86        clear_input_buffer();
 87
 88        /* 메뉴 처리 */
 89        switch (choice) {
 90            case 1:
 91                add_contact(&ab);
 92                break;
 93            case 2:
 94                list_contacts(&ab);
 95                break;
 96            case 3:
 97                search_contact(&ab);
 98                break;
 99            case 4:
100                edit_contact(&ab);
101                break;
102            case 5:
103                delete_contact(&ab);
104                break;
105            case 6:
106                if (save_to_file(&ab) == 0) {
107                    printf("βœ“ νŒŒμΌμ— μ €μž₯λ˜μ—ˆμŠ΅λ‹ˆλ‹€.\n");
108                }
109                break;
110            case 0:
111                /* μ’…λ£Œ μ „ μ €μž₯ 확인 */
112                printf("λ³€κ²½ 사항을 μ €μž₯ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ? (y/n): ");
113                char save_confirm;
114                scanf(" %c", &save_confirm);
115                if (save_confirm == 'y' || save_confirm == 'Y') {
116                    save_to_file(&ab);
117                    printf("μ €μž₯ μ™„λ£Œ.\n");
118                }
119                printf("ν”„λ‘œκ·Έλž¨μ„ μ’…λ£Œν•©λ‹ˆλ‹€.\n");
120                return 0;
121            default:
122                printf("잘λͺ»λœ μ„ νƒμž…λ‹ˆλ‹€.\n");
123        }
124        printf("\n");
125    }
126
127    return 0;
128}
129
130/* μ£Όμ†Œλ‘ μ΄ˆκΈ°ν™” */
131void init_addressbook(AddressBook *ab) {
132    ab->count = 0;
133    ab->next_id = 1;
134    memset(ab->contacts, 0, sizeof(ab->contacts));
135}
136
137/* 메뉴 좜λ ₯ */
138void print_menu(void) {
139    printf("\nβ”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”\n");
140    printf("β”‚  1. μ—°λ½μ²˜ μΆ”κ°€         β”‚\n");
141    printf("β”‚  2. λͺ©λ‘ 보기           β”‚\n");
142    printf("β”‚  3. 검색                β”‚\n");
143    printf("β”‚  4. μˆ˜μ •                β”‚\n");
144    printf("β”‚  5. μ‚­μ œ                β”‚\n");
145    printf("β”‚  6. 파일 μ €μž₯           β”‚\n");
146    printf("β”‚  0. μ’…λ£Œ                β”‚\n");
147    printf("β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜\n");
148}
149
150/* μ—°λ½μ²˜ μΆ”κ°€ */
151void add_contact(AddressBook *ab) {
152    /* μ£Όμ†Œλ‘μ΄ 가득 μ°ΌλŠ”μ§€ 확인 */
153    if (ab->count >= MAX_CONTACTS) {
154        printf("μ£Όμ†Œλ‘μ΄ 가득 μ°ΌμŠ΅λ‹ˆλ‹€. (μ΅œλŒ€ %dλͺ…)\n", MAX_CONTACTS);
155        return;
156    }
157
158    /* μƒˆ μ—°λ½μ²˜λ₯Ό μœ„ν•œ 포인터 */
159    Contact *c = &ab->contacts[ab->count];
160    c->id = ab->next_id++;
161
162    printf("\n═══ μƒˆ μ—°λ½μ²˜ μΆ”κ°€ ═══\n\n");
163
164    /* 이름 μž…λ ₯ (ν•„μˆ˜) */
165    printf("이름: ");
166    fgets(c->name, NAME_LEN, stdin);
167    c->name[strcspn(c->name, "\n")] = '\0';  // κ°œν–‰ 문자 제거
168
169    if (strlen(c->name) == 0) {
170        printf("이름은 ν•„μˆ˜μž…λ‹ˆλ‹€. μΆ”κ°€κ°€ μ·¨μ†Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.\n");
171        return;
172    }
173
174    /* μ „ν™”λ²ˆν˜Έ μž…λ ₯ */
175    printf("μ „ν™”λ²ˆν˜Έ: ");
176    fgets(c->phone, PHONE_LEN, stdin);
177    c->phone[strcspn(c->phone, "\n")] = '\0';
178
179    /* 이메일 μž…λ ₯ */
180    printf("이메일: ");
181    fgets(c->email, EMAIL_LEN, stdin);
182    c->email[strcspn(c->email, "\n")] = '\0';
183
184    /* μ—°λ½μ²˜ 수 증가 */
185    ab->count++;
186    printf("\nβœ“ '%s' μ—°λ½μ²˜κ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. (ID: %d)\n", c->name, c->id);
187}
188
189/* μ—°λ½μ²˜ λͺ©λ‘ 보기 */
190void list_contacts(AddressBook *ab) {
191    printf("\n═══ μ—°λ½μ²˜ λͺ©λ‘ ═══ (총 %dλͺ…)\n", ab->count);
192
193    if (ab->count == 0) {
194        printf("\nμ €μž₯된 μ—°λ½μ²˜κ°€ μ—†μŠ΅λ‹ˆλ‹€.\n");
195        return;
196    }
197
198    /* ν…Œμ΄λΈ” 헀더 */
199    printf("\n%-4s β”‚ %-15s β”‚ %-15s β”‚ %-20s\n", "ID", "이름", "μ „ν™”λ²ˆν˜Έ", "이메일");
200    printf("─────┼─────────────────┼─────────────────┼─────────────────────\n");
201
202    /* λͺ¨λ“  μ—°λ½μ²˜ 좜λ ₯ */
203    for (int i = 0; i < ab->count; i++) {
204        Contact *c = &ab->contacts[i];
205        printf("%-4d β”‚ %-15s β”‚ %-15s β”‚ %-20s\n",
206               c->id, c->name, c->phone, c->email);
207    }
208}
209
210/* μ—°λ½μ²˜ 검색 */
211void search_contact(AddressBook *ab) {
212    char keyword[NAME_LEN];
213    int found = 0;
214
215    printf("\n═══ μ—°λ½μ²˜ 검색 ═══\n\n");
216    printf("검색어: ");
217    fgets(keyword, NAME_LEN, stdin);
218    keyword[strcspn(keyword, "\n")] = '\0';
219
220    if (strlen(keyword) == 0) {
221        printf("검색어λ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”.\n");
222        return;
223    }
224
225    printf("\n검색 κ²°κ³Ό:\n");
226    printf("─────────────────────────────────────────────────────\n");
227
228    /* λͺ¨λ“  μ—°λ½μ²˜μ—μ„œ 검색 */
229    for (int i = 0; i < ab->count; i++) {
230        Contact *c = &ab->contacts[i];
231        /* 이름, μ „ν™”λ²ˆν˜Έ, μ΄λ©”μΌμ—μ„œ λΆ€λΆ„ λ¬Έμžμ—΄ 검색 */
232        if (strstr(c->name, keyword) != NULL ||
233            strstr(c->phone, keyword) != NULL ||
234            strstr(c->email, keyword) != NULL) {
235
236            printf("ID: %d\n", c->id);
237            printf("  이름: %s\n", c->name);
238            printf("  μ „ν™”: %s\n", c->phone);
239            printf("  이메일: %s\n", c->email);
240            printf("─────────────────────────────────────────────────────\n");
241            found++;
242        }
243    }
244
245    if (found == 0) {
246        printf("'%s'에 λŒ€ν•œ 검색 κ²°κ³Όκ°€ μ—†μŠ΅λ‹ˆλ‹€.\n", keyword);
247    } else {
248        printf("총 %d건 검색됨\n", found);
249    }
250}
251
252/* μ—°λ½μ²˜ μˆ˜μ • */
253void edit_contact(AddressBook *ab) {
254    int id;
255    char input[EMAIL_LEN];
256
257    printf("\n═══ μ—°λ½μ²˜ μˆ˜μ • ═══\n\n");
258    printf("μˆ˜μ •ν•  μ—°λ½μ²˜ ID: ");
259    scanf("%d", &id);
260    clear_input_buffer();
261
262    /* ID둜 μ—°λ½μ²˜ μ°ΎκΈ° */
263    int idx = find_by_id(ab, id);
264    if (idx == -1) {
265        printf("ν•΄λ‹Ή ID의 μ—°λ½μ²˜λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.\n");
266        return;
267    }
268
269    Contact *c = &ab->contacts[idx];
270
271    /* ν˜„μž¬ 정보 ν‘œμ‹œ */
272    printf("\nν˜„μž¬ 정보:\n");
273    printf("  이름: %s\n", c->name);
274    printf("  μ „ν™”: %s\n", c->phone);
275    printf("  이메일: %s\n", c->email);
276
277    printf("\nμƒˆ 정보λ₯Ό μž…λ ₯ν•˜μ„Έμš” (빈 μΉΈ: μœ μ§€):\n");
278
279    /* 이름 μˆ˜μ • */
280    printf("이름 [%s]: ", c->name);
281    fgets(input, NAME_LEN, stdin);
282    input[strcspn(input, "\n")] = '\0';
283    if (strlen(input) > 0) {
284        strcpy(c->name, input);
285    }
286
287    /* μ „ν™”λ²ˆν˜Έ μˆ˜μ • */
288    printf("μ „ν™”λ²ˆν˜Έ [%s]: ", c->phone);
289    fgets(input, PHONE_LEN, stdin);
290    input[strcspn(input, "\n")] = '\0';
291    if (strlen(input) > 0) {
292        strcpy(c->phone, input);
293    }
294
295    /* 이메일 μˆ˜μ • */
296    printf("이메일 [%s]: ", c->email);
297    fgets(input, EMAIL_LEN, stdin);
298    input[strcspn(input, "\n")] = '\0';
299    if (strlen(input) > 0) {
300        strcpy(c->email, input);
301    }
302
303    printf("\nβœ“ μ—°λ½μ²˜κ°€ μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.\n");
304}
305
306/* μ—°λ½μ²˜ μ‚­μ œ */
307void delete_contact(AddressBook *ab) {
308    int id;
309
310    printf("\n═══ μ—°λ½μ²˜ μ‚­μ œ ═══\n\n");
311    printf("μ‚­μ œν•  μ—°λ½μ²˜ ID: ");
312    scanf("%d", &id);
313    clear_input_buffer();
314
315    /* ID둜 μ—°λ½μ²˜ μ°ΎκΈ° */
316    int idx = find_by_id(ab, id);
317    if (idx == -1) {
318        printf("ν•΄λ‹Ή ID의 μ—°λ½μ²˜λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.\n");
319        return;
320    }
321
322    /* μ‚­μ œ 확인 */
323    printf("'%s' μ—°λ½μ²˜λ₯Ό μ‚­μ œν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ? (y/n): ", ab->contacts[idx].name);
324    char confirm;
325    scanf(" %c", &confirm);
326    clear_input_buffer();
327
328    if (confirm != 'y' && confirm != 'Y') {
329        printf("μ‚­μ œκ°€ μ·¨μ†Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.\n");
330        return;
331    }
332
333    /* μ‚­μ œ: λ’€μ˜ μš”μ†Œλ“€μ„ μ•žμœΌλ‘œ 이동 */
334    for (int i = idx; i < ab->count - 1; i++) {
335        ab->contacts[i] = ab->contacts[i + 1];
336    }
337    ab->count--;
338
339    printf("βœ“ μ—°λ½μ²˜κ°€ μ‚­μ œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.\n");
340}
341
342/* νŒŒμΌμ— μ €μž₯ (λ°”μ΄λ„ˆλ¦¬ λͺ¨λ“œ) */
343int save_to_file(AddressBook *ab) {
344    FILE *fp = fopen(FILENAME, "wb");
345    if (fp == NULL) {
346        printf("파일 μ €μž₯ μ‹€νŒ¨: νŒŒμΌμ„ μ—΄ 수 μ—†μŠ΅λ‹ˆλ‹€.\n");
347        return -1;
348    }
349
350    /* 메타데이터 μ €μž₯ (count, next_id) */
351    fwrite(&ab->count, sizeof(int), 1, fp);
352    fwrite(&ab->next_id, sizeof(int), 1, fp);
353
354    /* μ—°λ½μ²˜ λ°°μ—΄ μ €μž₯ */
355    fwrite(ab->contacts, sizeof(Contact), ab->count, fp);
356
357    fclose(fp);
358    return 0;
359}
360
361/* νŒŒμΌμ—μ„œ 뢈러였기 (λ°”μ΄λ„ˆλ¦¬ λͺ¨λ“œ) */
362int load_from_file(AddressBook *ab) {
363    FILE *fp = fopen(FILENAME, "rb");
364    if (fp == NULL) {
365        /* 파일이 μ—†μœΌλ©΄ μƒˆλ‘œ μ‹œμž‘ */
366        return -1;
367    }
368
369    /* 메타데이터 읽기 */
370    fread(&ab->count, sizeof(int), 1, fp);
371    fread(&ab->next_id, sizeof(int), 1, fp);
372
373    /* μ—°λ½μ²˜ λ°°μ—΄ 읽기 */
374    fread(ab->contacts, sizeof(Contact), ab->count, fp);
375
376    fclose(fp);
377    return 0;
378}
379
380/* ID둜 μ—°λ½μ²˜ μ°ΎκΈ° (인덱슀 λ°˜ν™˜) */
381int find_by_id(AddressBook *ab, int id) {
382    for (int i = 0; i < ab->count; i++) {
383        if (ab->contacts[i].id == id) {
384            return i;
385        }
386    }
387    return -1;  /* μ°Ύμ§€ λͺ»ν•¨ */
388}
389
390/* μž…λ ₯ 버퍼 λΉ„μš°κΈ° */
391void clear_input_buffer(void) {
392    int c;
393    while ((c = getchar()) != '\n' && c != EOF);
394}