반복문

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

 

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 를 사용한다.

 

형 변환

-> 서로 다른 타입간의 변환

 

묵시적 형 변환

-> 사용자가 의도하지 않아도 컴파일러가 자동으로 변환해주는 것

 

명시적 형 변환

-> 사용자가 의도한 형 변환

 

형 변환 규칙

#1 대입 연산자 기준

-> 대입 연산자 기준으로 좌측 자료형으로 형 변환이 발생한다.

 

묵시적 형 변환

int i = 3.14;
// double형 3.14라는 데이터가 int형 3이라는 정수로 형 변환되서 a에 대입된다.

double b = 3;
// int형 3이라는 데이터가 double형 3.0으로 형 변환되서 b에 대입된다.

명시적 형 변환

int a = (int)3.14;
int a = int(3.14);

#2 산술 연산 시 기준 (묵시적 형 변환)

 

정수 대 실수

-> 실수 형으로 형 변환

-> cout << (3 * 3.1) << endl;

-> 9.3

 

같은 타입, 크기가 다를 경우

-> 크기가 큰 쪽으로 형 변환

예)

int a = 3; (4byte)

long long b = 20; (8byte)

타입이 같고 크기가 다르기 때문에 8byte가 나온다.

 

float a = 3.14f; (4byte)

long long b = 20; (8byte)

cout << sizeof(a + b) << endl;

타입이 다르기 때문에 4byte가 나온다.

진수란?

-> 숫자를 표현하는 방법

 

진수의 종류

10진수 0 ~ 9까지 총 10개의 숫자를 표현할 수 있다.
-> 보통 사용하는 숫자 표현
2진수 0과 1 두 가지만 사용하여 표현할 수 있다. 
-> 기계어가 2진수로 되어 있다.
8진수 0 ~ 7까지 총 8개의 숫자를 표현할 수 있다.
-> 정수 앞에 0을 붙여서 8진수라고 명시해준다.
-> 각 자리당 000 ~ 111까지 표현할 수 있다.
16진수 0 ~ 15까지 총 16개의 숫자를 표현할 수 있다. / 정수 앞에 0x를 붙여서 16진수라고 명시해준다.
-> 10이상부터는 알파벳을 사용하여 혼돈을 방지한다.
-> 각 자리당 0000 ~ 1111까지 표현할 수 있다.

진수 변환 방법

10진수 -> 2진수 : 10진수의 값을 2로 나눠서 몫이 1이 되어 나누어 지지 않을 때까지 나누어 준다.

-> 그 후에 몫 1과 나머지 값을 아래부터 위에 순서로 명시해준다.

-> 예) 90 -> 1011010

10진수 -> 8진수 : 10진수의 값을 8로 나눠서 남은 숫자가 1이 나올 떄까지 나눠준다.

-> 예) 90 -> 0132

10진수 -> 16진수 : 10진수의 값을 16으로 나눌 수 없을 때까지 나눠준다.

나눌 수 없을때 몫을 0x앞에 나머지를 몫의 뒤에 명시해준다.

-> 예) 90 -> 0x5A

 

8진수, 16진수 -> 2진수 : 각 진수의 결과 값을 2진수로 풀어서 계산해본다.

 

-> 8진수 예) 0132 = 1011010 -> 90

 

-> 16진수 예) 0x5A = 1011010 -> 90

 

연산자

-> 연산 후 결과를 반환하는 것

 

연산자 종류

산술 연산자 +, -, *, /, %
-> 이항 연산자
대입 연산자
-> 이항 연산자
-> 대입 연산자 기준 양 항은 같은 타입의 자료형이어야 한다.
-> 대입은 우측에서 좌측으로 이루어진다.
-> 연산자는 연산 후 결과를 반환하기 때문에 연속 대입이 가능하다.
sizeof연산자 자료형이나 변수가 할당된 공간에 크기를 알아보기 위해 사용한다.
-> sizeof 연산자를 이용할 경우 자료형 또는 변수의 크기를 byte단위로 확인할 수 있다.
-> 예)
cout << sizeof(char) << endl;
cout << sizeof(int) << endl;
-> 한가지 더 예를 들어보면
-> 자료형 char에 a와 b라는 변수명을 지어주고 a 값은 'A' b는 'B'로 지어준다
-> 그럼 여기서 sizeof로 크기를 확인하면 4가 나오게 된다.
-> 왜냐하면 char에는 결과 값이 정수 값으로 저장이 되기 때문이다.
논리 연산자 &&(and)
-> 이항 연산자
-> 피 연산자로 조건을 취한다.
-> 두 조건을 만족하는 경우, 또는 하나만 만족하는 경우 등을 판별할 때 사용한다.
-> 두 조건이 모두 참이어야 참이다.
-> 하나라도 거짓일 경우 거짓이 된다.
-> 단, 시작부터 거짓이 올 경우 다음 연산은 수행하지 않는다.

