2장 제어 흐름

2023. 10. 30. 21:35프로그래밍 공부/OOP

2.1 부울식

부울식: 참이거나 거짓인 모든 표현

 

디스플레이 2.1 비교 연산자

MATH
SYMBOL
ENGLISH C++ NOTATION C++ SAMPLE MATH
EQUIVALENT
= Equal to == x + 7 = = 2*y x + 7 = 2y
Not equal to != ans != 'n' ans ≠ ‘n’
< Less than < count < m + 3 count < m + 3
Less than or
equal to
<= time <= limit time limit
> Greater than > time > limit time > limit
Greater than
or equal to
>= age >= 21 age 21

 

부울식 세우기

and 연산자: &&

예시)

(2 < x) && (x < 7)

 

or 연산자: ||

예시)

(y < 0)||(y < 12)

 

부정 연산자: !

!(x < y) == (x >= y)

 

함정: 부등식의 연속

부등식을 연속해서 사용하지 말기

x < z < y

->

(x < z) && (z < y)


부울식 평가

bool의 값은 true나 false로 나올 수 있음

예시)

bool result = (x < z) && (z < y)

 

예시)

!( (y < 3) || (y > 7) )

y = 8 이라고 가정하면 

!( (y < 3) || (y > 7) ) = !( false || true ) = !(true) = false

 

디스플레이 2.2 진리표(truth table)

AND

Exp_1 Exp_2 Exp_1 && Exp_2
true true true
true false false
false true false
false false false

 

OR

Exp_1 Exp_2 Exp_1 && Exp_2
true true true
true false true
false true true
false false false

 

NOT

Exp !(Exp)
true false
false true


우선 순위 규칙

부울 식은 꼭 괄호를 충분히 사용할 필요가 없다!

괄호를 생략하면 기본 우선 순위에 따른다.

하지만 가독성 향상을 위해 괄호를 사용하는 것이 좋은 관행이다.

예시)

(temperature > 90) && (humidity > 0.90) && (poolGate == OPEN)

 

우선 순위 규칙(precedence rules): 괄호를 생략하면 컴파일러 그룹은 우선순위 규칙에 따라 아이템을 정렬한다.

한 작업이 다른 작업보다 먼저 수행된 경우 먼저 수행된 작업이 우선 순위가 더 높다(higher precedence)고 합니다.

 

아래 표에서 위에 위치할 수록 연산자 우선순위가 높고 아래로 내려갈 수록 연산자 우선 순위가 낮아진다.

디스플레이 2.3 연산자 우선 순위

:: Scope resolution operator
.
->
[]
( )
++
--
Dot operator
Member selection
Array indexing
Function call
Postfix increment operator (placed after the variable)
Postfix decrement operator (placed after the variable)
++
--
!
-
+
*
&
new
delete
delete []
sizeof
( )
Prefix increment operator (placed before the variable)
Prefix decrement operator (placed before the variable)
Not
Unary minus
Unary plus
Dereference
Address of
Create (allocate memory)
Destroy (deallocate)
Destroy array (deallocate)
Size of object
Type cast
*
/
%
Multiply
Divide
Remainder (modulo)
+
-
Addition
Subtraction
<<
>>
Insertion operator (console output)
Extraction operator (console input)
<
>
<=
>=
Less than
Greater than
Less than or equal to
Greater than or equal to
==
!=
Equal
Not equal
&& And
|| Or
=
+=
-=
*=
/=
%=
Assignment
Add and assign
Subtract and assign
Multiply and assign
Divide and assign
Modulo and assign
?: Conditional operator
throw Throw an exception
, Comma operator

 

단락 평가(short-circuit evaluation): 두 번째 식의 값과 무관하게 식의 최종 값을 결정할 수 있는 충분한 정보를 제공하는 경우 C++는 굳이 두 번째 식을 평가하지 않는 방법

예시)

(x >= 0) && (y > 1)

만약 x가 음수이면 첫번째 식에서 이미 false이므로 두번째 식을 평가하지 않는다.

(x > 1) && (y++)

