🎯 조건문
▶️ if
- if 조건문은 여러 조건 중 하나를 처리하는 기능 입니다.
- 동작 순서 : 조건식을 체크하여 조건식이 true일 경우 코드 블록안의 코드가 동작합니다.
// if의 구조
if( 조건식 )
{
// 해당 조건식에 해당할 경우 동작할 코드
}
//else if문 구조
else if( 조건식 )
{
// 해당 조건식에 해당할 경우 동작할 코드
}
//else문 구조
else
{
}
▶️ else문
- else는 반드시 if와 함께 사용 되어야 합니다.
- if 문의 조건이 false일때 동작
- if문 다음에 위치해야 한다. else if()문이 있다면 else if()문 다음에 위치해야 합니다.
- 하나의 if문에 else는 하나만 존재할 수 있습니다.
▶️ else if문
- 반드시 if와 함께 사용 되어야 합니다.
- 우선순위 높은 친구가 위에 위치해야 합니다.
▶️if문 예시
int hp = 50;
if ( hp >= 30 && hp <= 50 )
printf( "print if true. hp is %d\n", hp );
else if( hp <= 51 && hp >= 70 )
printf( "hp is 51 up, and 70 down" );
else
std::cout << "not hp" << std::endl;
▶️ switch 조건문
- 변수로 분기처리가 가능 합니다.
switch( 변수 )
{
case 상수 :
동작할코드
break;
case 상수 :
동작할 코드
break;
default :
동작할 코드
break;
} - 변수의 값에 따라 case의 상수를 찾아서 코드를 동작시키고 break를 만나면 switch문을 나갑니다.
- case문에서 변수를 사용하려면 코드블럭으로 묶어서 사용합니다.
- 선언하며 초기화 함께하면 에러.선언하고, 초기화 따로하면 됨. case 사이에 같은 변수 선언(만 한거)는 안됩니다.
- default : if문의 else와 같습니다. case의 상수들과 같은 값이 없을 경우 default가 동작합니다
int num = 3;
switch (num)
{
case 1 :
// num이 1일때, 동작할 코드
break;
case 2 :
// num이 2일때, 동작할 코드
break;
case 3:
// num이 3일때, 동작할 코드
break;
default :
// num이 1 또는 2 또는 3이 아닐때(위 케이스들이 한번도 동작하지 않았을때), 동작할 코드
break;
}
‼️ switch문 사용시 주의점
1. switch문에선 case문에서 break없이 동작이 가능합니다
int num = 0;
int result = 0;
switch( num )
{
case 0 :
case 1 :
result = 1;
break;
case 2 :
result = 2;
break;
default :
result = -1;
break;
}
num 변수가 0 또는 1 일때 result엔 1이 대입 됩니다.
2. case문 안에서 변수를 선언과 동시에 초기화시 에러가 납니다.
int num = 0;
switch (num)
{
case 0:
int num2 = 2;
break;
case 1: // [에러] error C2360: 'num2' 초기화가 'case' 레이블에 의해 생략되었습니다.
break;
default : // [에러] error C2361: 'num2' 초기화가 'default' 레이블에 의해 생략되었습니다.
break;
}
밑에 case, default문에서도 해당 변수를 사용(위 예시에서는 num2)할 수 있는데, 중복으로 선언되어 사용할 수 있기때문에 에러를 발생시키게 됩니다.
해결방법 1. 코드블럭으로 묶어주기
int num = 0;
switch (num)
{
case 0:
{
int num2 = 2;
}
break;
case 1:
break;
default :
break;
}
해결방법 2. 선언과 초기화를 나눠서 하기
int num = 0;
switch (num)
{
case 0:
int num2;
num2= 2;
break;
case 1:
// 이렇게 위 케이스에서 선언한 변수를 사용 가능합니다.
num2 = 4;
break;
default :
break;
}
위 예시에서 case1에 num2를 다시 선언한다면 에러가 나게 됩니다.
case안에서 변수 선언 후 다른 case에서 사용은
문법적으론 가능한 내용이나, 가독성이 좋지않아서 저런 사용은 지양하시길 바랍니다.
🎯 난수
▶️ rand()
- 난수를 발생시켜 주는 함수 입니다
- 그냥 실행하면 동일한 숫자가 계속 나옵니다. 이미 정해진 난수표를 가지고 있기 때문입니다.
std::cout << rand() << std::endl; // 출력 : 41
std::cout << rand() << std::endl; // 출력 : 18467
▶️ srand( n ) : n번째 시드에 있는 난수표 값을 가져옵니다
srand(20);
std::cout << rand() << std::endl; // 103
std::cout << rand() << std::endl; // 26079
▶️ srand( time(0) ) : 매번 출력할 때마다 다른 값을 넣어주려면 현재 시간( time(0) )을 넣어주면 됩니다.
#include <time.h>
int main()
{
srand( time(0) );
std::cout << rand() << std::endl; // 이렇게 하면 실행할 때마다 첫번째값이 조금씩만 증가함. c++ 버그임
std::cout << rand() << std::endl;
return 0;
}
위 코드를 반복 실행하면 첫번째 값이 비슷한 값에서 조금씩 증가하는것을 확인할 수 있습니다.
이것은 c++버그라고 하네요 😂.
위 버그를 방지하기 위해 rand()를 사용하기 전 미리 rand()를 호출해줍니다.
#include <time.h>
int main()
{
srand( time(0) );
// 버그를 방지하기 위해 미리 rand()를 호출해줌
rand();
std::cout << rand() << std::endl;
std::cout << rand() << std::endl;
return 0;
}
▶️ rand()의 발생 범위를 0 - 100까지만 난수로 사용하고 싶을때
std::cout << rand() % 101 << std::endl;
▶️ 100 - 200 사이의 값만 난수로 사용하고 싶을 때
std::cout << rand() % 101 + 100 << std::endl;
특정 범위의 최소 ~ 최대 난수를 구하는 공식은
rand() % (최대 - 최소 + 1) + 최소 임을 알 수 있습니다.
▶️ 난수를 실수로 표현하기
소숫점 둘째자리까지 난수를 만들고 싶은 경우
0 ~ 10000 사이로 난수가 나오게 하고싶을 때
std::cout << rand() % 10001 * 0.01f << std::endl;
🎯 사용자 정의 변수타입
- 해당 프로젝트만의 고유한 변수 타입을 만들어서 사용 가능합니다.
ex) 열거형, 구조체, 클래스
▶️ 열거형(enum) : 사용자 정의 변수타입을 만들어 주기 위한 하나의 문법.
- 열거형은 연속된 숫자 상수를 만들어 줄 수 있는 기능입니다.
- 숫자에 이름을 부여해 줄 수 있습니다.
- 열거형은 기본으로 4바이트의 크기를 가지게 됩니다.
- 크기 지정도 가능합니다.
#include <iostream>
// enum은 변수명에 대문자 E가 붙어있음.
// enum이 다르더라도 열거자(변수)가 같으면 안됨 (그래서 나온게 enum클래스)
enum EJob
{
Job_None,
Job_Knight,
Job_Archer,
Job_Magicion,
};
enum ENumber
{
Num1, // 0
Num2, // 1
Num3 = 50,
Num4, // 51
};
enum EBuf
{
Buf_Attack = 0x1,
Buf_Defence = 0x2,
Buf_Hp = 0x4,
Buf_Mp = 0x8,
Buf_Exp = 0x10,
};
int main()
{
std::cout << Job_Knight << std::endl; // 1출력
std::cout << EJob::Job_Archer << std::endl; // 2 출력
EJob job;
// sizeof() : 괄호안에 들어가는 타입 혹은 변수의 메모리 크기가 몇 바이트인지 구해준다
std::cout << sizeof(EJob) << std::endl; // 4 출력 // 4바이트
std::cout << sizeof(int) << std::endl; // 4출력 // 4바이트
return 0;
}
열거형의 크기지정
enum ETest : unsigned char
{
a,
b,
c
};
열거형 변수에 정수를 직접 할당 할순 없습니다.
형변환을 거쳐야합니다.
EJob job;
job = 0; // [에러] "int" 형식의 값을 "Test" 형식의 엔터티에 할당할 수 없습니다.
job = (EJob)0; // 형변환을 해주면 대입이 가능합니다.
반대로 정수형 변수에 열거형 변수는 대입이 가능합니다.
EJob job = EJob::None;
int num = job;
std::cout << num << std::endl; // 0 출력
enum과 switch를 이용한 예제
// switch 만들때, tab으로 만들고, 인수에 Enum형 치고 탭 누르고 엔터 누르면 열거형 별로 케이스 자동완성
switch ( jobInt )
{
case Job_None:
break;
case Job_Knight:
break;
case Job_Archer:
break;
case Job_Magicion:
break;
}
-> 대부분 enum과 switch를 함께 사용합니다. 가독성 상승하여 읽기 좋은 코드가 됩니다.
▶️ enum class
- enum class는 타입을 엄격하게 따집니다.
- 기본 4바이트입니다.
- 언리얼에서는 enum class로 구현되어있는 경우가 많아서 훨씬 많이 사용합니다.
- 크기 지정이 가능합니다.
- enum class는 인트 변수에 넣을 수가 없습니다.
- int itemType = EItemType::Weapon; // [사용 불가]
std::cout << EItemType::Weapon << std::endl; - EItemType itemType = EItemType::Weapon;
- itemType = Armor; // [사용불가] 열거형 이름의 요소 이름만으로는 접근이 안됩니다. 이름 충돌이 될 가능성이 적어져서 안전함이 장점입니다.
- int itemType = EItemType::Weapon; // [사용 불가]
#include <iostream>
// enum 클래스는 크기를 지정 가능. enum class의 장점
// enum clase
enum class EItemType : unsigned char
{
Weapon,
Armor,
Etc,
};
int main()
{
// enum class는 인트 변수에 넣을 수가 없음.
//int itemType = EItemType::Weapon; // [에러] "EItemType" 형식의 값을 사용하여 "int" 형식의 엔터티를 초기화할 수 없습니다.
//std::cout << EItemType::Weapon << std::endl; // [에러]
EItemType itemType = EItemType::Weapon;
//itemType = Armor; // 열거형 이름의 요소 이름만으로는 접근이 안됨. 이름 충돌이 될 가능성이 적어져서 안전함이 장점.
return 0;
}
🎯 반복문
- 동일한 작업을 여러번 반복해서 동작시킬 때 사용합니다.
for, while, do while 3가지 반복문을 지원합니다.
▶️ for문
for( 초기값 ; 조건식 ; 증감값 )
{
반복할 코드
}
=> 초기값과 증감값은 없어도 됩니다.
- - 동작순서
초기값 -> 조건식 체크 true -> 코드동작 -> 증감값 -> 조건식 true -> 코드동작 -> 증감값
-> 조건식 false일 경우 종료 - 초기값은 처음 for문에 진입할 때 1번만 동작 합니다.
1. 조건식 체크
2. 코드동작
3. 증감값
이 순서대로 반복한다. - 조건식이 false가 될 수 없는 조건이라면 무한루프가 돌게 됩니다.
이 경우 break를 이용해 for문을 빠져나올 수 있습니다.
// 처음 아래 for문에 진입할 때 초기값에서 int 변수 i를 생성하고
// 0으로 초기화한다. i는 초기값에서 생선된 변수이기 때문에
// for문 안에서만 사용이 가능하다.
// 조건식을 체크한다. i < 10은 처음에는 i가 0이므로 0<10 이 되고
// 0은 10보다 작기 때문에 true가 되어 for문 안으로 진입한다.
// i값을 출력해서 0이 출력되고, 증감값으로 이동한다.
// 증감값에서는 ++i를 해주고 있다. 그러므로 i는 0에서 1이 되고
// 조건식을 체크한다
for (int i = 0; i < 100; ++i)
{
// continue는 증감값으로 실행흐름을 변경해준다.
// 0 % 3 == 0이 나옴. 0도 가능해야 한다면 조건 추가 ( i != 0 && i % 3 == 0 )
if (i % 3 == 0)
continue;
std::cout << i << std::endl;
}
for문으로 무한루프 돌리기
for (;;)
{
}
중첩 for문 사용하기
// 중첩for문
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
{
//아래와 동일하게 printf로 출력하기 : printf("i : %d, j : %d", i, j);
std::cout << "i = " << i << ", j = " << j << std::endl;
}
}
/*
i : 0, j : 0
i : 0, j : 1
i : 0, j : 2
i : 1, j : 0
i : 1, j : 1
i : 1, j : 2
i : 2, j : 0
i : 2, j : 1
i : 2, j : 2
*/
0~49까지 이중 for문을 통해 출력하기 예시
int num1 = 5;
int num2 = 10;
for( int i = 0 ; i < num1 ; ++i)
{
for( int j = 0 ; j < num2 ; ++j)
{
std::cout << i * 10 + j << std::endl;
}
}
세로 줄번호 * 가로갯수 + 가로 번호 라는 식을 세워서 작성할 수 있습니다.
많이 사용되는 인덱스 계산 공식이기 때문에 외워두시길 추천드립니다.
▶️ while문
while( 조건식 )
{
동작할 코드
}
- 조건식이 true면 반복 합니다.
▶️ do while문
do
{
}
while( 조건식 ) ;
- 처음 한번은 무조건 실행합니다.
- 한번 실행 후 조건을 체크합니다.
- 멀티쓰레드 환경에서 사용하기 좋음: 락카운트할때! 한번은 락카운트 한번 해줘야하기 때문입니다.
런타임 : 프로그램 실행되고 있는 상태를 말합니다.
▶️ 콘솔에서 입력받기
- std::cin : 콘솔창에서 입력을 받고, 그것을 변수에 넣어서 사용할 수 있게 해주는 함수
- 화살표를 cout의 반대로 넣어줘야 합니다.
- 정수가 아닌 string등이 입력될 경우 입력오류가 납니다.
int loopCnt = 0;
std::cout << "input loopCount : ";
std::cin >> loopCnt;
for ( int i = 0; i < loopCnt ; ++i )
{
std::cout << i << std::endl; // 입력받은 갯수부터 0까지 숫자 감소하며 출력
}
▶️ 배열
- 동일한 타입의 변수 여러개를 하나의 이름으로 만들어서 사용할 수 있게 해주는 기능입니다
- 선언 형태 : 변수타입 이름[개수];
- 배열은 인덱스를 이용해서 접근합니다 : 배열이름[접근할 인덱스 번호]
- 인덱스는 0 ~ 개수-1 까지 입니다.
ex) int arr[4] -> 0, 1, 2, 3 - 배열 선언시 = {}를 해주게 되면 배열에 모든 요소를 0으로 초기화 시킵니다.
ex) int arr[4] = {1,2} 해주게 되면 1, 2, 0, 0 으로 초기화 됩니다.
const int size = 10;
// 인덱스 0번 배열에 1, 인덱스 1번 배열에 2를 넣고 나머지 배열엔 0을 대입
// 배열 사이즈에는 상수만 입력 가능
int Array[size] = { 1,2 };
// 직접 접근하여 대입 가능
Array[3] = 500;
// 9번째 배열 값에 전치증가연산자 사용
++Array[9];
for (int i = 0; i < size; ++i)
{
std::cout << Array[i] << std::endl;
}
‼️ 배열 사용시 주의사항
배열 선언시 초기화를 해주지않거나, 값을 대입하지 않고 사용할 경우 쓰레기값이 들어가게 됩니다
const int size = 3;
int arr[size];
for (int i = 0; i < size; i++)
{
std::cout << arr[i] << std::endl;
}
아래 예제에선 char형태의 배열에서 초기화도 하지않고, null문자도 지정해주지 않아서
입력된 문자 외에 쓰레기 값이 저장되어 출력되는것을 확인하실 수 있습니다.
char chars[32];
chars[0] = 'a';
chars[1] = 'b';
std::cout << chars << std::endl;
컴파일러가 chars를 출력하기 위해 chars를 읽어올 때,
null 문자까지 가져와야 하나 null문자가 없어서 위와 같이 결과가 출력됩니다.
// 선언과 동시에 초기화
char chars[32] = {};
chars[0] = 'a';
chars[1] = 'b';
std::cout << chars << std::endl;
chars 배열에 선언과 동시에 초기화를 함으로써 우리가 원하는 값만 출력되도록 변경되었습니다.
'개발개발 > c++' 카테고리의 다른 글
c++의 include define, extern, memcpy_s (0) | 2024.12.09 |
---|---|
c++의 지역변수, 전역변수, 메모리 영역, static 변수, 동적할당, 함수 오버로딩, 함수의 디폴트 인자 (0) | 2024.12.08 |
c++의 구조체, 구조체 크기와 구조체 멤버맞춤 (0) | 2024.12.07 |
c++의 함수 (0) | 2024.12.06 |
c++의 구조, 문자열 출력, 변수, 상수, 형변환 (0) | 2024.12.04 |
댓글