전화번호부 v4.0
더 많은 항목, 구조체 추가
이름을 제외한 일부 항목이 누락되어도 작동되도록 한다.
추가, 검색의 경우 공백 입력이 많이 되었더라도 실제로는 공백 1개로 인식되게한다.
구조체
- 항상 같이 붙어다녀야 하는 데이터를 별개의 변수들에 분산해서 저장하는 것은 바람직하지 않다.
- 어떤 한 사람의 이름, 전화번호, 이메일 주소 등이 그런 예이다.
- C언어에서는 이런 경우 구조체(structure)를 사용한다.
#include <stdio.h>
#include <string.h>
#include <stlib.h>
#define CAPACITY 100
#define BUFFER_LENGTH 100
typedef struct person { // person은 생략가능
char *name; // 배열로 쓰기 위해 *로 선언
char *number;
char *mail;
char *group;
} Person;
Person dicrectory[CAPACITY];
int n = 0;
int main() {
char command_line[BUFFER_LENGTH];
char *command, *argument;
char name_str[BUFFER_LENGTH];
while(1) {
printf("$ ");
if(read_line(stdin, command_line, BUFFER_LENGTH)<=0)
continue;
command = strtok(command_line, " ");
if (strcmp(command, "read") == 0) {
arguemnt = strtok(NULL, " ");
if (argument == NULL) {
printf("Invalid arguments. \n");
continue;
}
load(argument);
}
else if (strcmp(command, "add") == 0) {
if (compose_name(name_str, BUFFER_LENGTH) <= 0) { // compose_name 함수는 공백 압축용이다.
printf("Name required.\n");
continue;
}
handle_add(name_str);
}
else if (strcmp(command, "find") == 0) {
if (compose_name(name_str, BUFFER_LENGTH) <= 0) {
printf("Name required.\n");
continue;
}
find(name_str);
}
else if (strcmp(command, "status") == 0) {
status();
}
else if (strcmp(command, "delete") == 0) {
if (compose_name(name_str, BUFFER_LENGTH) <= 0) {
printf("Invaild arguments.\n");
continue;
}
remove(name_str);
}
else if (strcmp(command, "save") == 0) {
argument = strtok(NULL, " ");
if (strcmp(argument, "as") != 0) {
printf("Invaild arguments.\n");
continue;
}
argument = strtok(NULL, " ");
if (argument == NULL) {
printf("Invaild arguments.\n");
continue;
}
save(argument);
}
else if (strcmp(command, "exit") == 0)
break;
}
return 0;
}
- compose_name()
int compose_name(char str[], int limit ) {
char *ptr;
int length = 0;
ptr = strtok(NULL, " ");
if (ptr == NULL)
return 0;
strcpy(str, ptr);
length += strlen(ptr);
while ((ptr = strtok(NULL, " ") != NULL) {
if ( length + strlen(ptr) +1 < limit ) {
str[length++] = ' ';
str[length] = ' \0';
strcat(str, ptr);
length += strlen(ptr);
}
}
return length;
}
- handle_add()
void handle_add(char *name) {
char number[BUFFER_LENGTH], email[BUFFER_LENGTH], group[BUFFER_LENGTH];
char empty[] = " ";
printf(" Phone: ");
read_line(stdin, number, BUFFER_LENGTH);
printf(" Email: ");
read_line(stdin, email, BUFFER_LENGTH);
printf(" Group: ");
read_line(stdin, group, BUFFER_LENGTH);
add(name, (char *)(strlen(number)>0 ? number: empty),
(char *)(strlen(email)>0 ? email: empty),
(char *)(strlen(group)>0 ? group: empty));
// 존재하지 않는 항목들을 하나의 공백문자로 구성된 문자열로 대체한다.
}
- read_line()
int read_line(FIEL * fp, str[], int n )
{
int ch, i =0;
while ((ch = fgetc(fp) != '\n' && ch != EOF) {
if ( i < n )
str[i++] = ch;
str[i] = '\0'; // 문자열이 끝이라는 걸 표시하기 위해 마지막에 null character('\0')를 추가해준다.
return i; // 실제로 읽은 문자수를 반환한다.
}
// 키보드 뿐만 아나라 파일로부터도 읽을 수 있도록 변경되었다.
- load()
void load(char *fileName) {
char buffer[BUFFER_LENGTH];
char *name, *number, *email, *group;
FILE *fp = fopen(fileName, "r");
if (fp==NULL) {
printf("Open failed.\n");
return;
}
while (1) {
if (read_line(fp, buffer, BUFFER_LENGTH) <= 0)
break;
name = strtok(buffer, "#");
number= strtok(NULL, "#");
email= strtok(NULL, "#");
group= strtok(NULL, "#");
add(name, number, email, group);
}
fclose(fp);
}
- add()
void add(char *name, char *number, char *email, char *group) {
int i=n-1
while(i>=0 && strcmp(directory[i].name, name) > 0) {
directory[i+1] = directory[i];
i--;
}
directory[i+1].name = strdup(name);
directory[i+1].number= strdup(number);
directory[i+1].email= strdup(email);
directory[i+1].group = strdup(group);
n++;
}
- save()
void save(char *fileName) {
int i;
FILE *fp = fopen(fimeName, "w"); //해당 이름의 파일이 없다면 fopen 함수에서 새로 만들어준다.
if (fp==NULL) {
printf("Open failed.\n");
return;
}
for(i=0; i<n; i++) {
fprint(fp, "%s#", directory[i].name);
fprint(fp, "%s#", directory[i].number);
fprint(fp, "%s#", directory[i].email);
fprint(fp, "%s#\n", directory[i].group);
}
fclose(fp);
}
- search()
int search(char *name) {
int i;
for (i=0; i<n; i++)
if (strcmp(name, directory[i].name)==0) {
return i;
}
}
return -1;
}
- print_person()
void print_person(Person p) {
printf("%s:\n", p.name);
printf(" Phone:%s:\n", p.name);
printf(" Email:%s:\n", p.email);
printf(" Group:%s:\n", p.group);
}
- status()
void status() {
int i;
for (i=0; i<n; i++)
print_person(dicrectory[i]);
printf("Total %d persons. \n", n);
}
- find()
void find(char *name) {
int index = search(name);
if (index==-1) {
printf("No person named '%s' exists/ \n", name);
else
print_person(directory[index]);
}
- remove()
void remove(char *name) {
int i= search(name); // return -1 if not exists
if (i== -1) {
printf("No persion named '%s' exists.\n", name);
return;
}
int j = i;
for (; j<n-1; j++) {
directory[j] = directory[j+1];
}
n--;
printf("'%s' was deleted successfully. \n", name);
}
구조체를 사용하여 프로그램을 표현하였다.
'CS > 자료구조' 카테고리의 다른 글
[인프런|11강] C로 배우는 자료구조 | 전화번호부 v5.0 (2) (0) | 2020.11.20 |
---|---|
[인프런|10강] C로 배우는 자료구조 | 전화번호부 v5.0 (1) (0) | 2020.11.19 |
[인프런|6,7,8강] C로 배우는 자료구조 | 전화번호부 v3.0 (0) | 2020.11.15 |
[인프런|5강] C로 배우는 자료구조 | 전화번호부 v2.0 (0) | 2020.11.14 |
[인프런|4강] C로 배우는 자료구조 | 전화번호부 v1.0 (0) | 2020.11.13 |