증가, 감소 연산자에 유의하자!

 


함정: 정수 값을 부울 값처럼 사용할 수 있다

true -> 1

false -> 0

모든 0이 아닌 값 -> true

0 값 -> false

 

2.2 분기 메커니즘

if-else 문

if-else 문은 부울 식을 기반으로 두 가지 대체 동작 중 하나를 선택합니다.

부울 식을 괄호 안에 넣어야 한다는 점에 유의하세요.

SYNTAX: A SINGLE STATEMENT FOR EACH ALTERNATIVE
if ( Boolean_Expression)
    Yes_Statement
else
    No_Statement

Boolean_Expression이 true로 평가되면 Yes_Statement가 실행됩니다.
Boolean_Expression이 false로 평가되면 No_Statement가 실행됩니다.

 

EXAMPLE
if (hours > 40)
    grossPay = rate * 40 + 1.5 * rate * (hours - 40);
else
    grossPay = rate * hours;


복합문

복합문(compound statement): 괄호 안에 포함된 문장 목록

복합문은 C++에 의해 하나의 문장으로 취급되며, 하나의 문장이 사용될 수 있는 모든 곳에 사용될 수 있습니다.

 

SYNTAX: A SEQUENCE OF STATEMENTS FOR EACH ALTERNATIVE
if ( Boolean_Expression)
{
    Yes_Statement_1
    Yes_Statement_2
    ...
    Yes_Statement_Last
}
else
{
    No_Statement_1
    No_Statement_2
    ...
    No_Statement_Last
}

 

EXAMPLE

if (myScore > yourScore)
{
    cout << "I win!\n";
    wager = wager + 100;
}
else
{
    cout << "I wish these were golf scores.\n";
    wager = 0;
}


함정: == 대신하여 = 이용하기

if (x = 12)
    Do_Something
else
    Do_Something_Else

== 는 비교연산자라서 true 인지 false인지 여부를 알려주지만

=는 할당연산자라서 true, false 여부와 관계가 없어 컴파일러가 에러 메세지를 발생한다.

C++에 코드 작성 후 ==을 잘 사용했는지 여부를 체크하자.

 

else 생략하기

if-else 문에서 두 대안 중 하나가 아무것도 하지 않기를 원할 때가 있습니다.

C++에서는 다른 부분을 생략함으로써 이를 달성할 수 있습니다.

이러한 종류의 문을 if-else 문과 구별하기 위해 if 문이라고 합니다.

예를 들어, 다음 두 문 중 첫 번째 문이 if 문입니다:

if (sales >= minimum)
    salary = salary + bonus;
cout << "salary = $" << salary;

 

중첩문(Nested Statements)

if-else 문장의 하위 부분 또는 그 안에 하나 이상의 문장을 포함하는 다른 문장의 하위 부분으로 사용될 수 있습니다.

중첩 문을 중첩할 때 일반적으로 각 수준의 중첩 부분문을 들여씁니다.

 

다중 if-else 문

부울 식을 순서대로 확인한 후 처음 참 부울 식을 찾을 때까지 해당 문을 실행합니다. 만약 부울 식을 참으로 지정하지 않으면 State_For_All_Other_Possibilities가 실행됩니다.

SYNTAX
if (Boolean_Expression_1)
    Statement_1
else if (Boolean_Expression_2)
    Statement_2
            .
            .
            .
else if (Boolean_Expression_n)
    Statement_n
else
    Statement_For_All_Other_Possibilities

 

EXAMPLE
if ((temperature < -10) && (day == SUNDAY))
    cout << "Stay home.";
else if (temperature < -10) // and day != SUNDAY
    cout << "Stay home, but call work.";
else if (temperature <= 0) // and temperature >= -10
    cout << "Dress warm.";
else // temperature > 0
    cout << "Work hard and play hard.";

 

switch문

switch문: 다중 분기를 구현하는 유일한 다른 종류의 C++ 문.

실행할 분기의 선택은 키워드 전환 후 괄호 안에 주어진 제어 표현에 의해 결정된다.

