지금까지 짠 프로그램은 위에서 아래로 한 줄씩, 늘 같은 길만 걸었습니다. 하지만 쓸모 있는 프로그램은 상황을 보고 길을 갈라야 합니다. 나이가 열아홉을 넘었으면 이 안내를, 아니면 저 안내를 내보내는 식입니다. 이렇게 어떤 물음의 답에 따라 실행할 코드를 골라내는 문장을 조건문이라 하고, 그 핵심 도구가 if입니다.


07.1 조건과 참거짓

조건(condition, 참인지 거짓인지 판별하는 물음)이 조건문의 출발점입니다. 앞 편에서 본 비교 연산의 결과를 떠올리면 됩니다. age >= 19 같은 식은 참이면 1, 거짓이면 0을 내놓았습니다. C는 이 값이 0이 아니면 참, 0이면 거짓으로 봅니다. if는 괄호 안 조건이 참일 때만 뒤따르는 중괄호 안 코드를 실행합니다.


#include <stdio.h>

int main(void) {

int age = 21;

if (age >= 19) {

printf("성인입니다.\n");

}

return 0;

}


실행하면 이렇게 나옵니다.


성인입니다.


만약 age가 15였다면 조건이 거짓이라 printf는 통째로 건너뛰고 화면엔 아무것도 찍히지 않습니다. 참일 때만 하는 일, 그것이 if 하나만 썼을 때의 동작입니다.


07.2 else로 두 갈래 나누기

참일 때만이 아니라 거짓일 때도 무언가 하고 싶으면 else를 덧붙입니다. 조건이 참이면 if의 블록을, 거짓이면 else의 블록을 실행하므로 둘 중 정확히 하나만 실행됩니다.


int age = 15;

if (age >= 19) {

printf("성인입니다.\n");

} else {

printf("미성년자입니다.\n");

}


미성년자입니다.


홀짝 가리기도 같은 틀입니다. 어떤 수를 2로 나눈 나머지 %가 0이면 짝수, 아니면 홀수입니다.


int n = 7;

if (n % 2 == 0) {

printf("%d는 짝수\n", n);

} else {

printf("%d는 홀수\n", n);

}


7는 홀수


07.3 중괄호를 빼면 생기는 일

중괄호 { }는 여러 문장을 한 덩어리로 묶습니다. 실행할 문장이 하나뿐이면 중괄호를 생략할 수도 있어 if (x > 0) printf("양수\n"); 처럼 씁니다.


함정. 이 생략은 위험합니다. if는 중괄호가 없으면 바로 뒤 한 문장까지만 자기 것으로 삼습니다.


int score = 40;

if (score >= 60)

printf("합격\n");

printf("축하합니다\n"); // if와 무관!


축하합니다


들여쓰기 탓에 두 줄 다 if에 속한 것처럼 보이지만, 조건에 묶인 것은 첫 줄 하나뿐입니다. 둘째 printf는 조건과 상관없이 늘 실행되어, 40점 불합격인데도 축하가 찍힙니다. 문장이 하나여도 { }로 감싸는 습관을 들이면 이런 사고를 막습니다.


07.4 대입과 비교를 헷갈리면

함정. 조건 자리에 같음 비교 == 대신 대입 =를 쓰는 실수입니다. 등호 하나는 값을 넣으라는 명령이고, 등호 둘이 같은지 견주는 비교입니다. 생김새가 비슷해 자꾸 헷갈립니다.


int login = 0; // 0은 로그인 안 됨

if (login = 1) { // 비교가 아니라 대입!

printf("환영합니다\n");

}


login = 1은 login에 1을 넣고, 그 대입식 자체의 값인 1을 조건으로 씁니다. 1은 0이 아니므로 언제나 참, 로그인 여부와 상관없이 환영 인사가 찍히고 login까지 1로 바뀝니다. 같은지 물으려면 반드시 if (login == 1)이어야 합니다. -Wall 경고 옵션을 켜 두면 컴파일러가 이런 자리를 짚어 줍니다.


