[C] 배열과 구조체

김태희·2023년 11월 13일
0
post-thumbnail

배열과 구조체

구조체를 사용하는것이 왜 좋은지 이해하려는 목적으로 학습을 시작하였다.

C를 너무 책으로만 배운 것 같아서, 코딩을 연습할겸 친구 정보 관리 프로그램 예제에, 정보를 수정하는 함수까지 스스로 추가하며 프로그램을 만들어보았다 !

배열만을 이용한 친구 정보 관리 프로그램

#include <stdio.h>
#define MAX_COUNT 5

typedef char NAME_TYPE[14];

int AddFriend(NAME_TYPE *p_name, unsigned short int *p_age, float *p_height,
              float *p_weight, int count) {
  if (count < MAX_COUNT) {
    printf("\n새로운 친구 정보를 입력하세요\n");
    printf("1. 이름 : ");
    scanf("%s", p_name[count]); /*포인터가 가르키는 다차원 배열에다 string처럼 저장하려면 주소 한번 덜 써야함*/
    printf("2. 나이 : ");
    scanf("%hu", &p_age[count]);
    printf("3. 키 : ");
    scanf("%f", &p_height[count]);
    printf("4. 몸무게 : ");
    scanf("%f", &p_weight[count]);
    printf("입력을 완료했습니다. \n\n");
    return 1;
  } else {
    printf("최대 인원을 초과하였습니다. \n");
  }
  return 0;
}

void ShowFriendList(NAME_TYPE *p_name, unsigned short int *p_age,
                    float *p_height, float *p_weight, int count) {
  if (count > 0) {
    printf("\n등록된 친구 목록\n");
    printf("=================================\n");
    for (int i = 0; i < count; i++) {
      printf("============%d번째 친구============\n", i+1);
      printf("1. 이름 : %-14s\n", *(p_name + i));
      printf("2. 나이 : %3d\n", *(p_age + i));
      printf("3. 키 : %6.2f\n", *(p_height + i));
      printf("4. 몸무게 : %6.2f\n", *(p_weight + i));
    }
  } else {
    printf("\n 등록된 친구가 없습니다. \n");
  }
}
void ChangeFriendSettings(NAME_TYPE *p_name, unsigned short int *p_age,
                          float *p_height, float *p_weight, int count) {
  int friend_num, option_num;

  printf("몇 번째 친구의 설정을 변경하시겠습니까 ?\n");
  ShowFriendList(p_name, p_age, p_height, p_weight, count);
  printf("친구의 번호 : ");
  scanf("%d", &friend_num);
  printf("\n%d번째 친구를 불러옵니다 ! \n", friend_num);
  friend_num--;

  if (friend_num >= 0 && friend_num < count) {
    printf("\n============%d번째 친구============\n", friend_num + 1);
    printf("1. 이름 : %-14s\n", p_name[friend_num]);
    printf("2. 나이 : %3d\n", p_age[friend_num]);
    printf("3. 키 : %6.2f\n", p_height[friend_num]);
    printf("4. 몸무게 : %6.2f\n", p_weight[friend_num]);

    printf("어떤 요소를 변경하고싶으세요 ? \n");
    printf("요소의 번호 : ");
    scanf("%d", &option_num);
    option_num--;

    if (option_num >= 0 && option_num <= 3) {
      printf("무엇으로 바꿀까요 ? : ");
      switch (option_num) {
        case 0:
          scanf("%s", p_name[friend_num]);
          break;
        case 1:
          scanf("%hu", &p_age[friend_num]);
          break;
        case 2:
          scanf("%f", &p_height[friend_num]);
          break;
        case 3:
          scanf("%f", &p_weight[friend_num]);
          break;
        default:
          printf("없는 요소입니다\n");
          return;
      }
      printf("변경 완료!\n");
    } else {
      printf("잘못된 요소 번호입니다\n");
    }
  } else {
    printf("존재하지 않는 친구 번호입니다\n");
  }
}
void main() {
  NAME_TYPE name[MAX_COUNT];
  unsigned short int age[MAX_COUNT];
  float height[MAX_COUNT];
  float weight[MAX_COUNT];
  int count = 0, num;

  while (1) {
    printf("    [MENU]    \n");
    printf("==============\n");
    printf("1. 친구 추가   \n");
    printf("2. 친구 목록   \n");
    printf("3. 친구 설정 변경   \n");
    printf("4. 종료   \n");
    printf("번호 선택 : ");
    scanf("%d", &num);

    if (num == 1) {
      if (1 == AddFriend(name, age, height, weight, count))
        count++;
    } else if (num == 2) {
      ShowFriendList(name, age, height, weight, count);
    } else if (num == 3) {
      ChangeFriendSettings(name, age, height, weight, count);
    } else {
      break;
    }
  }
}

배웠지만 코딩하며 헷갈렸던 내용들

  1. 서식 지정자들을 사용하는 여러 방법들
  2. 포인터와 변수를 함께 사용하는 방법들과 의미

그래서 배열로 코드를 짠 다음 이 부분들을 다시 복습하며 학습하였다

구조체를 활용해 친구 정보 관리 프로그램 최적화

#include <stdio.h>
#define MAX_COUNT 5