||(or)
-> 이항 연산자
-> 둘 중 하나라도 참이면 참.
-> 둘 다 거짓이어야만 거짓이 된다.
-> 시작부터 참이 올 경우 다음 연산은 수행하지 않는다.

!(not)
-> 단항 연산자
-> 논리 부정
-> 참과 거짓을 서로 바꾼다( true -> false, false -> true )
비트단위 연산자 -> 이항 연산자
-> 논리 연산을 수행한다.
-> 단, 비트 단위로 수행한다.
-> &(AND), |(OR), ^(XOR), !(NOT)

&(AND)
-> 논리 연산자의 AND와 동일한 역할을 수행한다.
-> 단, 비트 단위로 비교를 한다.
-> 둘 다 1일 경우 참

|(OR)
-> 둘 중 하나라도 1일 경우 참, 둘 다 0일 경우 거짓

^(XOR)
-> 두 비트가 같으면 0, 다르면 1

~(NOT)
-> 0과 1을 서로 바꿔준다.
-> 1의 보수와 같다.
비트 단위 쉬프트 연산자 <<, >>
-> 이항 연산자
-> 본 기능은 쉬프트 연산자 이지만 cout / cin과 만나면 입출력 연산자로 사용이 된다.
-> 좌측 피 연산자의 모든 비트열을 << / >> 방향으로 우측 피 연산자의 값 만큼 이동시킨다.
-> 단, 표현할 수 있는 비트를 넘어가면 값이 소실될 수 있다.
-> 또한, 부호비트가 변경될 수 있다.
-> <<은 n * 2^n 이고, >>은 n / 2^n이다.
-> 쉬프트 연산자는 정수만 연산이 가능하다.

n / 2 와 n >> 1의 차이
/ 가 * 보다 속도가 무려 10배 가까이 차이가 난다고 함
속도가 빠른 순 << -> >> -> * -> / 

정수를 표현할 때는 쉬프트 연산자를 사용하면 좋다.(속도 때문에)
실수를 표현할 때는 어쩔 수 없이 /, * 연산자를 사용한다.

사용 예)
bitset<8> a = 10, b = 0
b = a << 3;
축약 연산자 +=, -=, *=, /=, %=, <<=, >>= 등
-> 코드의 간결화를 위해서 사용한다.
증감 연산자 ++, --
-> 피 연산자의 값을 1 증가 혹은 1 감소 시켜주는 연산자
-> 단, 증감 연산자가 피 연산자 앞 또는 뒤에 붙을 경우 다르게 작동한다.

전위 증감
-> 선 증감 후 연산
++i

후위 증감
-> 선 연산 후 증감
i++

전위 증감과 후위 증감의 차이점
-> 전위 증감은 본인이 증가 후 본인을 통해 연산을 수행한다.
-> 후위 증감은 본인과 동일한 임시 객체를 만든 후 본인은 증가 임시 객체는 연산에 반영한다.
-> 전위, 후위 둘 다 사용해도 무관할 경우 전위 연산자가 더 빠르다.
단항 연산자 피 연사자 1개 
이항 연산자 피 연사자 2개
삼항 연산자 피 연사자 3개
-> 조건 ? 참일 경우 수행 : 거짓일 경우 수행

 

bitset
-> 정수를 데이터로 취한다.
-> 받은 정수를 2진수로 변환한 값을 보여준다.
-> 단, bitset을 사용하기 위해서는 #include <bitset> 의 추가가 필요하다.
사용 예)
bitset<?> : ?에 비트를 입력한다.

-> 4비트로 표시하고 싶을 때

-> bitset<4> A = 5, A = 6;

 

+ Recent posts