제어 표현은 부울 값, enum 상수, 정수나 문자 중 하나여야 한다.

case 식별자에 의해 경우의 수가 구분된다.

break문: break과 세미콜론(;)으로 이루어져 있는 구문

각 경우에 break 문을 둘 필요는 없습니다. break를 생략하면 break(또는 switch 문의 끝)에 도달할 때까지 해당 케이스는 계속됩니다.

아무 case에 해당하는 경우가 없으면 default로 이동한다.

 

SYNTAX
switch (Controlling_Expression)
{
    case Constant_1:
        Statement_Sequence_1
        break;
    case Constant_2:
        Statement_Sequence_2
        break;
                        .
                        .
                        .
    case Constant_n:
        Statement_Sequence_n
        break;
    default:
        Default_Statement_Sequence
}

 

EXAMPLE
int vehicleClass;
double toll;
cout << "Enter vehicle class: ";
cin >> vehicleClass;

 

switch (vehicleClass)
{
    case 1:
        cout << "Passenger car.";
        toll = 0.50;
        break;
    case 2:
        cout << "Bus.";
        toll = 1.50;
        break;
    case 3:
        cout << "Truck.";
        toll = 2.00;
        break;
    default:
        cout << "Unknown vehicle class!";
}

 

함정: switch문에서 break 잊기

switch문에서 break을 넣는 것을 잊어버리면 오류가 나지는 않으나 원하는 방향대로 동작하지 않을 것이다.


TIP: 메뉴에 대한 switch문 사용

다중 if-else문이 switch문보다 훨씬 다용도이며 모든 switch문을 대체할 수 있다.

하지만 때때로 switch문이 더 명확하다.

예를 들어, 메뉴를 실행할 때에는 switch문이 완벽하다.

 

열거형

열거형(Enumeration Types): 값이 int 유형의 상수 목록으로 정의되는 유형

예시)

enum MonthLength { JAN_LENGTH = 31, FEB_LENGTH = 28,
MAR_LENGTH = 31, APR_LENGTH = 30, MAY_LENGTH = 31,
JUN_LENGTH = 30, JUL_LENGTH = 31, AUG_LENGTH = 31,
SEP_LENGTH = 30, OCT_LENGTH = 31, NOV_LENGTH = 30,
DEC_LENGTH = 31 };

 

첫 번째 열거 상수의 기본값은 0입니다. 나머지는 열거 상수 중 하나 이상을 설정하지 않으면 1만큼 증가합니다.

예시1)
enum Direction { NORTH, SOUTH, EAST, WEST };

여기서 NORTH = 0, SOUTH = 1, EAST = 2, WEST = 3이 된다.

 

예시1)

enum MyEnum { ONE = 17, TWO, THREE, FOUR = -3, FIVE };

여기서 TWO = 18, THREE = 19, FIVE = -2가 된다.

 

열거형의 상수는 int 형이고 int로 쓰일 수 있다.

열거형은 별개의 형태이고 int 형이 아니다.

 

조건부 연산자

조건 연산자(삼항 연산자 또는 산술 if문이라고도 함)를 사용하여 식 안에 조건을 포함할 수 있습니다.
사용법은 오래된 프로그래밍 스타일을 연상시키므로 사용을 권장하지 않습니다.

조건 연산자는 if-else 문장의 특정 형태에 대한 표기 변형입니다.

if (n1 > n2)
    max = n1;
else
    max = n2;

이는 다음과 같이 조건 연산자를 사용하여 나타낼 수 있습니다:

max = (n1 > n2) ? n1 : n2;

할당 문의 오른쪽에 있는 식은 조건부 연산자 식입니다:

(n1 > n2) ? n1 : n2;

?와 :는 함께 조건 연산자(conditional operator)로 알려진 삼항 연산자(ternary operator)를 형성합니다.

조건 연산자 식을 부울 식 다음에 ?로 시작하여 콜론으로 구분된 두 식을 따릅니다.

부울 식이 참이면 두 식 중 첫 번째 식을 반환하고, 그렇지 않으면 두 식 중 두 번째 식을 반환합니다.

 

