본문 바로가기
모던 C

레벨 1 친숙 - 03 결국은 제어

by 왕초보 독학 코딩 2024. 2. 3.

이 포스트는 '모던 C'를 요약한 내용입니다.

 

이 장에서 다루는 내용

  • if를 이용한 조건부 실행
  • 도메인에 대해 반복하기
  • 다중 선택하기

C 언어는 if, for, do, while, switch라는 다섯 가지 조건부 제어문(conditional control statement)을 제공하며, 이 장에서 이들에 대해 하나씩 살펴볼 것이다. if는 불리언 표현식의 값을 기준으로 조건부 실행(conditional execution) 기능을 제공한다. for, do, while은 반복문(iteration)이고, switch는 정수 값을 기준으로 다중 선택(multiple selection) 기능을 제공한다.

 

3.1 조건부 실행

첫 번째 살펴볼 구문은 if라는 키워드로 표현한 것으로 다음과 같이 작성한다.

if (i > 25) {
    j = i - 25;
}

이 코드에서 i > 25는 제어 표현식(controlling expression)이라 하고, 뒤이어 나오는 블록 { ... }을 의존 블록(dependent block)이라 한다.

 

다음 코드는 if 제어 조건을 만족하지 못할 때 실행되는 의존 블록을 추가한 것이다. 코드를 구분하기 위해 else라는 키워드를 따로 제공한다.

if (i > 25) {
    j = i - 25;
} else {
    j = i;
}

 

C 언어는 0을 논리값의 거짓(false)을 의미한다. 반면, 0이 아닌 모든 값을 논리값 참(true)을 의미한다. 

 

==와 != 연산자로 두 값이 같은지 혹은 다른지 비교할 수 있다. a == b이란 표현식에서 a 값과 b 값이 같으면 이 식은 참이 되고, 나머지 경우는 거짓이 된다. 또한 a와 b가 같으면 a != b는 거짓이 되고, 나머지 경우는 참이 된다. 

 

조건으로 숫자값을 지정했을 때 평가되는 방식을 잘 알고 있으면 중복된 표현을 피할 수 있다. 예를 들어 다음 문장을 보자.

if (i != 0) {
    ...
}

이 문장은 다음과 같이 간결하게 표현할 수 있다.

if (i) {
    ...
}

 

사실 둘 중 어느 것이 읽기 쉬운지는 코딩 스타일(coding style)의 문제라서 소모적인 논쟁에 빠지기 쉽다. C 코드를 가끔 읽는 이들은 첫 번째 방식이 쉽게 느껴질 것이고, C 스타일 시스템에 익숙한 이들은 두 번째 스타일을 선호할 것이다.

 

bool 타입은 stdbool.h 파일에 정의돼 있다. bool 타입이 가질 수 있는 값은 false나 true다. 내부적으로 false는 0과 같고, true는 1이다. 조건을 표현할 때는 숫자보다는 false나 true로 표현하는 것이 좋다. 

 

일반적으로 다음 규칙을 따른다.

  • 0, false, true끼리 비교하는 표현은 쓰지 않는다. 
  • 스칼라값은 모두 진리값이 될 수 있다.

 

3.2 반복문

지금까지는 for문으로 어떤 도메인을 반복했다. 기본 형태는 다음과 같다.

for (절1; 조건2; 표현식3) 문장 또는 블록

 

절1 자리에 대입 표현식이나 변수 정의를 적는다. 즉, 반복 도메인의 초깃값을 지정하는 역할을 한다. 조건2는 반복을 계속할지 검사한다. 표현식3은 절1에 나왔던 반복 변수의 값을 업데이트하는데, 반복이 끝날 때마다 실행된다. 

 

for문의 다양한 예제를 살펴보자.

for (size_t i = 10; i; --1) {
    something(i);
}

for (size_t i = 10; i; --1) something(i);

for (size_t i = 9, stop = upper_bound(); i < stop; ++i) something(i);

 

C 언어는 while과 do라는 반복문도 제공한다. 이 반복문은 지정한 조건이 참이면 반복한다. do 루프도 거의 비슷하지만 의존 블록을 실행하고 나서 조건을 검사한다는 점이 다르다. 다시 말해 while 루프는 조건이 처음부터 거짓이면 의존 블록이 실행되지 않지만, do 루프는 의존 블록이 최소한 한 번은 실행된다.

