함수

-> input이 있으면, Output이 있는 것.

-> 수학적인 의미의 함수로는 y = f(x)가 있다.

-> 여기서 f는 Function의 약자이며. "기능"이라고 한다.

 

함수를 사용하는 이유

#1 재사용성

-> 함수를 한 번 만들어 놓으면 언제, 어디서든 사용자가 원할 때 불러와서 사용할 수가 있다.

 

#2 협업

-> 여러 사람들과 협업을 할 때 주로 사용을 한다.

 

함수의 종류 4가지
#1. Input이 있고, Output이 있다.
-> y = f(x), 빵공장, 라면공장 등

#2. Input이 있고, Output이 없다.
-> srand(시드값), system(문자열)

#3. Input이 없고, Output이 있다.
-> int iA = rand()

#4. Input이 없고, Output이 없다.
-> main 함수

 

함수의 형태

 

반환타입(int, float, void) 함수이름(PlayerCtrl) (인자 / 매개변수 / 파라미터)

{

기능 구현

}

 

반환타입 : 함수를 수행 후 가공된 결과를 내보낼 것이 있을 때 명시한다.
반환할 데이터의 자료형을 명시해주면 된다.
반환할 데이터가 없을 경우 void라고 명시한다.

 

함수이름

-> 말 그대로 함수의 이름이다.
-> 함수가 수행하는 기능을 뜻하는 이름으로 지어주는 것이 좋다. 

매개변수

-> 함수를 구현(가동)하는데 필요한 재료들을 명시할 수 있다.
-> 변수 하나당 자료형 하나씩 매칭하여 필요한 만큼 명시해주어야 한다.

기능구현

->함수의 기능을 작성하는 공간이다.

 

return
-> 코드 라인을 수행 중 return을 만나면 해당 함수가 종료된다.
-> 반환 타입이 void가 아닐 경우에는 return 뒤에 반환할 데이터를 명시해야한다.
-> 반환 타입이 void일 경우에는 return뒤는 생략이 가능하다.

 

함수 호출
-> 함수명 + 함수 호출 연산자
-> 함수 호출 연산자 : ()
-> 만약, 매개 변수에 넘겨줄 데이터가 있을 경우 ()안에 순차적으로 나열해준다.

 

사용 예)

#include <iostream>
using namespace std;


int Add(int _a, int _b)
{
	int Result = _a + _b;

	return Result;	
}

void main()
{
	int a = 10;
	int b = 20;

	Add(a, b);

	cout << Add(a, b) << endl;
}

난수 (random)
-> 순서나 규칙이 없는 무작위 수
->아이템 강화, 랜덤 박스, 크리티컬 확률 등
-> 확률이 적용되는 모든 것에 난수가 사용된다.

 

 

난수 추출 함수

-> rand()

-> rand함수를 사용하면 난수가 추출된다,

-> 단, 실행 할 때마다 같은 결과가 도출된다.

-> 위험한 상황이 발생할 수 있다.

 

 

난수 추출 시 같은 결과가 나오는 이유
-> 난수 추출 시 컴퓨터는 seed 값을 확인하여
-> 해당 seed 값에 있는 난수를 순차적으로 추출해준다.
-> 사용자가 seed 값을 변경하지 않을 경우 기본적으로 1의 값을 가진다.
-> 이로 인해 프로그램을 다시 실행할 경우에는 중복된 숫자가 보인다.

 


seed 변경
srand(시드값) -> srand(12);
단, 시드 값을 변경한다해도 고정된 숫자가 추출되는 것은 동일하다!
이를 해결하기 위해 프로그램을 실행할 때마다 시드 값을 변경해줄 필요가 있다.

 

중복되지 않는 seed값
시간
-> 하루 단위, 한달 단위, 일년 단위 등 기간이 정해지면 중복된 숫자가 나올 수 있다.
-> 이를 방지하기 위해 기간을 설정하지 않고 계속해서 누적해나가는 시간이 필요하다!
-> 누적해 나간다 라는 말은 기준 시간이 필요하다.
-> 1970년 1월 1일부터 시간을 누적하고 있다.

 

누적한 시간을 확인하는 함수
-> time(0)
-> 단, time함수를 사용하기 위해서는 #include <time.h> 추가가 필요하다.

srand(unsigned(time(NULL)));

 

 

