배움 저장소
[홍정모의 따라하며 배우는 C++] 5.흐름제어 본문
5.1 제어 흐름 개요 (Control Flow)
- 프로그래밍은 CPU에게 특정 명령을 실행시킴을 말한다.
- 이때 코드의 묶음을 다양한 흐름으로 실행할 수 있다. 이를 Control Flow라 하고 5가지 종류가 있다.
종류 | Keyword |
Halt(중단) | |
Jump(점프) | goto, break, continue |
Conditional Branches(조건 분기) | if, switch |
Loops(반복) | while, do while, for |
Exceptions(예외 처리) | try, catch, throw |
exit( ) vs return
- <cstdlib>라이브러리에서 exit(int) 함수를 사용하여 프로그램을 긴급하게 종료시킬 수 있다. 이때 Parameter를 운영체제에게 전달하며 디버깅 용도로 사용된다.
- return keyword는 자료형에 맞는 반환값을 전달하고 해당 함수가 종료된다.
5.2 조건문 if
if ( expression )를 잘못 사용한 사례
- if(x = -1)에서 x=-1이 실행되고 if(x) 조건문을 실행하여 항상 참이된다.
int x = 0 ;
if (x = -1)
{
cout << "x=" << x << endl;
}
cout << "x is " << x << endl;
>> x=-1
>> x is -1
5.3 switch-case
break keyword가 없으면 다음 case를 실행시킨다. 의도하였다면 주석을 남기자
int x = 0;
switch (x)
{
case 0: // work with case 1
cout << "Zero"; // no break on 0
case 1:
cout << "One";
break;
case 2:
cout << "Two";
break;
}
cout << endl;
enum class와 함께 사용하는 switch-case
- switch-case는 enum(열거형) 혹은 enum class(영역제한 열거형)과 많이 쓴다. 정수 x를 명시적 변환하여 사용하였다.
enum class Colors
{
BLACK,
WHITE,
RED,
GREEN,
};
int main()
{
int x;
cin >> x;
switch ((Colors)x)
{
case Colors::BLACK:
cout << "BLACK";
break;
case Colors::WHITE:
cout << "WHITE";
break;
case Colors::RED:
cout << "Red";
break;
case Colors::GREEN:
cout << "Green";
break;
default:
cout << "Undefined Number " << x << endl;
}
}
이 때 case마다 class Tag를 붙여줌이 번거로울 수 있다. 아래의 예제를 보자.
static_cast를 활용하여 enum class 변수를 간략하게 표시할 수 있다
Colors col = Colors::BLACK;
switch (static_cast<int>(col))
{
case 0:
cout << "BLACK";
break;
case 1:
cout << "WHITE";
break;
case 2:
cout << "Red";
break;
}
switch-case에서 변수 초기화/선언하기
case 분기 이전 변수를 선언할 수 있다
switch (x)
{
int a;
case 0:
a = 1;
break;
}
case 분기 이후에 변수를 선언하여도 내부적으로 case 분기 이전에 선언된다
int x = 1;
switch (x)
{
case 0:
int a;
break;
case 1:
a = 111;
cout << a << endl;
break;
}
>> 111
switch-case 내부에서 변수를 초기화 할 수 없다. 반드시 선언 이후 값을 할당하자
- 아래 코드는 다음과 같은 에러메세지를 출력한다. error C2360: initialization of 'a' is skipped by 'case' label
int x = 1;
switch (x)
{
int a = 1;
case 0:
break;
}
case분기문이 1개일 때 초기화 할 수 있다. 2개 이상일 때는 초기화 할 수 없다
- 위와 동일한 에러메세지를 출력한다.
int x = 1;
switch (x)
{
case 0:
int a = 1;
break;
case 1:
cout << "Work!";
}
switch-case에서 초기화 하고 싶다면 { }로 새로운 Scope(영역)을 만들어주자
int x = 0;
switch (x)
{
case 0:
{
int a = 1;
cout << a << endl;
break;
}
case 1:
cout << "Work!";
break;
default:
cout << "Undefined Input " << x << endl;
}
- default keyword는 정의되지 않은 case일 때 실행된다. break를 넣지 않아도 된다.
Visual Studio의 자동완성 기능 활용하기
- < switch문 자동완성 > 'switch' 입력 → (tab) → enum class 이름 (위 예제에서는 'Colors')입력 → 다른곳 클릭
5.4 goto
잘 사용하지 않는다
5.5 반복문 while
- while 반복문 내부 body에 사용자 정의 자료형을 정의/선언하면 느려질 수 있다. 외부에서 정의/선언 하자.
- unsigned int가 최적화에 유리하다
5.6 반복문 do-while
do-while반복문은 한 번은 반드시 실행시킨다
5.7 반복문 for
5.8 break, continue
do while 반복문의 잘못된 사용예제
- 아래 코드는 Infinite Loop에 빠진다.
int count(0);
do
{
if(count == 2) continue;
count++;
cout << count << endl;
}while(count < 5);
(1) if 조건문의 순서를 바꾸어주면 해결된다.
int count(0);
do
{
count++;
cout << count << endl;
if(count == 2) continue;
}while(count < 5);
(2) while(expression) 내부에 증감연산자를 넣으면 해결된다.
int count(0);
do
{
if(count == 2) continue;
cout << count << endl;
}while(++count < 5);
5.9 난수 만들기 random numbers
난수 생성 직접 구현해보기
- seed를 static으로 지정하자. 함수가 실행될 때마다 초기화 됨을 막아준다. 효율적이다.
- 아래와 같은 방법으로 난수를 생성할 수 있다. 실전에는 standard library를 사용한다.
unsigned int GetRand()
{
static unsigned int seed = 1234;
seed = 23467823 * seed + 438057;
return seed % 23530;
}
int main()
{
for (int i = 0; i < 10; ++i)
cout << GetRand() << endl;
}
12823
5890
19301
7786
15717
4252
5055
21032
10469
5552
<cstdlib>라이브러리 활용하기
- 아래 함수는 몇 번을 반복하여도 동일한 결과값이 나온다. seed가 동일하면 난수 생성 규칙이 동일하다.
#include <iostream>
#include <cstdlib> // std::radn(), std::srand()
using namespace std;
int main()
{
std::srand(1234); // seed
for (int i = 0; i < 10; ++i)
cout << std::rand() << endl;
}
4068
213
12761
8758
23056
7717
15274
24508
4056
13304
난수 규칙을 랜덤으로 바꾸어주기 위하여 <ctime>라이브러리를 활용해보자
#include <iostream>
#include <cstdlib> // std::radn(), std::srand()
#include <ctime>
using namespace std;
int main()
{
std::srand(static_cast<unsigned int>(time(0))); // seed
for (int i = 0; i < 10; ++i)
cout << std::rand() << endl;
}
최소값과 최대값 사이에서 난수 생성해보기
int getRandomNumber(int min, int max)
{
static const double fraction = 1.0 / (RAND_MAX + 1.0); // much faster
return min + static_cast<int>( (max - min + 1 ) * (std::rand() * fraction));
}
<random>라이브러리 활용하기
(1) random_device로 random에 필요한 정보를 담은 객체를 생성한다.
(2) seed를 생성한다.
(3) 분포를 설정한다.
(4) 설정한 분포값 사이에서 난수를 생성한다.
#include <iostream>
#include <random>
using namespace std;
int main()
{
std::random_device rd; // object for random implementation
std::mt19937_64 mesennce(rd()); // seeding, mesennce is mathematician
std::uniform_int_distribution<>dice(1,6); // set distribution
// all possiblity adjusted equal
for(int i=0; i<10; ++i)
cout << dice(mesennce) << endl;
}
5.10 std::cin 더 잘 쓰기
아래는 덧셈 뺄샘 계산기 코드이다. 예외처리까지 구현되었다
- 아래에서 cin.clear()함수는 cin 객체의 flag를 초기화 시킨다. cin 객체는 입력받을 때 EOF, 에러발생, 입력 성공의 경우를 각각 비트 플래그로 저장한다.
#include <iostream>
using namespace std;
int getInt()
{
while (true)
{
cout << "Enter an Integer Number : ";
int x;
cin >> x;
if (std::cin.fail()) // ex) if x get over INTMAX, it makes infitite loop
{
std::cin.clear(); // clear everything in "control in"
std::cin.ignore(32767, '\n'); // ignore first parameter's buffered
// or ignore till meet '\n' character
cout << "Invalid number, please try again" << endl;
}
else
{
std::cin.ignore(32767, '\n');
return x;
}
}
}
void printResult(int x, char op, int y)
{
if(op == '+') cout << x+y << endl;
else if(op == '-') cout << x-y << endl;
else
{
cout << "Invalid operator" << endl;
}
}
char getOperator()
{
while (true)
{
cout << "Enter an operator(+, -) : ";
char op;
cin >> op;
std::cin.ignore(32767, '\n');
if(op == '+' || op == '-')
return op;
else
cout << "Invalid Operator, please try again" << endl;
}
}
int main()
{
int x = getInt();
int y = getInt();
char ch = getOperator();
printResult(x,ch,y);
}
'Programming Language > C++' 카테고리의 다른 글
[홍정모의 따라하며 배우는 C++] 7. 함수 (0) | 2021.12.23 |
---|---|
[홍정모의 따라하며 배우는 C++] 6. 행렬, 문자열, 포인터, 참조 (0) | 2021.12.19 |
[홍정모의 따라하며 배우는 C++] 4.변수 범위와 더 다양한 변수형 (0) | 2021.12.15 |
[홍정모의 따라하며 배우는 C++] 3. 연산자들 (0) | 2021.12.14 |
[홍정모의 따라하며 배우는 C++] 2.변수와 기본적인 자료형 (0) | 2021.12.12 |