더 많은 항목 추가하기, 구조체(structure)
각 사람에 대해서 이름, 전화번호, 이메일 주소, 그리고 그룹을 지정할 수 있다. 단 이름을 제외한 다른 항목들은 비워둘 수도 있다.
한줄에 한명씩저장
이름 # 번호 # 이메일 # 그룹
*구조체
항상 가팅 붙어다녀야 하는 데이터를 별개의 변수들에 분산해서 저장하는 것은 바람직하지 않다.
어떤 한 사람의 이름, 전화번호, 이메일 주소 등이 그런 예이다.
c언어에서는 이런 경우 구조체(structure)를 사용한다.
*자료구조:
구조체
#pragma
warning(disable:4996)
#include
#include
#include
#define
CAPACITY 100
#define
BUFFER_LENGTH 100
typedef
struct person {
char* name;
char* number;
char* email;
char* group;
} Person;
//구조체 struct person을
정의하면서
// 동시에 그것을 Person으로 renaming했다.
// 이런식으로 사용할 경우 structure tag인 person을
생략해도 된다.
Person
directory[CAPACITY];
// person 타입의 배열 directory를
선언한다.
// number
of people in phone directory
int
read_line(FILE* fp, char str[], int n);
void
find(char* name);
void
status();
void
remove(char* name);
void
printf_person(Person p);
int
search(char* name);
void
handle_add(char* name);
void
add(char* name, char* number, char* email, char* group);
void
save(char* fileName);
int
compose_name(char str[], int limit);
void
load(char* fileName);
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)
//stdin 표준
키보드 입력 받기
// 아무것도
입력하지 않을경우 다시 반복문으로
continue;
command = strtok(command_line, " ");
// 공백문자를
기준으로 해서 문장을 단어로 짜른다.
if (strcmp(command, "read") == 0)
{
argument = 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)
{
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);
}
// compose_name은 나머지 토큰들을 merge하여 이름을 구성한다.
else if (strcmp(command, "status") == 0)
{
status();
}
else if (strcmp(command, "delete") == 0)
{
if (compose_name(name_str, BUFFER_LENGTH) <= 0)
{
printf("Invalid arguments. \n");
continue;
}
remove(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 arguments.\n");
continue;
}
save(argument);
}
else if (strcmp(command, "exit") == 0)
break;
}
return 0;
}
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);
}
int
compose_name(char str[], int limit) {
char* ptr;
int length = 0;
ptr = strtok(NULL, " ");
if (ptr == NULL)
return 0;
// 빈값이라면 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);
// \0로
끝난다는 가정하에 동작함
length += strlen(ptr);
}
}
return length;
}
//command_lien의 남아있는
토큰들을 모두 합쳐 이름을 나타내는 문자열을 구성한다.
//토큰과 토큰 사이에 하나의
공백문자를 삽입한다.
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#\n", directory[i].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++;
// 모든
항목들은 strdup로 복제하여 저장한다.
}
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));
// 왼쪽
조건이 안되면 오른쪽을
// 오른쪽
조건 안되면 왼쪽을 택해라
}
// 존재하지 않는 항목들을 하나의
공백문자로 구성된 문자열로 대체한다.
// add 호출 라인이 복잡해진것은
앞단에 펑션중 add와 통일하기 위한 것이다.
int
search(char* name)
{
int i;
for (i = 0; i < n; i++)
{
if (strcmp(name, directory[i].name) == 0)
{
return i;
}
}
return -1;
}
void
printf_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
remove(char* name) {
int i = search(name);
// returns - 1 if not exists
if (i == -1)
{
printf("No person named '%s' exitsts.\n", name);
return;
}
int j = i;
for (j; j < n - 1; j++)
{
directory[j] = directory[j + 1];
//구조체
변수간의 치환연산이 지원되므로 멤버항목들을 따로따로 치환할 필요가 없다.
}
n--;
printf("'%s' was deleted successfully. \n", name);
}
void
status() {
int i;
for (i = 0; i < n; i++)
printf_person(directory[i]);
printf("Total %d persons. \n", n);
}
void
find(char* name) {
int index = search(name);
// search를
한다.
if (index == 1)
// search의
결과가 1이면 사람이 없다고 출력한다.
printf("No person named '%s' exist. \n", name);
else
printf_person(directory[index]);
}
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;
}
댓글 없음:
댓글 쓰기