typedef struct People {
  char name[14];
  unsigned short int age;
  float height;
  float weight;
} Person;

int AddFriend(Person *p_friend, int count) {
  if (count < MAX_COUNT) {
    p_friend += count;
    printf("\n새로운 친구 정보를 입력하세요\n");
    printf("1. 이름 : ");
    scanf("%s", p_friend->name); // (*p_name).name과 같음
    printf("2. 나이 : ");
    scanf("%hu",
          &p_friend->age); //위의 name은 name[]로 가는거기때문에(2차원배열로생각) & 없이 저장하려는 곳으로 이동할 수 있음
    printf("3. 키 : "); 
    scanf("%f", &p_friend->height);
    printf("4. 몸무게 : ");
    scanf("%f", &p_friend->weight);
    printf("입력을 완료했습니다. \n\n");
    return 1;
  } else {
    printf("최대 인원을 초과하였습니다. \n");
  }
  return 0;
}

void ShowFriendList(Person *p_friend, int count) {
  if (count > 0) {
    printf("\n등록된 친구 목록\n");
    printf("=================================\n");
    for (int i = 0; i < count; i++) {
      printf("============%d번째 친구============\n", i + 1);
      printf("1. 이름 : %-14s\n", p_friend->name);
      printf("2. 나이 : %3d\n", p_friend->age);
      printf("3. 키 : %6.2f\n", p_friend->height);
      printf("4. 몸무게 : %6.2f\n", p_friend->weight);
      p_friend++;
    }
  } else {
    printf("\n 등록된 친구가 없습니다. \n");
  }
}

void ChangeFriendSettings(Person *p_friend, int count) {
  int friend_num, option_num;

  printf("몇 번째 친구의 설정을 변경하시겠습니까 ?\n");
  ShowFriendList(p_friend, count);
  printf("친구의 번호 : ");
  scanf("%d", &friend_num);
  printf("\n%d번째 친구를 불러옵니다 ! \n", friend_num);
  friend_num--;

  if (friend_num >= 0 && friend_num < count) {
    printf("\n============%d번째 친구============\n", friend_num + 1);
    p_friend += friend_num;
    printf("1. 이름 : %-14s\n", p_friend->name);
    printf("2. 나이 : %3d\n", p_friend->age);
    printf("3. 키 : %6.2f\n", p_friend->height);
    printf("4. 몸무게 : %6.2f\n", p_friend->height);
    printf("어떤 요소를 변경하고싶으세요 ? \n");
    printf("요소의 번호 : ");
    scanf("%d", &option_num);
    option_num--;

    if (option_num >= 0 && option_num <= 3) {
      printf("무엇으로 바꿀까요 ? : ");
      switch (option_num) {
        case 0:
          scanf("%s", p_friend->name);
          break;
        case 1:
          scanf("%hu", &p_friend->age);
          break;
        case 2:
          scanf("%f", &p_friend->height);
          break;
        case 3:
          scanf("%f", &p_friend->height);
          break;
        default:
          printf("없는 요소입니다\n");
      }
      printf("변경 완료!\n");
    } else {
      printf("잘못된 요소 번호입니다\n");
    }
  } else {
    printf("존재하지 않는 친구 번호입니다\n");
  }
}

void main() {
  Person friends[MAX_COUNT];
  int count=0, num;

  while (1) {
    printf("    [MENU]    \n");
    printf("==============\n");
    printf("1. 친구 추가   \n");
    printf("2. 친구 목록   \n");
    printf("3. 친구 설정 변경   \n");
    printf("4. 종료   \n");
    printf("번호 선택 : ");
    scanf("%d", &num);

    if (num == 1) {
      if (1 == AddFriend(friends, count))
        count++;
    } else if (num == 2) {
      ShowFriendList(friends, count);
    } else if (num == 3) {
      ChangeFriendSettings(friends, count);
    } else {
      break;
    }
  }
}

포인터 부분은 아무리 공부해도 헷갈리는것 같다
하지만 코드를 작성할 수록 조금씩 익숙해지는 것 같아 다행이다

p_friend->name 로 (*p_name).name 을 대신 표현하는 것 처럼
->를 사용하는 방법은 나중에도 자주 쓸 것 같고, 여러 예제에서 등장할 것 같아서 한번 봤을때 눈에 익혀두려고 한다

또한 scanf에서 포인터에 저장된 배열로 접근하기위해
p_friend->name
&p_friend->age
name에서는 &를 사용하지 않는 부분과 포인터배열에다가 typedef까지 합쳐지면서
처음에는 많이 헷갈리고 이해하기도 힘들었지만
포인터 배열에 대해 공부하며 해소된 것 같다 !
2차원 배열이라고 생각하는 것이 가장 이해하기 쉬운 것 같다

배열과 포인터의 합체

배열 표기법 대신 포인터 표기법 사용하기
data[2] == *(data+2)


배열을 기준으로 포인터와 합체하기
int *p[5] => int형을 가르키는 포인터 변수를 5개 만들기


포인터를 기준으로 배열과 합체하기
int (*p)[5] => int[5]를 가르키는 포인터 변수 만들기 (다차원 배열이라고 생각)

0개의 댓글