C++ 구조체 코딩 질문합니다.

조회수 1745회
#include <stdio.h>
#include <conio.h> //
#include <string.h> 


typedef struct U_Information
{  //구조체 작성 
char Name [10];
char RRN [15];
char ID [16];
char Password [16];
char Phone [16];
char Address [40];
char Email [20];

 } UI;

char gfile_name[256]="User Data1.txt"; //파일이름 설정 

#define MAX_USER_DATA  100 //

UI g_user_data[MAX_USER_DATA]; //
int g_user_count; //

void ReadUserData() //저장된 유저정보 읽어오기 
{ 
  int index = 0; 
  FILE *p_file = fopen(gfile_name, "r"); 
  if(p_file != NULL){ 
  fread(&g_user_count, sizeof(int), 1, p_file); //
  for(index = 0; index < g_user_count; index++){ 
      fread(g_user_data + index, sizeof(UI), 1, p_file); //
  } 
  fclose(p_file); 
  } 
} 

void SaveUserData() //유저정보를 파일에 저장시키기 
{ 
  int index = 0; 
  FILE *p_file = fopen(gfile_name, "w"); 
  if(p_file != NULL){ 
  fwrite(&g_user_count, sizeof(int), 1, p_file); //
  for(index = 0; index < g_user_count; index++){ 
      fwrite(g_user_data + index, sizeof(UI), 1, p_file); //
  } 
      fclose(p_file);} } 

void GetPassword(char parm_password[]) //비밀번호 입력시 *로 보이게 하기 
{ 
  int input = 0, index = 0; 
  while(input != 13){ 
  input = getch(); //
  if(input == 13) parm_password[index] = 0; //
  else { 
      printf("*"); 
      parm_password[index++] = input; //
  } 
  } 
  printf("\n"); 
} 

void UserRegister() //유저 정보를 입력해 회원 아이디 만들기 
{ 
  printf("회원 등록하시려면 다음 정보를 입력하십시오.\n\n"); 

  printf("1. Input Name: "); 
  gets(g_user_data[g_user_count].Name);
  printf("2. Input RRN: "); 
  gets(g_user_data[g_user_count].RRN);
  printf("3. Input ID: "); 
  gets(g_user_data[g_user_count].ID);
  printf("4. Input Password: "); 
  gets(g_user_data[g_user_count].Password);
  printf("5. Input Phone Number: "); 
  gets(g_user_data[g_user_count].Phone);
  printf("6. Input Address: "); 
  gets(g_user_data[g_user_count].Address);
  printf("7. Input Email: "); 
  gets(g_user_data[g_user_count].Email);       

  g_user_count++; //

  printf("회원이 되셨습니다. 다시 로그인 해주십시오. \n\n"); 
} 


int main () //기본메일 (회원아이디 입력,비밀번호 입력) 
       //->성공시 성공 메세지,비밀번호 틀렸을 시 재입력 
      //-> 아이디가 틀린경우 OR 없는 경우 회원 등록을 할 것인지 물어보기 - YES시 회원정보 입력으로 넘어가기 NO시 다시입력하기 
{
 int index = 0, input = 0; 
  char id[16], password[16], success_login = 0; 

   ReadUserData(); //

  while(!success_login){ 
  printf("Input ID: "); 
  gets(id); 
  printf("Input Password: "); 
  GetPassword(password); 

  for(index = 0; index < g_user_count; index++){ //
      if(!strcmp(g_user_data[index].ID, id)){ //
          if(!strcmp(g_user_data[index].Password, password)){ //
              success_login = 1; //
              printf("로그인에 성공하셨습니다. \n\n"); 
          } else printf("암호가 옳바르게 입력되었는지 확인 하십시오. \n\n"); 
          break; 
      } 
  } 

  if(index == g_user_count){ //
      printf("ID가 등록이 되어있지 않습니다. 등록하시겠습니까? ( y / n ): "); 
      input = getche(); 
      printf("\n\n"); 
      if(input == 'y' || input == 'Y') UserRegister(); //
      else printf("다시 입력하십시오.\n\n"); 
  } 
  } 

  SaveUserData(); //
}

