[이것이 C#이다] 5. 흐름 제어(Flow Control)

ssu_hyun·2022년 4월 10일
0

C#

목록 보기
9/22

Key point

  • 흐름 제어의 역할
  • 분기문
  • 반복문
  • 점프문

5.0 흐름 제어(Flow of Control)

코드 실행 순서를 결정하는 것

5.1 분기문(Branching Statement)

  • 제어 흐름을 여러 갈래로 나누는 코드
  • 단, 프로그램은 한 번에 하나의 갈래만 실행할 수 있음

5.1.1 if문

  • 조건을 만족하는 경우에만 분기 수행
  • else if절과 else절은 옵션
  • 조건식 : bool형식 (true or false)
if (조건식)
	참인_경우에_실행할_코드;

// 실행할 코드가 여러 줄인 경우 : {} 사용
if (조건식)
{
	참인
    경우에
    실행할
    코드;
}

// 옵션 : else, else if
int a = -10;

if (a < 0)
	Console.WriteLine("음수");
else if (a > 0)
	Console.WriteLine("양수");
else
	Console.WriteLine("0");
// IfElse //

using System;

namespace IfElse
{
    class MainApp
    {
        static void Main(string[] args)
        {
            Console.Write("숫자를 입력하세요. : ");

            string input = Console.ReadLine(); // 사용자로부터 문자열 입력받아 결과 반환하는 코드
            int number = Int32.Parse(input);

            if (number < 0)
                Console.WriteLine("음수");
            else if (number > 0)
                Console.WriteLine("양수");
            else
                Console.WriteLine("0");

            if (number % 2 == 0)
                Console.WriteLine("짝수");
            else
                Console.WriteLine("홀수");
        }
    }
}

  • 중첩 사용 가능
// IfIf //

using System;

namespace IfIf
{
    class MainApp
    {
        static void Main(string[] args)
        {
            Console.Write("숫자를 입력하세요. : ");

            string input = Console.ReadLine();
            int number = Convert.ToInt32(input);

            if (number > 0)
            {
                if (number % 2 == 0)
                    Console.WriteLine("0보다 큰 짝수.");
                else
                    Console.WriteLine("0보다 큰 홀수.");
            }
            else
            {
                Console.WriteLine("0보다 작거나 같은 수.");
            }
        }
    }
}

  • 코드의 흐름은 가급적 단순하고 명료하게 유지하는 것이 좋다.

5.1.2 switch

switch문

  • 입력식/값이 어떤 사례(case)와 매치되는지를 평가하여 분기 수행
  • 분기 수행 후엔 break문을 이용해 switch문 탈출
  • 조건식 : 정수 형식, 문자열 형식
// Format //
switch (조건식)
{
	case 상수1;
    	// 실행할 코드
        break;
    case 상수2;
    	// 실행할 코드
        break;
    case 상수N;
    	// 실행할 코드
        break;
    default:  // 조건식이 어떤 경우와도 맞지 않은 경우, 생략 가능
    	// 실행할 코드
        break;
}



// Switch - 정수, 문자열 //

using System;

namespace Switch
{
    class MainApp
    {
        static void Main(string[] args)
        {
            Console.Write("요일을 입력하세요.(일,월,화,수,목,금,토) : ");
            string day = Console.ReadLine();

            switch (day)
            {
                case "일":
                    Console.WriteLine("Sunday");
                    break;
                case "월":
                    Console.WriteLine("Monday");
                    break;
                case "화":
                    Console.WriteLine("Tuesday");
                    break;
                case "수":
                    Console.WriteLine("Wednesday");
                    break;
                case "목":
                    Console.WriteLine("Thursday");
                    break;
                case "금":
                    Console.WriteLine("Friday");
                    break;
                case "토":
                    Console.WriteLine("Saturday");
                    break;
                default:
                    Console.WriteLine($"{day}는(은) 요일이 아닙니다.");
                    break;
            }
        }
    }
}

  • C#7.0부터는 switch문에 데이터 형식을 조건으로 사용할 수 있게 되었다.
    • case절의 경우 반드시 데이터 형식 옆에 식별자를 붙여줘야 한다.
// Switch - 데이터 형식 //

object obj = 123;  // C#컴파일러는 123 리터럴을 평가하여 int 형식임을 유추한 후 obj 안에 박싱

switch(obj)
{
	case int i: // obj에 담겨 있는 데이터의 형식이 int이므로 이 프로그램은 이 case절을 따라 분기
    	...
        break;
    case float f:
    	...
        break;
    default:
    	...
        break;
}   



// Switch2 //

using System;

namespace Switch2
{
    class MainApp
    {
        static void Main(string[] args)
        {
            object obj = null;
			
            // 입력받기
            string s = Console.ReadLine(); 
            // int로 변환 성공할 경우
            if (int.TryParse(s, out int out_i)) // 반환 성공값은 두번째 매개변수
                obj = out_i;
            // float으로 변환 성공할 경우
            else if (float.TryParse(s, out float out_f)) // 반환 성공값은 두번째 매개변수
                obj = out_f;
            else
                obj = s;

            switch (obj)
            {
                case int i:
                    Console.WriteLine($"{i}는 int 형식입니다.");
                    break;
                case float f:
                    Console.WriteLine($"{f}는 float 형식입니다.");
                    break;
                default:
                    Console.Write($"{obj}(은)는 모르는 형식입니다.");
                    break;
            }
        }
    }
}

TryParse() vs Parse()

  • Parse() : 변환이 실패할 경우 예외를 던져 프로그램의 실행을 멈추게 함
  • TryParse() : 변환의 성공 여부를 반환하여 코드 흐름을 유지할 수 있고 변환한 데이터는 두 번째 매개변수에 저장된다.
  • out 키워드 : 출력 전용 매개변수 표시
  • 데이터 형식에 따라 분기하는 경우 switch 문의 when절을 이용해 추가적인 조건 검사를 수행할 수 있다.
switch (obj)
{
     case int i:
        Console.WriteLine($"{i}는 int 형식입니다.");
        break;
     case float f f when f >= 0: // obj가 float 형식이며 0보다 크거나 같은 경우
        Console.WriteLine($"{f}는 float 형식입니다.");
        break;
     case float f: // obj가 float 형식이며 0보다 작은 경우
        Console.WriteLine($"{f}는 float 형식입니다.");
        break;
     default:
        Console.Write($"{obj}(은)는 모르는 형식입니다.");
        break;

swith식

어떤 작업에 분기가 필요할 때는 switch문을 사용하되, 분기를 거쳐 값을 내야 하는 경우에는 switch식을 사용하면 보다 읽기 좋은 코드를 작성할 수 있다.

식(Expression) vs 문(Statement)

  • 식(Expression) : 어떤 계산을 해서 결과를 내놓음
  • 문(Statement) : 어떤 일을 함
// Switch문 // 

int input = Convert.ToInt32(Console.ReadLine());

// 1의 자리를 버림. 예) 92 → 90, 87 → 80
int score = (int)(Math.Truncate(input/10.0) * 10);
string grade = "";

switch(score)
{
	case 90:
    	grade = "A";
        break;
    case 80:
    	grade = "B";
        break;
    case 70:
    	grade = "C";
        break;
    case 60:
    	grade = "D";
        break;
   default:
    	grade = "F";
}



// Switch식 //

int input = Convert.ToInt32(Console.ReadLine());

// 1의 자리를 버림. 예) 92 → 90, 87 → 80
int score = (int)(Math.Truncate(input/10.0) * 10);

string grade = score switch;  // 1. 조건식 switch
{
	90 => "A", // 2. 각 케이스는 콤마로 구분
    80 => "B",
    70 => "C",
    60 => "D",
    _ => "F" // 3. default
};


// Switch식 + when절 //

bool repeated = true;

string grade = score switch
{
	90 when repeated == true => "B+", // score가 90이어도 repeated가 true면 "B+"
    90 => "A", 
    80 => "B",
    70 => "C",
    60 => "D",
    _ => "F" 
};



// SwitchExp //

using System;

namespace SwitchExp
{
    class MainApp
    {
        static void Main(string[] args)
        {
            Console.WriteLine("점수를 입력하세요");
            int score = Convert.ToInt32(Console.ReadLine());

            Console.WriteLine("재수강인가요? (y/n)");
            string line = Console.ReadLine();
            bool repeated = line == "y"?true:false;
            
            string grade = (int)(Math.Truncate(score/10.0) * 10) switch
            {
                90 when repeated == true => "B+",
                90 => "A",
                80 => "B",
                70 => "C",
                60 => "D",
                _ => "F"
            };

            Console.WriteLine($"학점 : {grade}");
        }
    }
}


5.2 반복문 (Loop Statement)

특정 구간의 제어 흐름을 반복 실행

5.2.1 while

  • 조건을 만족하는 동안 반복 수행
  • 조건식 : 논리 형식 (bool)
// Format //

while (조건식)
	반복실행할_코드
   
   
// 여러 문장의 코드를 반복 실행할 경우

while (조건식)
{
	반복실행할_코드_블록
}


// While //

using System;

namespace While
{
    class MainApp
    {
        static void Main(string[] args)
        {
            int i = 10;

            while (i > 0)
            {
                Console.WriteLine($"i : {i--}");
            }
        }
    }
}

5.2.2 do while

일단 코드 실행 후, 조건을 평가하여 반복 수행

do
{
	반복실행할_코드_블록 // 최초 한번은 무조건 실행되는 코드 블록
}
while (조건식); // 세미콜론(;) 반드시 붙여줘야 함


// DoWhile //

using System;

namespace While
{
    class MainApp
    {
        static void Main(string[] args)
        {
            int i = 10;

            do
            {
                Console.WriteLine($"a) i : {i--}");
            }
            while (i > 0);

            do
            {
                Console.WriteLine($"b) i : {i--}");
                /* 여기에서 i는 이미 0이지만 do while문은 조건식을 평가하기 전에
                반드시 한 번은 반복 코드를 실행하게 되어 있으므로 이 코드는 한 차례 실행됨 */
            }
            while (i > 0);
        }
    }
}

5.2.3 for

  • 조건을 만족하는 동안 반복 수행
  • for(조건변수 초기화; 조건비교; 조건변수 증/감)
// Format //
for ( 초기화식; 조건식; 반복식; )
	반복실행할_코드;
  • 임의의 횟수만큼 반복을 수행할 경우 while문보다 for문이 더 편리하다.
// For //

using System;

namespace For
{
    class MainApp
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine(i);
            }
        }
    }
}

  • 중첩 사용 가능