while (조건) 문장 또는 블록

do 문장 또는 블록 while(조건)
while (fabs(1.0 - a*x) >= eps) {
    x += (2.0 - a*x);
}

do {
    x += (2.0 - a*x);
} while (fabs(1.0 - a*x) >= eps);

 

지금까지 살펴본 반복문에 break와 continue문을 사용해서 훨씬 다양하게 제어할 수 있다. break문은 실행 중이던 반복문을 종료한다.

while (true) {
    double prod = a*x;
    if (fabs(1.0 - prob) < eps) {
        break;
    }
    x *= (2.0 - prod);
}

이를 for문으로도 작성할 수 있는데, C 프로그래머들은 관용적으로 다음과 같이 쓴다.

for (;;) {
    double prod = a*x;
    if (fabs(1.0 - prob) < eps) {
        break;
    }
    x *= (2.0 - prod);
}

for (;;)는 while (true)와 같다. for의 제어 조건문(;;에서 가운데 부분)을 생략하면 항상 참으로 처리되기 때문이다.

 

continue문은 현재 반복 회차를 마저 실행하지 않고 다음 회차로 넘어간다. 이후 조건을 검사한 다음 참이 나오면 의존 블록을 실행하게 된다.

 

3.3 다중 선택

마지막으로 소개할 제어문은 switch문으로서 선택문(selection statement)의 한 종류다. switch는 if-else문이 너무 길어서 코드가 복잡해질 때 주로 사용한다.

switch는 if-else문이 너무 길어서 코드가 복잡해질 때 주로 사용한다.

if (arg == 'm') {
    puts("this is a magpie");
} else if (arg == 'r') {
    puts("this is a raven");
} else if (arg == 'c') {
    puts("this is a jay");
} else {
    puts("this is an unknown corvid");
}

 

switch문을 사용하면 위의 코드를 다음과 같이 좀 더 간결하게 표현할 수 있다.

switch (arg) {
    case 'm': puts("this is a magpie");
              break;
    case 'r': puts("this is a raven");
              break;
    case 'c': puts("this is a jay");
              break;
    default: puts("this is an unknown corvid");
}

 

puts 함수는 stdio.h에 정의되어 있고, 이 함수는 인수로 전달한 문자열을 화면에 출력한다. default는 표현식의 값(위의 코드에서는 arg)과 일치하는 case가 없을 때 선택된다.

 

switch문은 상당히 직관적이다. case와 defaults 레이블은 점프 타깃(jump target) 역할을 한다. 표현식의 값과 일치하는 레이블의 문장으로 실행한다. break문을 만나면 그 문장이 속한 switch문이 종료되고, switch 다음 문장으로 넘어간다. 

 

이러한 점 때문에 다음과 같은 코드도 작성할 수 있다.

switch (count) {
    default: puts("-----");
    case 4: puts("++++");
    case 3: puts("+++");
    case 2: puts("++");
    case 1: puts("+");
    case 0:;
}

 

 

일단 switch문의 블록 안으로 들어가고 나면 break를 만나거나 블록이 끝날 때까지 계속 실행된다. 이 코드에는 break문이 하나도 없기 때문에 점프한 문장부터 나머지 문장이 모두 실행된다. 가령 count 값이 3이라면 다음과 같이 세줄에 걸쳐진 삼각형 모양이 출력된다.

+++
++
+

 

 

switch는 if-else보다 구조가 좀 더 유연하지만 case 값은 반드시 정수 타입의 상수 표현식으로 지정해야 한다는 제약 사항이 있다. 

 

3.4 요약

  • if문의 조건을 숫값으로 지정해도 된다. 0은 false로, 나머지 숫자는 true로 처리한다.
  • 반복문은 for, do, while가 있다. 특정한 도메인에 대해 반복할 때는 for를 가장 많이 쓴다.
  • switch문은 다중 선택을 표현할 수 있다. case 안의 문장에 break가 없으면 이어지는 case을 연달아 실행한다.

 

'모던 C' 카테고리의 다른 글

레벨 1 친숙 - 04 계산 표현하기  (0) 2024.02.23
레벨1 친숙 - 들어가며  (0) 2024.02.03
레벨0 만남 - 02 프로그램의 핵심 구조  (0) 2024.02.03
레벨0 만남 - 01 들어가며  (0) 2024.02.02
들어가며  (0) 2024.02.02