04. 제어문
프로그램의 흐름을 분기·반복으로 제어합니다. if·else·switch 분기와 for·while·do-while·foreach 반복, 그리고 break·continue 를 익힙니다.
이 강의에서 배우는 것
- 1`if` / `else if` / `else` 로 조건 분기를 한다
- 2`switch` 문과 **`switch` 표현식**(`=>`)의 차이를 안다
- 3`for` / `while` / `do-while` / `foreach` 의 쓰임을 구분한다
- 4`break` 와 `continue` 로 반복을 제어한다
소개
프로그램의 흐름은 위에서 아래로 흐르되, **조건**으로 분기하고 **반복**으로 되풀이합니다. C# 8 이후 추가된 `switch` 표현식은 함수형 스타일의 깔끔한 패턴 매칭을 제공합니다.
핵심 개념
1) `if` / `else if` / `else`
int score = 85;
if (score >= 90) Console.WriteLine("A");
else if (score >= 80) Console.WriteLine("B");
else if (score >= 70) Console.WriteLine("C");
else Console.WriteLine("F");조건이 위에서부터 차례로 평가되어, **처음 참인 가지** 하나만 실행됩니다.
2) `switch` 문 vs `switch` 표현식
**문(statement)** 형:
switch (day)
{
case 1: Console.WriteLine("월"); break;
case 2: Console.WriteLine("화"); break;
default: Console.WriteLine("?"); break;
}**표현식(expression)** 형 — C# 8+:
string name = day switch
{
1 => "월",
2 => "화",
_ => "?" // default 역할
};표현식형은 **값을 반환**하므로 변수에 바로 대입할 수 있고, `break` 가 필요 없습니다. `_` 는 "어떤 값과도 매칭" 되는 와일드카드입니다.
3) `for` / `while` / `do-while`
- `for` : 횟수가 정해진 반복
- `while` : 조건이 참인 동안 반복 (0회 가능)
- `do-while` : 일단 한 번 실행 후 조건 검사 (최소 1회)
for (int i = 0; i < 3; i++) Console.WriteLine(i); // 0 1 2
int n = 3;
while (n > 0) { Console.WriteLine(n); n--; } // 3 2 1
int m = 0;
do { Console.WriteLine("once"); } while (m > 0); // 한 번만4) `foreach`
배열·리스트 등 **`IEnumerable`** 을 순회합니다. 인덱스가 필요 없는 단순 순회에 적합.
int[] nums = [10, 20, 30];
foreach (int x in nums)
Console.WriteLine(x);5) `break` / `continue`
- `break` : 현재 반복문을 **즉시 종료**
- `continue` : 현재 반복을 건너뛰고 **다음 반복으로**
for (int i = 1; i <= 10; i++)
{
if (i == 5) break; // i==5 에서 탈출
if (i % 2 == 0) continue;// 짝수는 건너뜀
Console.WriteLine(i); // 1, 3 출력
}핵심 예제
예제 1 — `IfElse/Program.cs` : 성적 등급 판별
Console.Write("점수: ");
int score = int.Parse(Console.ReadLine()!);
string grade;
if (score >= 90) grade = "A";
else if (score >= 80) grade = "B";
else if (score >= 70) grade = "C";
else if (score >= 60) grade = "D";
else grade = "F";
Console.WriteLine($"등급: {grade}");**실행 결과**
점수: 85
등급: B**메모:** 위에서 아래로 평가되니, **좁은 조건부터** 또는 **큰 값부터** 정렬해야 의도대로 동작합니다.
예제 2 — `SwitchExpression/Program.cs` : 요일을 한글로
Console.Write("요일 번호 (1~7): ");
int day = int.Parse(Console.ReadLine()!);
string name = day switch
{
1 => "월요일",
2 => "화요일",
3 => "수요일",
4 => "목요일",
5 => "금요일",
6 => "토요일",
7 => "일요일",
_ => "잘못된 입력"
};
Console.WriteLine(name);**실행 결과**
요일 번호 (1~7): 3
수요일**메모:** `switch` 표현식은 모든 경우를 다루지 않으면 경고가 납니다. `_` 로 기본값을 꼭 둡시다.
예제 3 — `ForWhile/Program.cs` : `for` 합계, `while` 카운트다운
// 1부터 10까지의 합
int sum = 0;
for (int i = 1; i <= 10; i++)
sum += i;
Console.WriteLine($"1~10 합 = {sum}");
// 5부터 1까지 카운트다운
int n = 5;
while (n > 0)
{
Console.Write($"{n} ");
n--;
}
Console.WriteLine("발사!");**실행 결과**
1~10 합 = 55
5 4 3 2 1 발사!**메모:** 누적 변수는 **루프 밖**에서 초기화해야 결과가 유지됩니다.
예제 4 — `Foreach/Program.cs` : 배열 합계
int[] scores = [78, 92, 64, 85, 100];
int total = 0;
foreach (int s in scores)
total += s;
double avg = (double)total / scores.Length;
Console.WriteLine($"총점: {total}, 평균: {avg:F2}");**실행 결과**
총점: 419, 평균: 83.80**메모:** 배열의 자세한 사용법은 11편에서 다룹니다. 여기서는 "묶음을 순회한다" 정도면 충분합니다.
전체 예제 코드 (src/)
src/ForWhile/ForWhile.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>CodingNow.Lecture.Basics04</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
src/ForWhile/Program.cs
// for 로 합계, while 로 카운트다운
int sum = 0;
for (int i = 1; i <= 10; i++)
sum += i;
Console.WriteLine($"1~10 합 = {sum}");
int n = 5;
while (n > 0)
{
Console.Write($"{n} ");
n--;
}
Console.WriteLine("발사!");
src/Foreach/Foreach.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>CodingNow.Lecture.Basics04</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
src/Foreach/Program.cs
// 배열을 foreach 로 순회해 합계·평균
int[] scores = [78, 92, 64, 85, 100];
int total = 0;
foreach (int s in scores)
total += s;
double avg = (double)total / scores.Length;
Console.WriteLine($"총점: {total}, 평균: {avg:F2}");
src/IfElse/IfElse.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>CodingNow.Lecture.Basics04</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
src/IfElse/Program.cs
// 성적 등급 판별
Console.Write("점수: ");
int score = int.Parse(Console.ReadLine()!);
string grade;
if (score >= 90) grade = "A";
else if (score >= 80) grade = "B";
else if (score >= 70) grade = "C";
else if (score >= 60) grade = "D";
else grade = "F";
Console.WriteLine($"등급: {grade}");
src/SwitchExpression/Program.cs
// switch 표현식 - 요일 번호를 한글로
Console.Write("요일 번호 (1~7): ");
int day = int.Parse(Console.ReadLine()!);
string name = day switch
{
1 => "월요일",
2 => "화요일",
3 => "수요일",
4 => "목요일",
5 => "금요일",
6 => "토요일",
7 => "일요일",
_ => "잘못된 입력"
};
Console.WriteLine(name);
src/SwitchExpression/SwitchExpression.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>CodingNow.Lecture.Basics04</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
자주 하는 실수
- `for (int i = 0; i <= n; i++)` 처럼 `<=` 와 `<` 헷갈리기 — **off-by-one** 버그.
- `switch` 문에서 `break` 누락 — 표현식형엔 없지만 문형은 필수.
- 무한 루프 — `while (true)` 안에 `break` 조건 빠짐.
- `foreach` 중 컬렉션 수정 — 예외 발생. 수정하려면 `for` 사용.
- `if (a == 0 || 1)` 같이 잘못 쓰기 — `if (a == 0 || a == 1)` 이 맞다.
정리
- 분기: `if`/`else` 와 `switch`(표현식형 권장)
- 반복: 횟수 — `for`, 조건 — `while`, 최소 1회 — `do-while`, 컬렉션 — `foreach`
- `break` 로 탈출, `continue` 로 건너뛰기
- `switch` 표현식 + `_` 패턴이 현대 C# 의 권장 스타일
과제
**과제 - 04. 제어문**
문제 1 — 1부터 N까지의 합
- 프로젝트 폴더: `Homework01/`
- 핵심 개념: `for` 반복, 누적 합
요구사항
- 정수 `N` 을 입력받는다
- `1 + 2 + ... + N` 을 계산해 출력한다
- `N` 이 0 이하면 "0 이하 입력은 처리할 수 없습니다." 를 출력하고 종료
예상 출력
N: 10
1 ~ 10 의 합 = 55힌트
- `for (int i = 1; i <= n; i++) sum += i;`
- 입력 검증을 먼저 한 뒤 `return;` 으로 일찍 종료할 수 있다 (top-level statements 에서도 가능)
문제 2 — FizzBuzz (1~30)
- 프로젝트 폴더: `Homework02/`
- 핵심 개념: `for`, `%`, `if`/`switch` 표현식
요구사항
- 1부터 30까지 출력하되,
- 3의 배수이면 `Fizz`
- 5의 배수이면 `Buzz`
- 둘 다이면 `FizzBuzz`
- 그 외는 숫자 그대로
예상 출력
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
... (30까지)힌트
- `i % 15 == 0` 을 먼저 확인하거나, `switch` 표현식에서 패턴으로 처리
- `switch` 표현식 + when 절을 쓰면 한 식으로 깔끔하게 표현 가능:
```csharp string line = i switch { _ when i % 15 == 0 => "FizzBuzz", _ when i % 3 == 0 => "Fizz", _ when i % 5 == 0 => "Buzz", _ => i.ToString() }; ```
정답 확인
직접 풀어 본 후 [`answer/`](./answer/) 폴더의 정답과 비교해 보세요.
정답 (answer/)
homework/answer/Homework01/Homework01.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>CodingNow.Lecture.Basics04</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
homework/answer/Homework01/Program.cs
// 1부터 N까지의 합
Console.Write("N: ");
int n = int.Parse(Console.ReadLine()!);
if (n <= 0)
{
Console.WriteLine("0 이하 입력은 처리할 수 없습니다.");
return;
}
int sum = 0;
for (int i = 1; i <= n; i++)
sum += i;
Console.WriteLine($"1 ~ {n} 의 합 = {sum}");
homework/answer/Homework02/Homework02.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>CodingNow.Lecture.Basics04</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
homework/answer/Homework02/Program.cs
// FizzBuzz 1 ~ 30
for (int i = 1; i <= 30; i++)
{
string line = i switch
{
_ when i % 15 == 0 => "FizzBuzz",
_ when i % 3 == 0 => "Fizz",
_ when i % 5 == 0 => "Buzz",
_ => i.ToString()
};
Console.WriteLine(line);
}
직접 해 보기
cd src/IfElse && dotnet run
cd ../SwitchExpression && dotnet run
cd ../ForWhile && dotnet run
cd ../Foreach && dotnet run다음 단원
[05_메서드](../05_메서드/) — 코드를 메서드로 묶어 재사용합니다.