rand함수가 추출해주는 범위
-> 0 ~ 32767까의 범위에서 추출해준다

 

srand 사용 시 주의 사항
-> srand를 이용하여 seed값을 변경하면 추출 순서가 초기화 된다.
-> srand는 main 함수에 최초 1회만 선언해주면 된다.

-> 만약 여러번 선언을 하게 되는 경우 seed 값의 초기화가 여러번 진행되어 문제가 발생할 수 있다.

'Programming > C++ Basic' 카테고리의 다른 글

C++ 지역 변수, 전역 변수, 정적 변수(static)  (0) 2020.08.24
C++ 함수란?  (0) 2020.08.24
C++ 반복문(for, while, do ~ while), goto 문  (0) 2020.08.19
C++ 분기문(if, else if, else, switch)  (0) 2020.08.19
C++ 형변환  (0) 2020.08.18

반복문

-> 반복적인 코드를 효과적으로 해결할 수 있는 문법

 

while문

-> while로 받은 조건이 참일 경우 중괄호 안에 있는 코드블럭을 수행 후,

조건을 다시 비교하여 참일 경우 코드 블록을 재수행 한다.

-> 조건이 거짓이 될 때까지 조건을 수행한다.

 

-> 반복문의 조건이 계속 참일 경우 무한 루프에 빠질 수 있다.

 

무한 루프 탈출 방법

#1 break

	int a = 0;
	while (true)
	{
		if (10 < a)
			break;

		++a;
		cout << a << endl;
	}

#2 조건식의 조건으로 탈출

int a = 0;
	while (10 > a)
	{
		++a;
		cout << a << endl;
	}

do while

-> while과 같은 반복문이다.

-> 단, 최초 1회는 코드 블록을 수행 후 조건을 비교하여 추가 수행 여부를 결정한다.

do
{ // 여기부터

코드 블록

} // 여기까지
while (조건)

 

continue

-> 반복문 내부에서만 사용이 가능한 명령어

-> 반복문 수행 중 continue 키워드를 만나면 반복문 맨 끝으로 이동시켜준다.

do 
{ 


코드 블럭


} << continue가 나오면 여기로 이동
while (조건)

 

while과 do while의 차이점

#1 while

-> 조건을 비교하여 코드 블록의 수행 여부를 결정

 

#2 do while

-> 코드 블록을 최초 1회 수행 후 조건을 비교하여 추가 수행 여부를 결정

 

goto 문

-> 프로그램의 흐름을 사용자가 원하는 곳으로 이동 시킬 때 사용한다.

-> 프로그램의 흐름을 강제로 이동시키기 때문에 효율이 좋지 않다.

 

사용 예)

	int		a = 0;
	goto AABBCC; 


	a = 999;
    
AABBCC: // goto AABBCC 다음 AABBCC:로 이동 하여 999는 대입이 되지않음.

	cout << a << endl;

 

 

for문

-> 반복 횟수가 정해져있을 때 유용하게 사용할 수 있다.

-> 변수 선언, 증감, 비교가 한 곳에 모여있어 가독성이 뛰어나다.

 

사용 예)

for(변수 선언; 조건; 증감)

{

코드 블록

}

 

순서 : 변수 선언 -> 조건 -> 코드 블록 -> 증감 -> 조건 -> 코드 블록 -> 증감

 

변수 선언

-> for문에서 사용할 변수를 선언 할 수 있다.

-> 선언과 동시에 초기화도 가능하다.

-> for문 실행 시 최초로 수행되며, 단 한번만 적용된다.

 

조건식

-> 조건을 비교하여 참이 나올 경우 조건이 거짓이 될 때 까지 코드 블록을 수행한다.

 

증감식

-> 코드 블록을 수행 후 증감식이 적용된다.

 

n중 for문

-> for문 내부에 for문이 작성되어 있는 것

-> 3중 for문은 자주 사용하지 않는다.

-> n이 증가할수록 반복 횟수가 기하급수적으로 늘어나기 때문이다.

 

범위기반 for문(Ranged-based for loop)

-> 범위 기반 for문은 고정 배열뿐만 아니라 std::vector, list, set, map과 같은 구조에서도 작동한다.

-> 적용 가능한 곳이라면 범위기반 for 문을 사용하는 것이 좋다.