2.3 루프

루프 바디(loop body): 반복되는 코드

루프의 반복(iteration): 루프 바디의 반복

 

while문과 do-while문

Syntax for while and do-while Statements
A while STATEMENT WITH A SINGLE-STATEMENT BODY
  while (Boolean_Expression)
      Statement

 

A while STATEMENT WITH A MULTISTATEMENT BODY
  while (Boolean_Expression)
  {
      Statement_1
      Statement_2
              .
              .
              .
      Statement_Last
  }

 

A do-while STATEMENT WITH A SINGLE-STATEMENT BODY
  do
      Statement
  while (Boolean_Expression);
A do-while STATEMENT WITH
A MULTISTATEMENT BODY
  do
  {
      Statement_1
      Statement_2
              .
              .
              .
      Statement_Last
  } while (Boolean_Expression);

do-while문을 마칠 때 마지막 세미콜론을 잊지 마라!

 

while 문과 do-while문의 차이

while문은 루프 바디가 실행되기 에 부울식을 확인한다.

do-while문은 루프 바디가 실행된 에 부울식을 확인한다.

 

디스플레이 2.4 while문 예제

#include <iostream>
using namespace std;

int main( )

{
	int countDown;

	cout << "How many greetings do you want? ";
	cin >> countDown;

	while (countDown > 0)
	{
		cout << "Hello ";
		countDown = countDown - 1;
	}
    
	cout << endl;
	cout << "That's all!\n";
    
	return 0;
}

샘플 대화1

How many greetings do you want? 3
Hello Hello Hello
That's all!

 

샘플 대화 2

How many greetings do you want? 0
That's all!

루프 바디가 0번 실행하였다.

 

디스플레이 2.5 do-while문 예제

#include <iostream>
using namespace std;

int main( )

{
	int countDown;

	cout << "How many greetings do you want? ";
	cin >> countDown;

	do
	{
		cout << "Hello ";
		countDown = countDown - 1;
	} while (countDown > 0);
    
	cout << endl;
	cout << "That's all!\n";
    
	return 0;
}

샘플 대화1

How many greetings do you want? 3
Hello Hello Hello
That's all!

 

샘플 대화 2

How many greetings do you want? 0
Hello
That's all!

루프 바디가 항상 최소 1번은 실행한다.

 

증가 및 감소 연산자 재방문

while문의 부울 식에서 증가와 감소 연산자를 사용할 수 있다.

디스플레이 2.6에 예시가 나와 있다.

count++ <= numberOfItems>에서 count++로 반환되는 값은 증가하기 전의 count 값이다.

 

디스플레이 2.6 식에서의 증가 연산자

#include <iostream>
using namespace std;

int main( )
{
	int numberOfItems, count,
    	caloriesForItem, totalCalories;

	cout << "How many items did you eat today? ";
	cin >> numberOfItems;
	totalCalories = 0;
	count = 1;
	cout << "Enter the number of calories in each of the\n"
		 << numberOfItems << " items eaten:\n";
         
	while (count++ <= numberOfItems)
	{
		cin >> caloriesForItem;
		totalCalories = totalCalories
					     + caloriesForItem;
	}
    
	cout << "Total calories eaten today = "
		 << totalCalories << endl;
    return 0;
}

샘플 대화

How many items did you eat today? 7
Enter the number of calories in each of the
7 items eaten:
300 60 1200 600 150 1 120
Total calories eaten today =
2431

 

쉼표 연산자

쉼표 연산자(comma operator): 식 목록을 평가하고 마지막 식의 값을 반환하는 방법

for 루프에서 사용하는 것이 편리할 때가 있습니다.


예시)
result = (first = 2, second = first + 1);
쉼표 연산자는 앞 문장의 중앙에 있는 쉼표입니다.

쉼표 표현은 할당 연산자의 오른쪽에 있는 표현입니다.
쉼표 연산자는 피연산자로서 두 식을 갖습니다. 이 경우 두 피연산자는
first = 2 and second = first + 1
첫 번째 식을 평가하고, 두 번째 식을 평가합니다.