07.5 else if로 여러 갈래 나누기

갈림길이 둘을 넘으면 else if를 이어 붙입니다. 위에서부터 조건을 차례로 검사하다가, 처음으로 참인 가지 하나만 실행하고 나머지는 건너뜁니다. 점수로 학점을 매겨 보겠습니다.


int score = 82;

if (score >= 90) {

printf("A\n");

} else if (score >= 80) {

printf("B\n");

} else if (score >= 70) {

printf("C\n");

} else {

printf("F\n");

}


B


[C 07] 조건문 if, else, else if


82는 90 이상은 아니지만 80 이상이라, 둘째 가지에서 B가 찍히고 검사가 끝납니다. 주의. 순서가 중요합니다. 만약 score >= 70을 맨 위에 두면 82도 95도 모두 거기 먼저 걸려 늘 C가 나옵니다. 범위가 좁은 조건, 곧 큰 값부터 위에 두어야 합니다.


07.6 여러 조건을 함께 걸기

로그인처럼 조건 두 개가 동시에 맞아야 할 때가 있습니다. 앞 편의 논리 그리고 &&로 묶으면 됩니다. 아이디와 비밀번호가 둘 다 맞아야 통과한다고 해 보겠습니다.


int idOk = 1; // 아이디 확인됨

int pwOk = 0; // 비밀번호 틀림

if (idOk && pwOk) {

printf("로그인 성공\n");

} else {

printf("로그인 실패\n");

}


로그인 실패


아이디는 맞았지만 비밀번호가 틀려 && 전체가 거짓이 되고, else 쪽이 실행됩니다. 둘 중 하나만 맞아도 통과시키려면 또는 ||로 바꾸면 됩니다.


07.7 조건 안에 조건 넣기

if의 블록 안에 또 다른 if를 넣을 수도 있습니다. 이것을 중첩 조건문이라 합니다. 회원인지 먼저 보고, 회원이면 다시 포인트가 충분한지 따지는 식으로 단계를 나눌 때 자연스럽습니다.


int member = 1; // 1은 회원

int point = 300;

if (member) {

if (point >= 500) {

printf("사용 가능\n");

} else {

printf("포인트 부족\n");

}

} else {

printf("회원 전용\n");

}


포인트 부족


회원 조건이 참이라 바깥 if로 들어오고, 안쪽에서 포인트가 500에 못 미쳐 else가 실행됩니다. 다만 중첩이 깊어지면 눈으로 따라가기 어려우니, 논리 연산자 &&로 한 줄에 합칠 수 있는지 늘 먼저 살피는 편이 좋습니다.


07.8 한 줄로 고르는 삼항 연산자

참과 거짓 중 값 하나만 고르면 되는 단순한 갈림길은 삼항 연산자로 한 줄에 줄일 수 있습니다. 조건 ? A : B 꼴로, 조건이 참이면 A를, 거짓이면 B를 값으로 내놓습니다.


int score = 60;

char *result = (score >= 60) ? "합격" : "불합격";

printf("%s\n", result);


합격


같은 판단을 if else로도 쓸 수 있지만, 이렇게 값 하나를 고르는 경우엔 삼항 연산자가 짧고 깔끔합니다. 다만 조건이 복잡하거나 실행할 일이 여러 줄이면 if가 읽기 낫습니다.


07.9 정리하며

if는 조건이 참일 때 코드를 실행하고, else는 거짓일 때, else if는 그 사이 여러 갈래를 위에서부터 걸러 냅니다. 실행할 문장이 하나여도 { }로 감싸고, 조건 자리의 ===를 늘 구별하는 두 가지만 몸에 붙여도 초보가 겪는 사고의 절반은 사라집니다. 조건의 값과 가지의 순서를 직접 바꿔 가며 어떤 출력이 달라지는지 확인해 보시길 권합니다.