구조체를 사용하는것이 왜 좋은지 이해하려는 목적으로 학습을 시작하였다.
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;
}
}
}
- 서식 지정자들을 사용하는 여러 방법들
- 포인터와 변수를 함께 사용하는 방법들과 의미
그래서 배열로 코드를 짠 다음 이 부분들을 다시 복습하며 학습하였다
#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]를 가르키는 포인터 변수 만들기 (다차원 배열이라고 생각)