// ForFor //

using System;

namespace ForFor
{
    class MainApp
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j <= i; j++)
                {
                    Console.Write("*");
                }
                Console.WriteLine("");
            }
        }
    }
}

5.2.4 foreach

  • 배열(또는 컬렉션)을 순회하며 각 데이터 요소에 차례대로 접근
// Format //

foreach (데이터형식 변수명 in 배열_또는_컬렉션)
	코드_또는_코드블록
    

// ForEach //

using System;

namespace ForEach
{
    class MainApp
    {
        static void Main(string[] args)
        {
            int[] arr = new int[]{0, 1, 2, 3, 4}; // 배열 선언

            foreach (int a in arr)
            {
                Console.WriteLine(a);
            }
        }
    }
}

5.2.5 무한 반복 코드

// InfiniteFor //

using System;

namespace InfiniteFor
{
    class MainApp
    {
        static void Main(string[] args)
        {
            int i=0;
            for ( ; ; ) // for 무한 반복 코드
                Console.WriteLine(i++);
        }
    }
}


// InfiniteWhile //

using System;

namespace InfiniteWhile
{
    class MainApp
    {
        static void Main(string[] args)
        {
            int i = 0;
            while (true) // while 무한 반복 코드
                Console.WriteLine(i++);
        }
    }
}