따라서 이 쉼표 식은 변수 second의 최종 값을 반환하고, 이는 변수 결과가 3과 동일하게 설정됨을 의미합니다.
두 번째 식의 값만 반환되므로 첫 번째 식의 부수 효과만 평가됩니다.

앞의 예제에서 첫 번째 식의 부수 효과는 변수의 값을 먼저 변경하는 것입니다.


for문

for문은 C++에서 세 번째이자 마지막 루프문이다.

for문은 정수 변수를 같은 증분으로 처리할 때 가장 일반적으로 사용된다. 

for문은 배열의 요소를 반복적으로 처리할 때 자주 사용된다.

 

첫 번째 식(Initialization_Action): 변수, 변수 또는 다른 것을 초기화하는 방법 확인

두 번째 식(Boolean_Expression): 루프가 언제 끝나야 하는지 확인하는 부울 식 확인

마지막 식(Update_Action): 루프 제어 변수가 루프 본체의 각 반복 후에 업데이트되는 방법 확인

 

for Statement Syntax
  for (Initialization_Action; Boolean_Expression; Update_Action )
      Body_Statement

 

EXAMPLE
  for (number = 100; number >= 0; number--)
      cout << number
               << " bottles of beer on the shelf.\n";

 

EQUIVALENT while LOOP SYNTAX
  Initialization_Action;
  while (Boolean_Expression)
  {
      Body_Statement
      Update_Action;
  }

 

EQUIVALENT EXAMPLE
  number = 100;
  while (number >= 0)
  {
      cout << number
               << " bottles of beer on the shelf.\n";
      number--;
  }

 

TIP: N번 반복 루프

for문은 루프 바디를 미리 결정된 횟수만큼 반복하는 루프를 생성하는 데 사용될 수 있습니다. 

예시)

for ( int count = 1; count <= 3; count++)
    cout << "Hip, Hip, Hurray\n";

 

함정: for문에서 추가 세미콜론

일반적으로 for 루프의 처음에 괄호 뒤에 세미콜론을 배치하지 않습니다.

예시)

for ( int count = 1; count <= 10; count++);
    cout << "Hello\n";

이 때 컴파일러는 Hello를 10번 출력하지도 않고 오류 메세지를 출력하지도 않는다.

for문에 아무런 문장이 없으므로 count가 10으로 증가되는 동안 for문은 아무것도 출력하지 않는다.

 

함정: 무한 루프

무한 루프(infinite loop): 부울 식을 항상 참이 되어 영원히 실행되는 루프

무한 루프의 예시

x = 1

while (x != 12)
{
    cout << x << endl;
    x = x + 2;
}


무한 루프에 있는 프로그램을 강제 종료를 시켜야 할 때 대부분의 시스템에서 Control + C를 누른다.

(시스템마다 강제 종료 버튼이 다른 경우가 있다.)

무한 루프가 있는 경우는 대부분 오류이나 의도적으로 무한 루프를 일으킬 때도 있다.

 

break문과 continue문

제어 흐름을 변경하는 두 가지 방법은 break 또는 continue 문을 삽입하는 것입니다.

break 문은 루프를 종료합니다.

continue 문은 루프 본체의 현재 반복을 종료합니다.

 

break 문: 키워드 break 뒤+ 세미콜론, 실행 시 break 문은 가장 가까운 둘러싸인 스위치 또는 루프 문을 종료

디스플레이 2.8 루프에서 break문 이용

#include <iostream>
using namespace std;

int main( )
{
	int number, sum = 0, count = 0;
	cout << "Enter 4 negative numbers:\n";
	
    while (++count <= 4)
	{
		cin >> number;
		
        if (number >= 0)
		{
        	cout << "ERROR: positive number"
				 << " or zero was entered as the\n"
				 << count << "th number! Input ends "
				 << "with the " << count << "th number.\n"
				 << count << "th number was not added in.\n";
			break;
		}
		
        sum = sum + number;
	}
	
    cout << sum << " is the sum of the first "
		 << (count - 1) << " numbers.\n";
	
    return 0;
}

 

