소켓프로그램에 대해 공부하였다. 자세히 들어가 공부하는 것 아니지만 서버랑 클라이언트랑 가위바위 보를 하는 프로그램을 통하여 소켓의 생성원리, fork()함수, pipe()함수에 대해 다뤄보는 소스를 분석해보자.

일단 소켓을 무엇인지 알아야 소켓을 생성를 하지 않겠는가. 난 처음에 소켓을 하나의 패킷이라고 생각했지만 그런 개념을 아니였다. 서로 멀리 떨어져 있는 매개체를 연결해주는 역활을 해야된다고 생각해야되나..? 하여튼 그런 개념을 소켓이라고 한다. 자 그럼 한번 소스를 봐볼까

------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>

#define BUFSIZE 100
void error_handling(char *message);
void z_handler(int sig);
int who_win(int a, int b);
------------------------------------------------------------------------------------------
여기까지는 함수를 사용할 헤더파일 정의 또한 밑에서 사용할 사용자 정의 함수를 각각 선언하였다.

-------------------------------------------------------------------------------------------
int
main(int argc, char **argv)
{
int fd1[2], fd2[2];

char buffer[BUFSIZE];
char intro[]="Input(gawi : 0, bawi : 1, bo : 2) : ";
char win[] = "You Win!!\n";
char lose[] = "You Lose!!\n";
char no_winner[] = "Oh same!! Re try!!\n";

int serv_sock;
int clnt_sock;
struct sockaddr_in serv_addr;
struct sockaddr_in clnt_addr;
struct sigaction act;
int str_len, state, addr_size;
pid_t pid;
---------------------------------------------------------------------------------------------
이부분은 각각 사용할 변수와 구조체를 선언하였다. 맨 마지막에 형이 없이 pid_t를 선언한 부분이 있는데 이걸 사용자 정의 변수라 한다. 사용자가 알아보기 싶게할때 쓰거나 만약 int형이 시스템 마다 틀려서 define해서 쓸수 있게 하여 확장성 높일때 사용한다.

-------------------------------------------------------------------------------------------
if( argc != 2 )
{
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
-------------------------------------------------------------------------------------------
이 프로그램은 서버 프로그램이다. 서버프로그램은 실행파일명 하고 뒤에 클라이언트와 접속할수 있는 포트 번호를 써줘야 하기때문에 인수가 2가 아니면 포트를 사용하라고 에러문이 뜨게 한다.

-------------------------------------------------------------------------------------------
if( pipe(fd1) < 0 || pipe(fd2) < 0 ) error_handling("pipe() error!");
-------------------------------------------------------------------------------------------
파이프 함수를 정의 하여 사용한다. 만약 파이프 함수가 에러가 나면 -1값을 리턴하는데 이때 오류문을 출력하는 구문

------------------------------------------------------------------------------------------
act.sa_hander = z_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
state = sigaction(SIGCHLD, &act, 0);
if( state != 0 ) error_handling("sigaction() error");
-------------------------------------------------------------------------------------------
struct sigaction{
void (*sa_handler) int /* 취해질 행동 */
sigset_t sa_mask /*시그널을 처리할 동안 추가의 시그널을 봉쇄 */
int sa_flags /*시그널을 형태에 영향을 미칠 플래그들 */
void(*sa_sigaction ) (int, siginfo_t *, vodi *) /* 시그널 핸들러에 대한 포인터 */

시그널 구조체에 각각의 값을 넣는 구문이다. 두번째 sigemptyset()는 초기화 하란 뜻이다. SIGCHLD는 자식프로세스의 신호에 대한 값으로 시스템에서 SIGCHLD가 발생이 되면 &act에 걸린 핸들러를 호출하는 구문이다.


---------------------------------------------------------------------------------------------
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
---------------------------------------------------------------------------------------------
스트림형 소켓(TCP통신)을 생성한다.

-------------------------------------------------------------------------------------------
memset(&serv_addr, 0, sizeof(serv_addr));
-------------------------------------------------------------------------------------------
serv_addr주소 부터 serv_addr 주소크기까지 0으로 채운라는 뜻이다 즉 초기화시키는 뜻을 가지고 있다.

------------------------------------------------------------------------------------------
serv_addr.sin_family = AF_INET;
-------------------------------------------------------------------------------------------
아아피 버전4 주소를 사용하겠다는의미

-------------------------------------------------------------------------------------------
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-------------------------------------------------------------------------------------------
htonl ->호스트의 네트워크 바이트 순서를 32비트를 사용하겠다는 의미 리틀 엔디안과 빅 엔디안의 차이 즉 CPU계열에 메모리 저장방식이 서로 틀려도 이것에 상관없이 사용할수 있도록 한다. (INADDR_ANY)자기 아이피 주소할당

-----------------------------------------------------------------------------------------
serv_addr.sin_port = htons(atoi(argv[1]));
-----------------------------------------------------------------------------------------
htons ->포트정보를 바꿔주겠단 의미로써 16-비트 정수로 된 호스트 바이트 오더를 네트웍 바이트 오더로 변환하는 함수이다. htons 함수는 SOCKADDR_IN 구조체에 저장되기 전에 포트 번호를 네트웍 바이트 오더로 변환하는데 자주 사용 한다

-------------------------------------------------------------------------------------------
if( bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) )
error_handling("bind() error");
--------------------------------------------------------------------------------------------
bind 소켓에다 주소를 할당 해주는 함수
ipv4에 할당된 주소를 표준된 주소로 형변환 할려는 것

-------------------------------------------------------------------------------------------
if( listen(serv_sock, 5)) error_handling("listen() error");
-------------------------------------------------------------------------------------------
listen 소켓연결 요청 대기 상태 5는 큐의 크기(클라이언트가 여러명들어갈수 있게

-------------------------------------------------------------------------------------------
while(1)
{
addr_size = sizeof(clnt_addr);

clnt_sock = accept(serv_sock, (struct sockaddr*) &clnt_addr, &addr_size);
if( clnt_sock == -1 ) continue;
-------------------------------------------------------------------------------------------
연결요청이 들어오면 받아들이는 함수(또하나의 소켓을 만들어준다. 클라인트 접속한 정보들이 구조체에 채워지고 에러가 나면 다시 처음으로 돌아간다.

-----------------------------------------------------------------------------------------
if( (pid = fork()) == -1 )
{
close(clnt_sock);
continue;
}
------------------------------------------------------------------------------------------
자식 프로세스 생성하다 오류나면 반복문 처음으로 돌아감

------------------------------------------------------------------------------------------
else if( pid > 0 )
{
int result;
puts("connection success");

close(clnt_sock);
//클라이언트 소켓을 닫아준다
//나중에 자식프로세스가 닫아주면 완전히 닫혀진다. (부모가 미리 닫는다.)

write(1, intro, sizeof(intro));
//첫번재 인수는 파일디스크립트(파일티스크립트는 시스템이 할당받은 미리 정해진 일련번호 라고 생각하면 된다. 보통 0은 표준입력 1은 표준출력 2는 표준에러를 뜻한다),intro 출력하라는 의미

read(0, buffer, BUFSIZE);
//사용자가 가위,바위,보를 저장한다.

read(fd1[0], &buffer[1], BUFSIZE - 1);
//클라이언트 가위바위보 낸걸 fd1[1]에서 서버 fd1[0]으로 읽어온다(파이브 함수를 통해서).

result = who_win(buffer[0], buffer[1]);
//buffer[0]에 서버 , buffer[1]에 클라이언트

if( result == 0 )
{
write(1, no_winner, sizeof(no_winner));
write(fd2[1], no_winner, sizeof(no_winner));
}
else if( result == 1 )
{
write(1, win, sizeof(win));
write(fd2[1], lose, sizeof(lose));
}
else
{
write(1, lose, sizeof(lose));
write(fd2[1], win, sizeof(win));
}
//이겼는지 졌는지 비겼는지를 출력하는 조건문이다.
}
--------------------------------------------------------------------------------------------
부모프로세스가 해야할것

---------------------------------------------------------------------------------------------
else
{
close(serv_sock);

write(clnt_sock, intro, sizeof(intro));
read(clnt_sock, buffer, BUFSIZE);
write(fd1[1], buffer, 1);
str_len = read(fd2[0], buffer, BUFSIZE);

write(clnt_sock, buffer, str_len);

puts("connection end");
close(clnt_sock);
exit(0);
}
----------------------------------------------------------------------------------------------
자식프로세스는 클라이언트에게 서버가 낸 가위바위보 정보를 전달해주는 역활을 한다.


}
return 0;
}

---------------------------------------------------------------------------------------------
void
z_handler(int sig)
{
pid_t pid;
int rtn;

pid = waitpid(-1, &rtn, WNOHANG);
//waitpid는 프로세스의 번호를 받는다. 첫번째 인자는 어떤프로세스에게 pid를 받을지 쓴다.
//(-1는 기달렸다가 먼저 종료되는 프로세스를 이미로 받는다.
//셋번째인자는 기달려도 종료된 자식프로세스가 신호를 않보내면 자동적으로 종료

printf("killed zombie pid : %d \n", pid);
printf("returned data : %d \n\n", WEXITSTATUS(rtn));
//자식프로세스가 죽었다는 신호(숫자)를 리턴값으로 전달해주는 함수
}
-------------------------------------------------------------------------------------------
자식프로세스 신호의 핸드러에 관한 함수이다.

-------------------------------------------------------------------------------------------
int
who_win(int a, int b)
{
if( a == b ) return 0;

else if( a % 3 == (b + 1) % 3) return 1;
//서버가 이길경우

else return -1;
//클라이언트가 이길 경우
}
---------------------------------------------------------------------------------------------
클라이언트와 서버간에 가위바위보 비교

--------------------------------------------------------------------------------------------
void
error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
---------------------------------------------------------------------------------------------
에러문 출력


#include <stdio.h>
#include <string.h>
#include <windows.h>

#define TRUE        1
#define FALSE       0

#define REG         1
#define VIEW        2
#define SEARCH      3
#define SAVE        4
#define LOAD        5
#define EXIT        6

#define S_ITEM  1
#define S_NAME  2
#define S_PHONE  3
#define S_ADDRESS 4
#define S_GROUP  5
#define S_MD  6
#define S_EXIT  7

#define LIST_MAX    100

typedef struct _list
{
    char name[255];
    char phone[255];
    char address[255];
    char group[255];
    int used;
    int searched;
}LIST;

void Main_Menu(int *total);         // 메인 메뉴 출력
void Exit(void);           // 프로그램 종료
void Registration(LIST *member, int *total);    // 새 리스트 등록
int Auto_num(LIST* member);         // 자동 번지 설정
void Contents_input(char *title, char *contents);   // 내용 저장
void List_view(LIST *member, int total);     // 리스트 보기
void File_save(LIST *member, int total);     // 리스트 파일 저장
void File_load(LIST *member, int *total);     // 리스트 파일 읽기
void Search(LIST *member, int *total);      // 리스트 검색
void Search_Menu(void);          // 리스트 검색 메뉴
void Search_init(LIST *member);        // 리스트 검색 초기화
void Search_view(LIST *member);        // 리스트 검색 결과 출력
void Search_item(LIST *member);        // 리스트 항목별 검색
void Search_string(LIST *member, int s_title);    // 리스트 문자별 검색
void Search_MD_Menu(void);         // 리스트 수정/삭제 메뉴
void Search_MD(LIST *member, int *total);     // 리스트 수정/삭제
void Re_registration(LIST *member, int s_item, int title); // 리스트 수정 등록


/* MAIN START */
void main()
{
    LIST member[LIST_MAX] = {0};    // 멤버 등록 정보
    int choice = 0;                 // 메뉴 선택
    int total =0;                   // 리스트 등록 수

    while(TRUE)
    {
        Main_Menu(&total);

        printf("Choice >> ");
        scanf("%d", &choice);
        fflush(stdin);

        switch(choice)
        {
        case REG    : { Registration(member, &total);   break; }
        case VIEW   : { List_view(member, total);  break; }
        case SEARCH : { Search(member, &total);   break; }
        case SAVE   : { File_save(member, total);  break; }
        case LOAD   : { File_load(member, &total);  break; }
        case EXIT   : { Exit();       break; }
        }
  system("pause");
    }
}


/* 메인 메뉴를 출력 합니다. */
void Main_Menu(int *total)
{
    system("cls");
    puts("");
    puts("┏━━━━━━━━━━━━━━━━━━┓");
    puts("┃          MY  ADDRESS BOOK          ┃");
    puts("┣━━━━━━━━━━━━━━━━━━┫");
    puts("┃   1. REGISTRATION                  ┃");
    puts("┃   2. LIST VIEW                     ┃");
    puts("┃   3. SEARCH <MODIFY / DELETE>      ┃");
    puts("┃   4. FILE SAVE                     ┃");
    puts("┃   5. FILE LOAD                     ┃");
    puts("┃   6. EXIT                          ┃");
    puts("┣━━━━━━━━━━━━━━━━━━┫");
 printf("┃   Total of list : %3d item.        ┃\n", *total);
 puts("┗━━━━━━━━━━━━━━━━━━┛");
    puts("");
}


/* 프로그램을 종료 합니다. */
void Exit(void)
{
    puts("");
    puts("┏━━━━━━━━━━━━━━━━━━┓");
    puts("┃            PROGRAM  END            ┃");
    puts("┗━━━━━━━━━━━━━━━━━━┛");
    puts("");
    exit(TRUE);
}


/* 새로운 주소를 등록 합니다. */
void Registration(LIST *member, int *total)
{
    int num, flag, i;
    char group[5][10] = {"FAMILY", "RELATIVE", "FRIEND", "COLLEAGUE", "Ete."};
    char item[5], decision;

 do
 {
  system("cls");

  if(*total == LIST_MAX)
  {
   puts("LIST FULL, Registration failed !");
   return;
  }

  do
  {
   flag = FALSE;
   num = Auto_num(member);
   printf("Auto register : [%3d] >> ", ++num);
   gets(item);
       
   if(item[0] != '\0')
   {
    num = atoi(item);
    if(member[num-1].used != 0)
    {
     flag = TRUE;
     printf("%d of list is already registered.\n", num);
     puts("Please, try again");
     system("pause");
     system("cls");
    }
   }
  }while(flag == TRUE);
  
  printf("\nRegistration : [%3d]\n", num);
  Contents_input("NAME\t", member[num-1].name);
  Contents_input("PHONE\t", member[num-1].phone);
  Contents_input("ADDRESS\t", member[num-1].address);

  do
  {
   for(i = 0; i < 5; i++)
    printf("\t%d. %s", i+1, group[i]);
   printf("\nGROUP\t>> ");
   scanf("%d", &i);
   fflush(stdin);
  }while (i < 0 && i > 6);
   
  strcpy(member[num-1].group, group[i-1]);
   
  printf("\nDo you want save? <N/n> or other keys >> ");
  decision = getchar();
  fflush(stdin);
  puts("");

  if( strchr("Nn", decision) != NULL )
   puts("SAVE Canceled.\n");
  else
  {
   member[num-1].used = 1;
   printf("SAVE Complete. Total of list : %3d item.\n", ++*total);
  }

  printf("\nDo you want input continue? <Y/y> or other keys >> ");
  decision = getchar();
  fflush(stdin);
  puts("");
 }while(strchr("Yy", decision) != NULL);
}


/* 빈번지를 자동으로 설정 합니다. */
int Auto_num(LIST *member)
{
    int i=0;
    while(member[i].used != 0)
  i++;
    return (i);
}


/* 타이틀을 출력하고 입력된 내용을 등록 합니다. */
void Contents_input(char *title, char *contents)
{
    do
    {
        printf("%s>> ", title);
        gets(contents);
    }while(contents[0] == '\0');
}


/* 등록된 리스트를 출력 합니다. */
void List_view(LIST *member, int total)
{
 int i;
 system("cls");

 if(total == 0)
 {
  puts("List is empty.");
  return;
 }

 puts("No.\t NAME\t PHONE\t ADDRESS\t GROUP\t");
 for(i = 0; i < LIST_MAX ; i++)
 {
  if(member[i].used != 0)
  {
   printf("[%3d]\t %s\t %s\t %s\t %s\t\n",
    i+1, member[i].name, member[i].phone, member[i].address, member[i].group);
  }
 }
}


/* 리스트를 파일로 저장 합니다. */
void File_save(LIST *member, int total)
{
 FILE *fp;
 int i;

 if(total == 0)
 {
  puts("List is empty.");
  puts("SAVE Canceled.\n");
  return;
 }
 
 fp = fopen("my_list.txt", "w");
 if(fp == NULL)
 {
  puts("Don't have enough of storage capacity.");
  puts("SAVE Canceled.\n");
  return;
 }

 for(i = 0; i < LIST_MAX ; i++)
 {
  if(member[i].used == 1)
  {
   fprintf(fp, "%d>%s>%s>%s>%s\n",
    i, member[i].name, member[i].phone, member[i].address, member[i].group);
   printf("[%3d]\t %s\t %s\t %s\t %s\t\n",
    i+1, member[i].name, member[i].phone, member[i].address, member[i].group);
  }
 }
 puts("SAVE Complete !!!\n");
 fclose(fp);
}


/* 리스트 파일을 읽어 옵니다. */
void File_load(LIST *member, int *total)
{
 FILE *fp;
 char decision, ch;
 int i, num;

 fp = fopen("my_list.txt", "r");

 if(fp == NULL)
 {
  puts("Can't read [my_list.txt] file.");
  puts("LOAD Canceled.\n");
  return;
 }

 if(*total != 0)
 {
  printf("\nDo you want file load? Your current data will be lost !\n");
  printf("<Y/y> or other keys >> ");
  decision = getchar();
  fflush(stdin);
  puts("");

  if( strchr("Yy", decision) != NULL )
  {
   *total = 0;
   for(i = 0; i < LIST_MAX; i++)
    member[i].used = 0;
   puts("Memory Initialized.\n");
  }
  else
  {
   puts("LOAD Canceled.\n");
   fclose(fp);
  }
 }

 puts("Data Loading...\n");
 while( (ch = fgetc(fp)) != EOF )
 {
  num = 0;
  do
  {
   num = num * 10 + (ch -'0');
  }while((ch = fgetc(fp)) != '>');

  i = 0;
  while((ch = fgetc(fp)) != '>')
   member[num].name[i++] = ch;
  member[num].name[i] = '\0';

  i = 0;
  while((ch = fgetc(fp)) != '>')
   member[num].phone[i++] = ch;
  member[num].phone[i] = '\0';

  i = 0;
  while((ch = fgetc(fp)) != '>')
   member[num].address[i++] = ch;
  member[num].address[i] = '\0';

  i = 0;
  while((ch = fgetc(fp)) != '\n')
   member[num].group[i++] = ch;
  member[num].group[i] = '\0';

  member[num].used = 1;

  ++*total;

  printf("[%3d]\t %s\t %s\t %s\t %s\t\n",
   num+1, member[num].name, member[num].phone, member[num].address, member[num].group);
  Sleep(300);
 }
 puts("\nLOAD Complete !!!\n");
 fclose(fp);
}


/* 검색 메뉴를 출력 합니다. */
void Search_Menu(void)
{
    system("cls");
    puts("");
    puts("┏━━━━━━━━━━━━━━━━━━┓");
    puts("┃            SEARCH MENU             ┃");
    puts("┣━━━━━━━━━━━━━━━━━━┫");
    puts("┃   1. Item Number Search            ┃");
    puts("┃   2. Name Search                   ┃");
    puts("┃   3. Phone Number Search           ┃");
    puts("┃   4. Address Search                ┃");
    puts("┃   5. Group Search                  ┃");
    puts("┃   6. Modify / Delete               ┃");
    puts("┃   7. EXIT                          ┃");
 puts("┗━━━━━━━━━━━━━━━━━━┛");
    puts("");
}


/* 수정/검색 메뉴를 출력 합니다. */
void Search_MD_Menu(void)
{
 puts("");
    puts("┏━━━━━━━━━━━━━━━━━━┓");
    puts("┃   1. Modify                        ┃");
    puts("┃   2. Delete                        ┃");
    puts("┃   3. EXIT                          ┃");
 puts("┗━━━━━━━━━━━━━━━━━━┛");
    puts("");
}


/* 리스트를 항목별로 검색 합니다. */
void Search(LIST *member, int *total)
{
 int choice, cnt = 0;

 while(TRUE)
 {
  Search_Menu();

  if(*total == 0)
  {
   puts("List is empty.");
   puts("SEARCH Canceled.\n");
   return;
  }
  printf("Choice >> ");
        scanf("%d", &choice);
        fflush(stdin);

        switch(choice)
        {
        case S_ITEM  : { Search_item(member);    break; }
        case S_NAME  : { Search_string(member, S_NAME);  break; }
        case S_PHONE : { Search_string(member, S_PHONE);  break; }
        case S_ADDRESS : { Search_string(member, S_ADDRESS); break; }
        case S_GROUP : { Search_string(member, S_GROUP);  break; }
        case S_MD  : { Search_MD(member, total);     break; }
  case S_EXIT  : { return; }
        }
 }
}


/* 검색 조건을 초기화 합니다. */
void Search_init(LIST *member)
{
 int i;
 for(i = 0; i < LIST_MAX; i++)
  member[i].searched = 0;
}


/* 검색된 결과를 출력 합니다. */
void Search_view(LIST *member)
{
 int i;

 puts("No.\t NAME\t PHONE\t ADDRESS\t GROUP\t");
 for(i = 0; i < LIST_MAX ; i++)
 {
  if(member[i].searched == 1)
  {
   printf("[%3d]\t %s\t %s\t %s\t %s\t\n",
    i+1, member[i].name, member[i].phone, member[i].address, member[i].group);
  }
 }
}


/* 항목 번호로 검색을 수행 합니다. */
void Search_item(LIST *member)
{
 int num;
 char decision;

 do
 {
  Search_init(member);
  printf("Item Number >> ");
  scanf("%d", &num);
  fflush(stdin);

  if(member[num-1].used == 0)
  {
   printf("[%3d] Item is Empty !!!\n", num);
   printf("Do you want item search continue? (Y/y) >> ");
   decision = getchar();
   fflush(stdin);
  }
  else
  {
   member[num-1].searched = 1;
   Search_view(member);
   printf("Do you want item search continue? (Y/y) >> ");
   decision = getchar();
   fflush(stdin);
  }
 }while(strchr("Yy", decision) != NULL);
}


/* 타이틀별로 검색을 수행 합니다. */
void Search_string(LIST *member, int s_title)
{
 char s_buf[255], decision;
 int i, cnt;

 do
 {
  cnt = 0;

  Search_init(member);
  printf("Search >> ");
  scanf("%s", &s_buf);
  fflush(stdin);

  for(i = 0; i < LIST_MAX; i++)
  {
   if(member[i].used != 0)
   {
    switch(s_title)
    {
    case S_NAME :
     {
      if(strstr(member[i].name, s_buf) != NULL)
      {
       member[i].searched = 1;
       cnt++;
      }
     }
    case S_PHONE :
     {
      if(strstr(member[i].phone, s_buf) != NULL)
      {
       member[i].searched = 1;
       cnt++;
      }
     }
    case S_ADDRESS :
     {
      if(strstr(member[i].address, s_buf) != NULL)
      {
       member[i].searched = 1;
       cnt++;
      }
     }
    case S_GROUP :
     {
      if(strstr(member[i].group, s_buf) != NULL)
      {
       member[i].searched = 1;
       cnt++;
      }
     }
    }
   }
  }

  if(cnt == 0)
  {
   printf("[%s] is not match !!!", s_buf);
   printf("Do you want search continue? (Y/y) >> ");
   decision = getchar();
   fflush(stdin);
  }
  else
  {
   Search_view(member);
   printf("Do you want search continue? (Y/y) >> ");
   decision = getchar();
   fflush(stdin);
  }
 }while(strchr("Yy", decision) != NULL);
}


/* 검색된 목록에서 리스트를 수정/삭제 합니다. */
void Search_MD(LIST *member, int *total)
{
 int i, flag=0;
 char decision, mode, choice, title;

 for(i = 0; i < LIST_MAX ; i++)
 {
  if(member[i].searched == TRUE)
  {
   flag = TRUE;
  }
 }
 
 if(flag == FALSE)
 {
  puts("Search result don't exist");
  system("pause");
  return;
 }

 else
 {
  do
  {
   flag = FALSE;
   Search_MD_Menu();
   printf("Choice >> ");
   mode = getchar();
   fflush(stdin);
   Search_view(member);

   if(mode == '1')
   {
    do
    {
     printf("Motify item choice >> ");
     choice = getchar();
     fflush(stdin);

     if(member[choice-'0'-1].searched == FALSE)
     {
      puts("This item is not searched.");
     }
    }while(member[choice-'0'-1].searched != TRUE);
    
    printf("\n\t\t1.NAME 2.PHONE 3.ADDRESS 4.GROUP\n");
    printf("Motify title choice >> ");
    title = getchar();
    fflush(stdin);
    
    Re_registration(member, choice - '0', title-'0'+1);
    printf("\nDo you want Motify item continue? (Y/y) or other keys >> ");
    decision = getchar();
    fflush(stdin);
   }
   else if(mode == '2')
   {
    do
    {
     printf("\nDelete item choice >> ");
     choice = getchar();
     fflush(stdin);

     if(member[choice-'0'-1].searched == FALSE)
     {
      puts("This item is not searched.");
     }
    }while(member[choice-'0'-1].searched != TRUE);

    printf("\nDo you want Delete? (Y/y) or other keys >> ");
    decision = getchar();
    fflush(stdin);

    if(strchr("Yy", decision) != NULL)
    {
     member[(choice-1) - '0'].used = 0;
     printf("\nDELETE Complete. <Total of list : %3d item.>\n", --*total);
    }
    else
    {
     puts("DELETE Canceled");
    }
    printf("\nDo you want Delete item continue? (Y/y) or other keys >> ");
    decision = getchar();
    fflush(stdin);
   }
   else return;
  }while(strchr("Yy", decision) != NULL);
 }
}


/* 리스트를 수정 등록 합니다. */
void Re_registration(LIST *member, int s_item, int title)
{
    int i;
    char group[5][10] = {"FAMILY", "RELATIVE", "FRIEND", "COLLEAGUE", "Ete."};
    char decision;

 printf("\nRegistration : [%3d]\n", s_item);
 switch(title)
 {
 case S_NAME  : {Contents_input("NAME\t", member[s_item-1].name);  break;}
 case S_PHONE : {Contents_input("PHONE\t", member[s_item-1].phone);  break;}
 case S_ADDRESS : {Contents_input("ADDRESS\t", member[s_item-1].address); break;}
 case S_GROUP : 
  {
   Contents_input("GROUP\t", member[s_item-1].group);
   do
   {
    for(i = 0; i < 5; i++)
     printf("\t%d. %s", i+1, group[i]);
    printf("\nGROUP\t>> ");
    scanf("%d", &i);
    fflush(stdin);
   }while (i < 0 && i > 6);
   
   strcpy(member[s_item-1].group, group[i-1]);
   break;
  }
 }
   
 printf("\nDo you want save? <N/n> or other keys >> ");
 decision = getchar();
 fflush(stdin);
 puts("");
 
 if( strchr("Nn", decision) != NULL )
  puts("MODIFY Canceled.\n");
 else
 {
  member[s_item-1].used = 1;
  puts("MODIFY Complete.\n");
 }
}

//atof() 만들기
//입력은 char str[MAX]; scanf("%s",str);
//출력은 printf("%d",num);
//1) str[0]가 음수인지 check
//2) 소수점 이상, 이하 분리 해서 처리
//1-2)결과 종합해서 출력

 

#include<stdio.h>
#include<string.h>
#define MAX 100

void main()
{
    char str[MAX];
    double num1=0, num2=0;
    int i=0, flag=0;

    printf("숫자형의 문자열을 입력하시오 : ");
    scanf("%s",str);
    fflush(stdin);

    if(str[0] == '-')
    {
        i++;
        flag++;
    }

    for( ; str[i]!='.' ; i++)
    {
        if(i != flag)
            num1*=10;
        num1 += (str[i] - '0');
    }
    for(i=strlen(str)-1 ; str[i]!='.' ; i--)
    {
        num2 += (str[i] - '0');
        num2 *= 0.1;
    }
    printf("==== Result :%f ====\n", !flag ? (num1 + num2) : -(num1 + num2));
}


+ Recent posts