'Programming > C++ Basic' 카테고리의 다른 글

C++ 함수란?  (0) 2020.08.24
C++ 난수(rand, srand)  (0) 2020.08.20
C++ 분기문(if, else if, else, switch)  (0) 2020.08.19
C++ 형변환  (0) 2020.08.18
C++ 진수, 연산자  (0) 2020.08.14

if문

-> if문으로 조건을 받아서 조건이 참일 경우 실행, 참이 아닐 경우 실행하지 않는다.

if(조건)

{

코드 블록

}

조건이 참일 경우 코드 블록을 수행

 

else if

-> if문으로 여러 조건을 검사 할 때 사용한다.

-> if 짝을 이루어야 하며, 혼자 존재할 수 없다.

-> 중복되는 동일한 조건이 있을 경우 우선적으로 참이 되는 if 또는 else if문만 수행한다.

 

if문 사용 시 주의 사항

#1 if와 else if 또는 else 사이에 코드라인이 올 수 없다.

-> 수행해야할 코드 라인이 한 줄일 경우 중괄호는 생략할 수 있다.

 

switch 문

-> 상수 조건 분기문

-> 정수로된 변수 또는 상수 조건을 받아서 상수로 분기한다.

switch(조건)

{

case 상수:

코드블럭 실행

break;

case 상수:

코드블럭 실행

break;

case 상수:

코드블럭 실행

break;

}

 

break란?

-> switch 또는 반복문 내부에서만 사용이 가능하다.

-> 코드 라인을 수행 중 break를 만나면 가장 가까운 switch 또는 반복문을 탈출한다.

 

default

-> if문의 else와 비슷하게 작동한다.

-> 분기할 상수가 없을 경우 default를 수행한다.

-> 가장 하단에 배치하는게 좋다.

switch(조건)

{

case 상수:

코드블럭 실행

break;

case 상수:

코드블럭 실행

break;

default:

잘못 입력

break;

}

 

switch case 문 끝에 break;를 넣지 않고 그 바로 아래 case 문의 코드를 실행하고 싶은 경우,

미리 정의해둔 FALLTHROUGH 매크로를 추가한다. 단, case 문 안에 코드가 없는 경우는 예외이다.

switch (n)
{
case 0:
    Func();
    FALLTHROUGH
case 1:
    Func2();
    break;
case 2:
case 3:
    Func3();
    break;
default:
    break;
}

 

default case가 절대 실행될 일이 없는 경우, default case 안에 Assert(false); 란 코드를 추가한다.

Assert()는 직접 구현하면 그 안에서 릴리즈 빌드 시 최적화 힌트를 추가할 수 있다.

switch (type)
{
case 1:
    ... 
    break;
default:
    Assert(false, "unknown type");
    break;
}

특정조건이 반드시 충족되어야 한다고 가정하고 짠 코드 모든 곳에 assert를 사용한다.

assert는 복구 불가능한 조건이다.

assert는 릴리즈 빌드에서 __assume 키워드로 대체하여 컴파일러의 최적화에 도움이 된다.

 

__assume(0) 사용

switch (type)
{
case 1:
    ... 
    break;
default:
    __assume(0);
    break;
}

__assume(0)로 컴파일러는 case 명령문에 표시되지 않은 값이 있는지 여부를 테스트하는 코드를 생성하지 않는다 .

이 작업을 수행하려면 __assume(0)문이 기본 case 본문의 첫 번째 문이어야한다.

 

컴파일러는 런타임을 기반으로 코드를 생성하기 때문에 명령문 __assume내부 __assume의식이 런타임에 false 이면

해당 코드가 올바르게 실행되지 않을 수 있다.

 

런타임에 식이 항상 참인지 확실하지 않은 경우 assert함수를 사용하여 코드를 보호 할 수 있다.

#define ASSERT(e)    ( ((e) || assert(__FILE__, __LINE__)), __assume(e) )

 

하지만, 이 사용은 assert컴파일러가 최적화를 수행하지 못하게한다.

그래서 다음과 같이 별도의 매크로를 사용할 수 있다.

#ifdef DEBUG
# define NODEFAULT   ASSERT(0)
#else
# define NODEFAULT   __assume(0)
#endif

   default:
      NODEFAULT;

가능한 Assert 대신 static_assert 를 사용한다.

 

+ Recent posts