본문 바로가기

CS/자료구조

[인프런|9강] C로 배우는 자료구조 | 전화번호부 v4.0

전화번호부 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); 

}

 

 

구조체를 사용하여 프로그램을 표현하였다.