✏️포인터
🔎 주소, 암호
#include <stdio.h>
int main(void)
{
//포인터
// [철수] 101호
// [영희] 201호
// [민수] 301호
// 각 문 앞에 '암호'가 걸려 있음
int 철수 = 1; //암호
int 영희 = 2;
int 민수 = 3;
printf("철수네 주소 : %d, 암호 : %d\n", &철수, 철수);
printf("영희네 주소 : %d, 암호 : %d\n", &영희, 영희);
printf("민수네 주소 : %d, 암호 : %d\n", &민수, 민수);
//미션맨 !
// 첫번째 미션 : 아파트의 각 집에 방문하여 문에 적힌 암호 확인
int* 미션맨; // 포인터 변수
미션맨 = &철수;
printf("미션맨이 방문하는 곳 주소 : %d, 암호 : %d\n", 미션맨, *미션맨);
미션맨 = &영희;
printf("미션맨이 방문하는 곳 주소 : %d, 암호 : %d\n", 미션맨, *미션맨);
미션맨 = &민수;
printf("미션맨이 방문하는 곳 주소 : %d, 암호 : %d\n", 미션맨, *미션맨);
// 두번째 미션 : 각 암호에 3을 곱하라
미션맨 = &철수;
*미션맨 = *미션맨 * 3;
printf("미션맨이 암호를 바꾼 곳 방문하는 곳 주소 : %d, 암호 : %d\n", 미션맨, *미션맨);
미션맨 = &영희;
*미션맨 = *미션맨 * 3;
printf("미션맨이 암호를 바꾼 곳 방문하는 곳 주소 : %d, 암호 : %d\n", 미션맨, *미션맨);
미션맨 = &민수;
*미션맨 = *미션맨 * 3;
printf("미션맨이 암호를 바꾼 곳 방문하는 곳 주소 : %d, 암호 : %d\n", 미션맨, *미션맨);
// 스파이
// 미션맨이 바꾼 암호에서 2를 빼라
int* 스파이 = 미션맨;
printf("\n ..... 스파이가 미션 수행하는 중 ... \n\n");
스파이 = &철수;
*스파이 = *스파이 - 2;
printf("스파이가 방문하는 곳 주소 : %d, 암호 : %d\n", 스파이, *스파이);
스파이 = &영희;
*스파이 = *스파이 - 2;
printf("스파이가 방문하는 곳 주소 : %d, 암호 : %d\n", 스파이, *스파이);
스파이 = &민수;
*스파이 = *스파이 - 2;
printf("스파이가 방문하는 곳 주소 : %d, 암호 : %d\n", 스파이, *스파이);
printf("\n\n... 철수 영희 민수는 집에 오고서는 바뀐 비번을 보고 깜놀 ...\n\n");
printf("철수네 주소 : %d, 암호 : %d\n", &철수, 철수);
printf("영희네 주소 : %d, 암호 : %d\n", &영희, 영희);
printf("민수네 주소 : %d, 암호 : %d\n", &민수, 민수);
//참고로... 미션맨이 사는 곳의 주소는... &미션맨으로 확인
printf("미션맨의 주소 : %d\n", &미션맨);
printf("스파이의 주소 : %d\n", &스파이);
return 0;
}
&영희 : 주소값
* 영희 : 지칭하는 값
스파이라는 명칭으로 영희 주소값에 접근해 값을 변경해도 그 값이 바뀌는 걸 확인 할 수 있다.
🔎 배열과 포인터
📌 *(arr + i) == arr[i]
*(arr + 0) == arr[0] == *arr
포인터를 활용하면 배열값의 일부도 바꿀 수 있다.
📌 *&는 서로 상쇄된다.
& 는 주소이며, * 는 그 주소의 값이기 때문에, *&arr[0] == arr[0]
#include <stdio.h>
// 배열과 포인터 관계
int main(void)
{
//배열
int arr[3] = { 5, 10, 15 };
int* ptr = arr;
for (int i = 0; i < 3; i++)
{
printf("배열 arr[%d]의 값 : %d\n", i, arr[i]);
}
for (int i = 0; i < 3; i++)
{
printf("포인터 ptr[%d]의 값 : %d\n", i, ptr[i]);
}
ptr[0] = 100;
ptr[1] = 200;
ptr[2] = 300;
for (int i = 0; i < 3; i++)
{
//printf("배열 arr[%d]의 값 : %d\n", i, arr[i]);
printf("배열 arr[%d]의 값 : %d\n", i, *(arr + i));
}
for (int i = 0; i < 3; i++)
{
//printf("포인터 ptr[%d]의 값 : %d\n", i, ptr[i]);
printf("포인터 ptr[%d]의 값 : %d\n", i, *(ptr + i));
}
// *(arr + i) == arr[i] 똑같은 표현
// arr == arr 배열의 첫번째 값의 주소와 동일 == &arr[0]
printf("arr 자체의 값 : %d\n", arr);
printf("arr[0] 의 주소 : %d\n", &arr[0]);
printf("arr 자체의 값을 가지는 주소의 실제 값 : %d\n", *arr); // *(arr + 0)
printf("arr[0] 의 주소 : %d\n", *&arr[0]); // *&는 아무것도 없는 것과 같다.
// & 는 주소이며, * 는 그 주소의 값이기 때문에,
// *&는 서로 상쇄된다.
return 0;
}
✏️ Swap
🔎 값을 바꿔주기
swap 함수를 이용해 값을 바꿔주는걸 시도했으나, 실패했다.
왜냐면, main내에 a,b 주소와 swap 함수 내 a,b주소가 상이하기 때문이다.
따라서, 값을 바꿔주기 위해서는 주소값을 함수에 전달해 값을 바꾸도록 해야한다.
함수는 받은 주소값을 활용해 포인터로 값을 바꿔줘야 한다.
#include <stdio.h>
void swap(int a, int b);
void swap_addr(int *a, int *b);
int main(void)
{
//Swap
int a = 10;
int b = 20;
printf("a의 주소 : %d\n", &a);
printf("b의 주소 : %d\n", &b);
// a와 b의 값을 바꾼다.
printf("Swap 함수 전 a : %d, b : %d\n", a, b);
swap(a, b);
printf("Swap 함수 후 a : %d, b : %d\n", a, b);
//값에 의한 복사 (Call by Value) -> 값만 복사한다는 의미.
//주소값을 넘기면? 메모리 공간에 있는 주소값 자체를 넘기면
printf("(주소값 전달)Swap 함수 전 a : %d, b : %d\n", a, b);
swap_addr(&a, &b);
printf("(주소값 전달)Swap 함수 후 a : %d, b : %d\n", a, b);
return 0;
}
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
//printf("함수 내 a의 주소 : %d\n", &a);
//printf("함수 내 b의 주소 : %d\n", &b);
//printf("Swap 함수 내 a : %d, b : %d\n", a, b);
}
void swap_addr(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
🔎 배열 값 바꿔주기
배열은 주소 전달해주지 않더라도 값이 잘 바뀐다.
다만, 함수에서는 포인터를 받아야 한다.
#include <stdio.h>
void chageArray(int* ptr);
int main(void)
{
//배열일 때, arr -> 주소
int arr2[3] = { 10, 20, 30 };
chageArray(arr2); //chageArray(&arr2[0]);
for (int i = 0; i < 3; i++)
{
printf("%d\n", arr2[i]);
}
// scanf 에서 &num의 의미와 동일
return 0;
}
void chageArray(int* ptr)
{
ptr[2] = 50;
}
✏️ 프로젝트
🔎 물고기 키우기
사막에서 물고기 키우는 걸로 시간이 경과되는 만큼 물이 증발된다.
그러므로 물고기는 물을 줘도 죽을 수 밖에 없는 환경...
#include<stdio.h>
#include<time.h>
// 물고기가 6마리가 있다.
// 이들은 어항에 살고 있는데, 사망이에요.
// 사막이 너무 더워서, 너무 건조해서 물이 아주 빨리 증발해요.
// 물이 다 증발하기 전에 부지런히 어항에 물을 줘서 물고기를 살려주세요~
int level;
int arrayFish[6];
int * cursor;
void iniDate();
void printfFishes();
void decreseWater(long elapsedTime);
int checkFishAlive();
int main(void)
{
long startTime = 0; // 게임 시작 시간
long totalElapseTime = 0; // 총 경과 시간
long preElapsedTime = 0; // 작전 경과 시간(최근에 물을 준 시간 간격)
int num; // 몇 번 어항에 물을 줄것인지. 사용자 입력
iniDate();
cursor = arrayFish; // cursor[0] .... cursor[1]
startTime = clock(); // 현재 시간을 millisecond [1000분의 1초]단위로 반환
while (1)
{
printfFishes();
printf("몇 번 어항에 물을 주시겠어요?");
scanf_s("%d", &num);
//입력값 체크
if (num < 1 || num >6)
{
printf("\n입력값이 잘못되었습니다.\n");
continue;
}
//총 경과 시간
totalElapseTime = (clock() - startTime) / CLOCKS_PER_SEC;
printf("총 경과 시간 : %1d 초\n", totalElapseTime);
//직전 물 준 시간 (마지막으로 물 준 시간) 이후로 흐른 시간
preElapsedTime = totalElapseTime - preElapsedTime;
printf("최근 경과 시간 : %1d 초\n", preElapsedTime);
//어항의 물을 감소(증발)
decreseWater(preElapsedTime);
//사용가가 입력한 어항에 물을 준다.
// 1. 어항의 물이 0이면? 물을 주지 않는다... 이미 물고기가 죽었음
if (cursor[num - 1] <= 0)
{
printf("%d번 물고기는 이미 죽었습니다. 물을 주지 않습니다.\n", num);
}
//2. 어항의 물이 0이 아닌 경우? 물은 준다! 100을 넘지 않는지 체크
else if (cursor[num - 1] + 1 <= 100)
{
//물을 준다.
printf("%d번 어항의 물을 줍니다,\n\n", num);
cursor[num - 1] += 1;
}
// 레벨업을 할 건지 확인 (레벨업은 20초마다 한번씩 수행)
if (totalElapseTime / 20 > level - 1)
{
// 레벨업
level++;
printf("**** 축 레벨업 ! 기존 %d 레벨에서 %d 레벨로 업그레이드 ***\\n\n", level-1, level);
// 최종 레벨 : 5
if (level == 5)
{
printf("\n\n 축하합니다. 최고 레벨을 달성하였습니다. 게임을 종료합니다.");
exit(0);
}
}
// 모든 물고기가 죽었나 확인
if (checkFishAlive() == 0)
{
// 물고기 모두 죽었다.
printf("모든 물고기가... ㅠㅠ 흑흑...\n");
exit();
}
else
{
//최소 한마리 이상의 물고기 살아있음
printf("물고기가 아직 살아 있어요!\n");
}
preElapsedTime = totalElapseTime;
// 10초 -> 15초 (5초 : preElapsedTime->15초)->25초 (10초?)
}
return 0;
}
void iniDate()
{
level = 1; // 게임 레벨(1~5)
for (int i = 0; i < 6; i++)
{
arrayFish[i] = 100; // 어항의 물 높이 (0~100)
}
}
void printfFishes()
{
printf("%3d번 %3d번 %3d번 %3d번 %3d번 %3d번\n", 1,2,3,4,5,6);
for (int i = 0; i < 6; i++)
{
printf("% 6d", arrayFish[i]);
}
printf("\n\n");
}
void decreseWater(long elapsedTime)
{
for (int i = 0; i < 6; i++)
{
arrayFish[i] -= (level * 3 * (int)elapsedTime); //3 : 난이도 조절을 위한 값
if (arrayFish[i] < 0)
{
arrayFish[i] = 0;
}
}
}
int checkFishAlive()
{
for (int i = 0; i < 6; i++)
{
if (arrayFish[i] > 0)
return 1; //참 True
}
return 0;
}
🍏 KEEP, 습관 중요한 것
함수에 주소값을 전달해야 한다는 점이 흥미로웠다.
컴퓨터가 변수에 값을 저장할 때, 항상 주소와 값이 형성된다는 점을 유의해야 한다.
🍎 PROBLEM, 이슈, 에러, 오류
이번 목차를 학습할때는 운이 좋게도 에러가 발생하지 않았다.
🍉 TRY 시도
프로젝트는 다시 듣고 이해해 봐야 할듯하다.
프로젝트가 혼자 구현하긴 어렵다.
배열부터 좀 어렵다..ㅎㅎㅎ
'c언어 개발일지' 카테고리의 다른 글
malloc 함수로 메모리 할당 (1) | 2022.09.19 |
---|---|
[나도 코딩 C언어] 다차원 배열 (1) | 2022.09.19 |
[나도 코딩 C언어] 배열 (0) | 2022.08.16 |
[나도 코딩 C언어] 함수 (0) | 2022.08.12 |
[나도 코딩 C언어] 조건 / 분기 (0) | 2022.08.12 |
댓글