일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 오늘의조언
- swift animation
- CountDownTimer
- date picker
- color animate
- Storyboard
- motivation
- 프로젝트기획
- valueChanged
- randombackgroundcolor
- 한국어 설정
- datepicker
- backgroundColor
- SWIFT
- IOS
- Today
- Total
정우의 연구일지
구조체로 주소록 프로그램 구현하기 (C언어) 본문
코드 설명
struct List
{
char name[20];
char phone[13];
char address[50];
char birth_of_date[8];
};
구조체는 효율을 우선시 하기 보단 다른 사람의 코드를 참고하지 않고 구조체를 활용해서 코드를 짜는 것에 초점을 맞추었다.
코드에 주석이 없는 이유는 내가 주석 없이도 이해되는 코드를 지향하기 때문이다.
int AddInfo(struct List *li, int *cnt);
int PrintEveryInfo(struct List *li, int cnt);
int SearchInfo(struct List *li, int cnt);
int DeleteInfo(struct List *li, int *cnt);
main함수를 제외한 함수는 이렇게 4가지이다.
순서대로 등록, 출력, 검색, 삭제 기능을 한다.
AddInfo 함수와 DeleteInfo 함수는 cnt의 값을 수정해야 하기 때문에 포인터로 받았다.
struct List list[100];
int input = 0, cnt = 0;
구조체 배열을 사용해야 했기 때문에 크기를 여유롭게 100으로 정해 주었다.
input 변수는 메인의 입력값이고, cnt 변수는 현재 구조체에 등록된 원소의 개수를 카운트한 개수이다.
while (input != 5){
printf("------ 주소록 프로그램 ------ \n");
printf("- 기능에 해당하는 숫자 입력 - \n");
printf("----------------------------- \n \n");
printf("(1) 정보 등록 \n");
printf("(2) 모든 정보 출력 \n");
printf("(3) 정보 검색 \n");
printf("(4) 정보 삭제 \n");
printf("(5) 프로그램 종료 \n");
printf("숫자 입력: ");
rewind(stdin);
scanf("%d", &input);
while문의 조건은 입력이 5가 아니면 참으로 설정했다.
숫자 이외의 값이 들어왔을 때 입력 버퍼가 비워지지 않는 문제를 예방하기 위해 rewind 함수를 사용했다.
switch (input){
case 1:
AddInfo(list, &cnt);
break
case 2:
PrintEveryInfo(list, cnt);
break;
case 3:
SearchInfo(list, cnt);
break
case 4:
DeleteInfo(list, &cnt);
break
case 5:
printf("\n ---- 프로그램을 종료합니다. ---- \n");
break
default:
printf("예외 입력 발생. 다시 입력해주세요. \n");
break;
}
switch문에서 각 케이스별로 해당하는 함수를 호출한다.
모든 함수는 인자로 구조체 배열 list와 cnt를 받는다.
1번은 정보 등록이기 때문에 cnt를 1 증가시켰고, 4번은 정보 삭제이기 때문에 cnt를 1 감소시켰다.
5번을 입력하게 되면 while문이 반복하지 않아서 프로그램이 종료된다.
해당되지 않는 숫자가 입력되었을 때를 예방하기 위해 default 케이스를 두었다.
int AddInfo(struct List *li, int *cnt){
printf("이름 입력 ex) 홍길동 : ");
scanf("%s", li[*cnt].name);
printf("전화번호 입력 ex) 010-1234-5678 : ");
scanf("%s", li[*cnt].phone);
printf("주소 입력 ex) 서울특별시 : ");
scanf("%s", li[*cnt].address);
printf("생년월일 입력 ex) 20021126 : ");
scanf("%s", li[*cnt].birth_of_date);
*cnt += 1;
printf("\n---- 입력 종료 ---- \n");
return 0;
}
AddInfo 함수는 이름으로 알 수 있듯이 정보를 등록하는 함수다.
gets는 버퍼 오버플로우 때문에 사용하지 않았고, scanf_s는 Clang 컴파일러에서 지원하지 않기 때문에 사용하지 않았다.
열거형을 활용해서 반복문으로 짤지도 고민해 보았지만, 입력 개수가 일정하며 많은 게 아니라서 이렇게 입력 받았다.
모든 입력이 정상적으로 끝난 뒤 cnt의 값을 1 증가시킨다.
int PrintEveryInfo(struct List *li, int cnt){
if(cnt < 1){
printf("등록된 정보가 없습니다. 정보를 먼저 등록해 주세요. \n");
return 0;
}
printf("등록된 정보 %d개 \n", cnt);
for(int i=0;i<cnt;i++){
printf("(이름: %s / 전화번호: %s / 주소: %s / 생년월일: %s) \n", li[i].name, li[i].phone, li[i].address, li[i].birth_of_date);
}
printf("\n---- 출력 종료 ---- \n");
return 0;
}
PrintEveryInfo 함수는 등록된 정보 전체를 출력하는 함수다.
등록된 정보의 개수가 1개 미만이라면 함수를 빠져나간다.
아니라면 반복문에서 모든 정보를 출력한 뒤 빠져나간다.
int SearchInfo(struct List *li, int cnt){
char search_str[20];
int check = 0;
if(cnt < 1){
printf("등록된 정보가 없습니다. 정보를 먼저 등록해 주세요. \n");
return 0;
}
printf("이름으로 정보 검색: ");
scanf("%s", search_str);
for(int i=0;i<cnt;i++){
if(strcmp(li[i].name, search_str) == 0){
printf("(이름: %s / 전화번호: %s / 주소: %s / 생년월일: %s) \n", li[i].name, li[i].phone, li[i].address, li[i].birth_of_date);
check +=1;
}
}
SearchInfo 함수는 이름으로 정보를 검색하는 함수이다.
반복문에서 이름이 같은 원소를 만나면 출력한다.
출력하고 break 할 지도 고민했었지만 그러면 이름이 중복되는 경우 출력할 수 없기 때문에 넣지 않았다.
만약 이름이 아닌 인덱스같은 슈퍼키로 검색했다면 break를 넣었을 것이다.
int DeleteInfo(struct List *li, int *cnt){
int index;
if(*cnt < 1){
printf("등록된 정보가 없습니다. 정보를 먼저 등록해 주세요. \n");
return 0;
}
for(int i=0;i<(*cnt);i++){
printf("(%d)(이름: %s / 전화번호: %s / 주소: %s / 생년월일: %s) \n", i+1, li[i].name, li[i].phone, li[i].address, li[i].birth_of_date);
}
printf("삭제할 항목의 번호 입력: ");
rewind(stdin);
scanf("%d", &index);
for(int i=index-1;i<(*cnt)-1;i++){
li[i] = li[i+1];
}
*cnt -= 1;
printf("\n---- 삭제 완료 ----\n");
return 0;
}
DeleteInfo 함수는 정보를 삭제하는 함수다.
먼저 현재 등록된 모든 정보를 번호와 함께 출력하고 삭제할 항목의 번호를 사용자가 입력하면 해당 정보가 삭제된다.
삭제는 삭제할 항목의 다음 항목부터 한 칸 씩 앞으로 붙여넣는 방식이다.
마지막 항목은 다음 항목이 존재하지 않기 때문에 반복문에 포함하지 않았다.
삭제가 성공적으로 끝나면 cnt의 값을 감소 시킨다.
전체 코드
#include <stdio.h>
#include <string.h>
struct List
{
char name[20];
char phone[13];
char address[50];
char birth_of_date[8];
};
int AddInfo(struct List *li, int *cnt);
int PrintEveryInfo(struct List *li, int cnt);
int SearchInfo(struct List *li, int cnt);
int DeleteInfo(struct List *li, int *cnt);
int main() {
struct List list[100];
int input = 0, cnt = 0;
while (input != 5){
printf("------ 주소록 프로그램 ------ \n");
printf("- 기능에 해당하는 숫자 입력 - \n");
printf("----------------------------- \n \n");
printf("(1) 정보 등록 \n");
printf("(2) 모든 정보 출력 \n");
printf("(3) 정보 검색 \n");
printf("(4) 정보 삭제 \n");
printf("(5) 프로그램 종료 \n");
printf("숫자 입력: ");
rewind(stdin);
scanf("%d", &input);
switch (input){
case 1:
AddInfo(list, &cnt);
break;
case 2:
PrintEveryInfo(list, cnt);
break;
case 3:
SearchInfo(list, cnt);
break;
case 4:
DeleteInfo(list, &cnt);
break;
case 5:
printf("\n ---- 프로그램을 종료합니다. ---- \n");
break;
default:
printf("예외 입력 발생. 다시 입력해주세요. \n");
break;
}
}
return 0;
}
int AddInfo(struct List *li, int *cnt){
printf("이름 입력 ex) 홍길동 : ");
scanf("%s", li[*cnt].name);
printf("전화번호 입력 ex) 010-1234-5678 : ");
scanf("%s", li[*cnt].phone);
printf("주소 입력 ex) 서울특별시 : ");
scanf("%s", li[*cnt].address);
printf("생년월일 입력 ex) 20021126 : ");
scanf("%s", li[*cnt].birth_of_date);
*cnt += 1;
printf("\n---- 입력 종료 ---- \n");
return 0;
}
int PrintEveryInfo(struct List *li, int cnt){
if(cnt < 1){
printf("등록된 정보가 없습니다. 정보를 먼저 등록해 주세요. \n");
return 0;
}
printf("등록된 정보 %d개 \n", cnt);
for(int i=0;i<cnt;i++){
printf("(이름: %s / 전화번호: %s / 주소: %s / 생년월일: %s) \n", li[i].name, li[i].phone, li[i].address, li[i].birth_of_date);
}
printf("\n---- 출력 종료 ---- \n");
return 0;
}
int SearchInfo(struct List *li, int cnt){
char search_str[20];
int check = 0;
if(cnt < 1){
printf("등록된 정보가 없습니다. 정보를 먼저 등록해 주세요. \n");
return 0;
}
printf("이름으로 정보 검색: ");
scanf("%s", search_str);
for(int i=0;i<cnt;i++){
if(strcmp(li[i].name, search_str) == 0){
printf("(이름: %s / 전화번호: %s / 주소: %s / 생년월일: %s) \n", li[i].name, li[i].phone, li[i].address, li[i].birth_of_date);
check +=1;
}
}
if(check == 0){
printf("검색 결과를 찾을 수 없습니다. \n");
}
printf("\n---- 검색 종료 ---- \n");
return 0;
}
int DeleteInfo(struct List *li, int *cnt){
int index;
if(*cnt < 1){
printf("등록된 정보가 없습니다. 정보를 먼저 등록해 주세요. \n");
return 0;
}
for(int i=0;i<(*cnt);i++){
printf("(%d)(이름: %s / 전화번호: %s / 주소: %s / 생년월일: %s) \n", i+1, li[i].name, li[i].phone, li[i].address, li[i].birth_of_date);
}
printf("삭제할 항목의 번호 입력: ");
rewind(stdin);
scanf("%d", &index);
for(int i=index-1;i<(*cnt)-1;i++){
li[i] = li[i+1];
}
*cnt -= 1;
printf("\n---- 삭제 완료 ----\n");
return 0;
}
향후 개선점
- 예외처리 추가
- 검색 기능 보완