[7] C review < 전화번호부 알고리즘 version4.0 >Language/자료구조2021. 11. 23. 21:36
Table of Contents
동장방식 : 이름과 번호 뿐아니라 email과 소속그룹까지 추가해보자 >> 구조체 이용 , 만약 번호,email,group이 없다면 빈칸으로 둔다. 또한 이름이 하나 이상의 단어로 구성될 수 있으며 단어사이에 여러 개의 공백이 있을 경우 한칸의 공백으로 저장한다.
생각해야할 점 2가지 !
1. 구조체를 어떻게 사용할 것인가 ?
typedef struct person
{
char *name;
char *number;
char *email;
char *group;
} Person;
Person directory[CAPACITY]; // Person type의 배열 directory를 선언.
person struct를 Person으로 재선언.
2. 빈칸을 어떻게 처리 할 것인가?
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); // strcat는 모두 NULL로 끝나야 정상작동
length += strlen(ptr);
}
}
return length;
}
배열 하나를 새롭게 만들어서 추가한다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define CAPACITY 100
#define BUFFER_LENGTH 100
typedef struct person
{
char *name;
char *number;
char *email;
char *group;
} Person;
Person directory[CAPACITY]; // Person type의 배열 directory를 선언.
int n = 0;
int read_line(FILE *fp, char *str, int n);
void load(char *fileName);
int compose_name(char *str, int limit);
void handle_add(char *name);
void find(char *name);
void status();
void delete (char *name);
void save(char *fileName);
void add(char *name, char *number, char *email, char *group);
int search(char *name);
void print_person(Person p);
int main(void)
{
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)
{
argument = strtok(NULL, " ");
if (argument == NULL)
{
printf("Invalid argeuments.\n");
continue;
}
load(argument);
}
else if (strcmp(command, "add") == 0)
{
if (compose_name(name_str, BUFFER_LENGTH) <= 0)
{
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("Name required.\n");
continue;
}
delete (name_str);
}
else if (strcmp(command, "save") == 0)
{
argument = strtok(NULL, " ");
if (strcmp(argument, "as") != 0)
{
printf("Invalid arguments.\n");
continue;
}
argument = strtok(NULL, " ");
if (argument == NULL)
{
printf("Invalid argeuments.\n");
continue;
}
save(argument);
}
else if (strcmp(command, "exit") == 0)
{
break;
}
}
return 0;
}
int read_line(FILE *fp, char *str, int n)
{
int ch, i = 0;
while ((ch = fgetc(fp)) != '\n' && ch != EOF)
{
if (i < n)
{
str[i++] = ch;
}
}
str[i] = '\0';
return i;
}
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);
}
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++;
}
// 'a'는 단일 문자 리터럴이고 "a"는 'a'와 null을 포함하는 문자열 리터럴이다.
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); // strcat는 모두 NULL로 끝나야 정상작동
length += strlen(ptr);
}
}
return length;
}
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));
}
void save(char *fileName)
{
int i;
FILE *fp = fopen(fileName, "w");
if (fp == NULL)
{
printf("Open failed.\n");
return;
}
for (i = 0; i < n; i++)
{
fprintf(fp, "%s#", directory[i].name);
fprintf(fp, "%s#", directory[i].number);
fprintf(fp, "%s#", directory[i].email);
fprintf(fp, "%s#", directory[i].group);
}
fclose(fp);
}
int search(char *name)
{
int i;
for (i = 0; i < n; i++)
{
if (strcmp(name, directory[i].name) == 0)
{
return i;
}
}
return -1;
}
void delete (char *name)
{
int i = search(name);
if (i == -1)
{
printf("No person named %s exists.\n", name);
return;
}
int j = i;
for (; j < n; j++)
{
directory[j] = directory[j + 1];
}
n--;
printf("%s was deleted successfully.\n");
}
void find(char *name)
{
int index = search(name);
if (index == -1)
{
printf("No person named %s exists.\n", name);
}
else
print_person(directory[index]);
}
void print_person(Person p)
{
printf("%s:\n", p.name);
printf(" Phone:%s\n", p.number);
printf(" Email:%s\n", p.email);
printf(" Group:%s\n", p.group);
}
void status()
{
int i;
for (i = 0; i < n; i++)
{
print_person(directory[i]);
}
printf("Total %d persons.\n", n);
}
'Language > 자료구조' 카테고리의 다른 글
[10] C review < 연결리스트의 개념 > (0) | 2021.11.25 |
---|---|
[8] C review < 전화번호부 알고리즘 version5.0 preview > (0) | 2021.11.25 |
[6] C review < 전화번호부 알고리즘 version3.0 > (0) | 2021.11.22 |
[5] C review < 전화번호부 알고리즘 version2.0 > (0) | 2021.11.22 |
[4] C review < 전화번호부 알고리즘 version1.0 > (0) | 2021.11.22 |
@Return :: Return
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!