인터넷에서 카피한 내용입니다. 출처는http://www.tipssoft.com/bulletin/board.php?bo_table=old_bbs&wr_id=119 이곳에서 가져온거고요 조금 수정했습니다. 이해 안되는 명령어가 너무 많아서요ㅠㅠ 이해를 좀 하려고하는데 // 쳐진 부분에 설명 좀 붙혀주세요 간단하게ㅠㅠ부탁드립니다..

  • (•́ ✖ •̀)
    알 수 없는 사용자
  • 이해 안되는 것에 대해 질문을 하시기 바랍니다. 정영훈 2017.12.5 19:22
  • 모든 문제에 대해서 그저 Cheat Sheet를 바라면 안돼요! 질문이 명확했으면!!.. dbwodlf3 2017.12.6 18:59

1 답변

  • #include <stdio.h>
    #include <conio.h> //
    #include <string.h> 
    

    먼저 conio.h 는 헤더파일 입니다. 이것에 대해서는 직접 검색해 보세요.


    #define MAX_USER_DATA  100 //
    

    #define은 어떤 매크로를 지정하는데 쓰입니다. 여기서는 MAX_USER_DATA를 지정하였는데 이는 MAX_USER_DATA에 값 100을 지정하는 것입니다. 이 값은 상수로 변경할수 없습니다.

    #define은 프로그래밍 대회에서 쓰이고는 하는데 주로 다음과 같이 쓰입니다.

    #define REP(n) for(int i=0; i<n; i++)
    

    그러면 반복문을 사용할 때는 오타를 줄일 수 있고 다음과 같이 씁니다.

    int n;
    cin>>n;
    REP(n)
        cout<<i; //출력결과: 0123
    
    

    UI g_user_data[MAX_USER_DATA]; //
    

    갑자기 UI가 튀어나왔다고 생각할 수 있으시겠지만

    typedef struct U_Information
    {  //구조체 작성 
    char Name [10];
    char RRN [15];
    char ID [16];
    char Password [16];
    char Phone [16];
    char Address [40];
    char Email [20];
    
     } UI;
    

    위에서 사실 정의가 내려졌습니다. typedef 는 어떤 자료형의 '별칭'을 붙이는 것입니다. 즉 U_Information의 별칭이 바로 UI인 것입니다. 이 둘은 서로 쓰일수 있고 같은 역할을 합니다.

    typedef도 마찬가지로 프로그래밍 대회에서 쓰이고는 합니다.

    typedef vector<int> vi;
    typedef pair<int,int> pi;
    

    다음과 같이 쓰면 오타를 줄일 수 있습니다.


    int g_user_count; //
    

    이는 이름이 어려울 수도 있지만 사실 정수형 변수 선언입니다. c/c++에서는 변수이름에 알파벳(a~z, A~Z), 언더바(_), 숫자(0~9) 가 들어갈 수 있습니다. 하지만 숫자는 변수이름 처음으로 올 수 없습니다.

    int abc;
    int ab12;
    int a_b_1;
    int _ab;
    int __ab;
    int 1a;        //컴파일 오류!!!
    

    fread(&g_user_count, sizeof(int), 1, p_file); //
    

    이 함수는 stdio.h에 아래와 같이 정의되어 있는 함수입니다. 파일 입력시 쓰이는 함수입니다.

    size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
    

    ptr은 값을 저장하고 싶은 변수의 포인터, size는 저장할 바이트 수(정수형 변수이므로 4바이트가 될 것입니다.), count는 문서에서 읽고 싶은 값의 개수입니다. 마지막 stream은 파일 스트림입니다. 이는 위에서 정의가 이루어졌습니다.

    FILE *p_file = fopen(gfile_name, "r"); 
    

    fread(g_user_data + index, sizeof(UI), 1, p_file); //
    
    fwrite(&g_user_count, sizeof(int), 1, p_file); //
    
    fwrite(g_user_data + index, sizeof(UI), 1, p_file); //
    

    이 함수들도 위의 함수들과 비슷하다고 생각하시면 됩니다. fwrite는 파일 출력함수입니다.


    input = getch(); //
    

    getch()함수는 conio.h에 정의되어 있는 함수입니다. 이 함수는 특별하게도 입력을 받을때 눌린 키 값을 리턴하지만 눌린 값은 콘솔창에 쓰여지지 않습니다.


    if(input == 13) parm_password[index] = 0; //
    

    위의 getch함수로 input에 값이 들어옵니다. 이 값이 13이면 다음 문장을 실행한다는 것입니다.c/c++에서는 charint의 형변환이 자유롭습니다. 13의 값은 아스키코드값이고 리턴값입니다. 그런데 엔터의 값은 10인데 여기서는 잘 모르겠네요.


    parm_password[index++] = input; //
    

    parm_password는 앞에서 정의된 배열입니다. index도 앞에서 정의된 변수입니다. 여기서 단항연산자 ++가 사용되었는데 이는 변수의 값을 1 증가시키는 역할을 합니다. 그런데 두가지 쓰임이 있습니다. 바로 변수 앞에 쓰이느냐, 변수 뒤에 쓰이느냐 입니다. 둘다 변수의 값을 1 증가시키지만 앞에 쓰이면 선 증가 후 리턴이고 뒤에 쓰이면 선 리턴 후 증가 입니다. 다음을 보면 쉽게 이해가 되실겁니다.

    int a=0;
    
    cout<<a++<<" ";        //출력결과: 0, a의 값: 1
    
    a=0;
    
    cout<<++a<<" ";        //출력결과: 1, a의 값: 1
    
    

      g_user_count++; //
    

    이것도 바로 위에서 설명한 것입니다. 그런데 아까 g_user_count는 전역변수로 정의하였기 때문에 0으로 초기화가 자동으로 됩니다. 따라서 초기화를 안하고 증감을 써도 됩니다.


       ReadUserData(); //
    

    이는 위에서 정의된 함수를 호출하는 것입니다.

    void ReadUserData() //저장된 유저정보 읽어오기 
    { 
      int index = 0; 
      FILE *p_file = fopen(gfile_name, "r"); 
      if(p_file != NULL){ 
      fread(&g_user_count, sizeof(int), 1, p_file); //
      for(index = 0; index < g_user_count; index++){ 
          fread(g_user_data + index, sizeof(UI), 1, p_file); //
      } 
      fclose(p_file); 
      } 
    } 
    

    for(index = 0; index < g_user_count; index++){ //
    

    위를 for문이라고 부릅니다. for문은 반복을 하는데 다음으로 이루어져 있습니다.

    for(//정의; //조건문; //증감)
    {
        //코드
    }
    

    정의에서는 처음 1번만 실행됩니다. 조건문은 처음과 1번 반복할 때마다 확인되어 참이면 반복하고 거짓이면 빠져나갑니다. 증감은 1번 반복한 뒤 실행되는 구문입니다. 주로 증감을 저곳에 써 놓습니다.


    if(!strcmp(g_user_data[index].ID, id)){ //
    
    if(!strcmp(g_user_data[index].Password, password)){ //
    

    strcmpstring compare의 줄임말로 말그대로 두개의 문자열을 비교하는 함수입니다. 즉 g_user_data[index].IDid가 다를때 if문 안의 코드가 실행됩니다.


    success_login = 1; //
    

    위에서 정의된 변수에 1을 집어넣은 것입니다.


    if(index == g_user_count){ //
    

    indexg_user_count가 같으면 if문 이 실행됩니다.


    if(input == 'y' || input == 'Y') UserRegister(); //
    

    만약 inputy 또는 Y이면 UserRegister 함수가 호출됩니다.


    SaveUserData(); //
    

    SaveUserData함수가 호출됩니다.

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)