5.3 점프문(Jump Statement)

  • 흐름을 특정 위치로 단번에 이동

5.3.1 break

반복문이나 switch문의 실행을 중단하고 탈출

using System;

namespace Break
{
    class MainApp
    {
        static void Main(string[] args)
        {
            while (true)
            {
                Console.Write("계속할까요?(예/아니오) : ");
                string answer = Console.ReadLine();

                if (answer == "아니오")
                    break; // 입력받은 값이 아니오일 경우 if문 탈출
            }
        }
    }
}

5.3.2 continue

반복을 건너뛰어 반복을 계속 수행

using System;

namespace Continue
{
    class MainApp
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 10; i++)
            {
                if (i % 2 == 0)
                    continue; // 짝수일 경우 건너뛰기

                Console.WriteLine($"{i} : 홀수");
            }
        }
    }
}

5.3.3 goto

지정한 레이블로 제어를 이동

using System;

namespace Goto
{
    class MainApp
    {
        static void Main(string[] args)
        {
            Console.Write("종료 조건(숫자)을 입력하세요 :");

            String input = Console.ReadLine();

            int input_number = Convert.ToInt32(input);
            
            int exit_number = 0;

            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        if (exit_number++ == input_number)
                            goto EXIT_FOR;

                        Console.WriteLine(exit_number);
                    }
                }
            }

            goto EXIT_PROGRAM;

        EXIT_FOR:
            Console.WriteLine("\nExit nested for...");

        EXIT_PROGRAM:
            Console.WriteLine("Exit program...");
        }
    }
}