샘플 대화

Enter 4 negative numbers:
-1 -2 -3 4
ERROR: positive number or zero was entered as the
4th number! Input ends
with the 4th number.
4th number was not added in
-6 is the sum of the first 3 numbers.

continue문: continue + 세미콜론. 실행 시 continue 문은 가장 가까운 둘러싸인 루프 문의 현재 루프 바디 반복을 종료

디스플레이 2.9 루프에서 continue문 사용

#include <iostream>
using namespace std;

int main( )
{
	int number, sum = 0, count = 0;
	cout << "Enter 4 negative numbers, ONE PER LINE:\n";
    
	while (count < 4)
	{
		cin >> number;
        
		if (number >= 0)
		{
			cout << "ERROR: positive number (or zero)!\n"
				 << "Reenter that number and continue:\n";
			continue;
		}
		sum = sum + number;
		count++;
	}
    
	cout << sum << " is the sum of the "
	     << count << " numbers.\n";
	return 0;
}

 

샘플 대화

Enter 4 negative numbers, ONE PER LINE:
1
ERROR: positive number (or zero)!
Reenter that number and continue:
-1
-2
3
ERROR: positive number!
Reenter that number and continue:
-3
-4
-10 is the sum of the 4 numbers.

 

중첩 루프

하나의 루프 문을 다른 루프 문 안에 중첩하는 것은 완벽하게 합법적입니다.

그렇게 할 때, 임의의 break문 또는 continue문은 break문 또는 continue 문을 포함하는 가장 안쪽의 루프(또는 switch) 문에 적용된다는 것을 기억하십시오.

다음과 같이 하는 것이 최선입니다.

내부 루프를 함수 정의 내부에 배치하고 외부 루프 내부에 함수 호출을 배치함으로써 중첩 루프를 방지합니다. 

 

2.4 파일 입력 소개

입력 스트림(input stream): 데이터를 프로그램으로 읽을 수 있게 해주는 중요한 개념

 

ifstream 를 사용하여 텍스트 파일에서 읽기

텍스트 파일에서 읽으려면 fstream 라이브러리를 포함하고 std 네임스페이스에 있는 ifstream 개체를 만들어야 한다.

#include <fstream>
using namespace std;

 

변수를 선언하면 다음과 같다.

ifstream inputStream;

 

텍스트파일을 열 때

inputStream.open("filename.txt");

 

프로그램은 >>으로 변수의 입력을 받는다.

inputStream >> intVar

 

디스플레이 2.10 플레이어의 고득점 및 이름을 저장하기 위한 샘플 텍스트 파일, player.txt

100510
Gordon Freeman

 

디스플레이 2.11 디스플레이 2.10의 텍스트 파일 읽기 프로그램

#include <iostream>
#include <fstream>
#include <string>

using namespace std;
int main( )
{
	string firstName, lastName;
	int score;
	fstream inputStream;
	
    inputStream.open("player.txt");
	
    inputStream >> score;	
    inputStream >> firstName >> lastName;
	
    cout << "Name: " << firstName << " "
		 << lastName << endl;
	cout << "Score: " << score << endl;
	inputStream.close();
	
    return 0;
}

샘플 대화

Name: Gordon Freeman
Score: 100510

 

디스플레이 2.12 

#include <iostream>
#include <fstream>
#include <string>

using namespace std;
int main( )
{
	string text;
	fstream inputStream;

	inputStream.open("player.txt");

	while (inputStream >> text)
	{
		cout << text << endl;
	}
    inputStream.close();
	
    return 0;
}

샘플 대화

100510
Gordon
Freeman

 

'프로그래밍 공부 > OOP' 카테고리의 다른 글

5장 배열  (0) 2023.11.21
4장 매개변수와 오버로딩  (0) 2023.11.05
3장 함수 기초  (1) 2023.11.04
1장 C++ 기초  (1) 2023.10.30
OOP 공부 시작  (0) 2023.10.28