5.3.3 return, throw

6장, 13장에서 설명


연습 문제

  1. 다음과 같은 결과를 출력하는 프로그램을 for문을 이용하여 작성하세요. 규칙은 첫 번째 줄에 별 하나, 두 번째 줄에 별 둘, 세 번째 줄에 별 셋... 이런 식으로 5개의 별이 찍힐 때까지 반복합니다. (힌트 : for문 블록 안에 for문 블록을 넣으세요.)
*
**
***
****
*****

// answer //

using System;

namespace For
{
	class MainApp
    {
    	static void Main(string[] args)
        {
        	for ( int i=0; i<5; i++)
            {
            	for (int j=0; j<= i; j++)
                {
                	Console.Write("*");
                }
                Console.WriteLine();
            }
        }
    }
}

  1. 다음과 같은 결과를 출력하는 프로그램을 for문을 이용하여 작성하세요.
*****
****
***
**
*

// answer //

using System;

namespace For
{
    class MainApp
    {
        static void Main(string[] args)
        {
            for (int i = 4; i >= 0; i--)
            {
                for (int j = 0; j <= i; j++)
                {   
                    Console.Write("*");
                }
                Console.WriteLine();
            }
        }
    }
}


3. 1번과 2번을 for문 대신 while문과 do 문으로 바꿔서 각각 작성하세요.

// 1번 - while문

using System;

namespace While
{
	class MainApp
    {
    	static void Main(string[] args)
        {
        	int i = 0;
        	while ( i<5 )
            {	
            	int j = 0;
            	while (j <= i)
                {
                	Console.Write("*");
                    j += 1;
                }
                Console.WriteLine();
                i += 1;
            }
        }
    }
}

// 1번 - do while문

using System;

namespace DoWhile
{
	class MainApp
    {
    	static void Main(string[] args)
        {
        	int i = 0;
            
            do 
            {
            	int j = 0;
                do
                {
                	Console.Write("*");
                    j += 1;
                }
                while (j <= i);
                
                Console.WriteLine();
                i += 1;
            }
         	while (i < 5);
            
        }
    }
}

// 2번 - while문

using System;

namespace While2
{
	class MainApp
    {
    	static void Main(string[] args)
        {
        	int i = 4;
        	while ( i>=0 )
            {	
            	int j = 0;
            	while (j <= i)
                {
                	Console.Write("*");
                    j += 1;
                }
                Console.WriteLine();
                i -= 1;
            }
        }
    }
}

// 2번 - do while문

using System;

namespace DoWhile2
{
	class MainApp
    {
    	static void Main(string[] args)
        {
        	int i = 4;
            
            do 
            {
            	int j = 0;
                do
                {
                	Console.Write("*");
                    j += 1;
                }
                while (j <= i);
                
                Console.WriteLine();
                i -= 1;
            }
         	while (i >= 0);
            
        }
    }
}

  1. 다음과 같이 사용자로부터 입력받은 횟수만큼 별을 반복 출력하는 프로그램을 작성하세요. 단, 입력받은 수가 0보다 작거나 같을 경우 "0보다 같거나 작은 숫자는 사용할 수 없습니다."라는 메시지를 띄우고 프로그램을 종료합니다.
반복 횟수를 입력하세요 : -10
0보다 작거나 같은 수는 입력할 수 없습니다.

반복 횟수를 입력하세요 : 5

*
**
***
****
*****
using System;

namespace Star
{
    class MainApp
    {
        static void Main(string[] args)
        {
            Console.Write("반복 횟수를 입력하세요 : ");
            String input = Console.ReadLine();
            int i = Convert.ToInt32(input);

            if (i <= 0)
            {
                Console.WriteLine("0보다 같거나 작은 숫자는 사용할 수 없습니다.");
                goto EXIT;
            }


            for (i = 0; i < 5; i++)
            {
                for (int j = 0; j <= i; j++)
                {
                    Console.Write("*");
                }
                Console.WriteLine();
            }
            EXIT:
                Console.WriteLine();
        }
    }
}

0개의 댓글