조건문
지난번의 기록에서 배운 입출력 함수로
여러가지 재미있는 프로그램을 만들어졌다?
그러한 프로그램들을 많이 만들 수록
여러분의 실력은 몇 배로 향상된다는
사실을 잊지 말자.
C 언어에서 매우 중요한
부분인 제어문 – 그 중에서도
조건문이라는 사실을
배우거나 기록해보겠다.
우리가 자판기에서 음료수를 고를
때 자판기 내부에는 다음과
같은 과정이 수행 된다.
돈을 넣는다. 지폐인가?
맞다면 액수가 충분한가?
아니면 더 받는다.
이렇게 맞다 아니다 로 갈리게 된다.
이러한 것을 조건문 이라고 합니다.
즉 항상 실행되는 것이 아니라
특정한 조건이 맞는 경우에만 실행되는 것
그런데, 위 부분에서 우리가 여태 까지
보지 못했던 특징이 있다.
여태까지 우리는 모든 문장들이
순차적으로 실행되어 왔다.
예를들어,
//.....
printf("1\n");
printf("2 \n");
printf("3\n");
//....
와 같은 문장에서
처음에 1 이 출력되고
그 다음에 2,
그리고 마지막으로 3
가 출력이 됩니다.
1이 출력이 되지 않거나
2가 출력되지 않는 일은 없다.
뿐만 아니라, 2가 1 보다
먼저 출력되는 경우도 없다.
단지 어떠한 조건에서도 1,
2, 3 가 차례대로
출력되는 것이지요.
하지만, 위의 그림을 보도록하자.
지폐 인가? 부분을
보면 만약 Yes 라면 액수는 충분한가?
를 실행하고 No 라면 동전 인가?
를 실행하게 끔 되어 있다.
다시말해 어떠한 경우를 만족한다면
이것을 실행하고,
또 다른 경우라면
이 것을 실행하는 꼴이다.
이런 것을 ‘조건문’ 이라 한다.
어떠한 조건에 따라 실행되는
것이 달라지는 것.
if 문 시작하기
아래 예제를 봅시다.
/* if 문 이란? */
#include <stdio.h>
int main() {
int i;
printf("입력하고 싶은 숫자를 입력하세요! : ");
scanf("%d", &i);
if (i == 7) {
printf("당신은 행운의 숫자 7 을 입력했습니다");
}
return 0;
}
위 예제를 성공적으로 컴파일 한 후, 7 을 입력하였으면
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
입력하고 싶은 숫자를 입력하세요! : 7
당신은 행운의 숫자 7 을 입력했습니다
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
와 같이 나오게 된다. 그런데,
7 이 아닌 다른 수를 입력하였을 때 에는,
처럼 나오게 됩니다. 일단,
위 소스 코드에는 우리가 여태까지 보지
못했던 것이 있으니 찬찬히 뜯어 보도록 하자.
if (i == 7) {
printf("당신은 행운의 숫자 7 을 입력했습니다");
}
이는위 소스코드에서 가장 핵심적인 부분이다.
영어에서 흔히 말할 때 어떨 때,
if 라는 단어를 쓰나요. 예를 들어서,
If you are smart enough, please learn C language
(만약 당신이 충분히 똑똑하다면, C 언어를 배워라!)
라는 문장을 보았을 때 If 라는
단어는 무슨 역할을 할까?
아마 영어를 조금이나마 배운
사람들이라면, if 는
‘만약 ~ ‘ 이라는 의미를
가진 것임을 바로 알 수 있다.
C 언어에서도 마찬가지 다.
if 는 가정을 나타낸다. 여기서는
무엇을 가정 하였을까?
바로 if 문 안에 있는 i == 7
이 그 가정을 나타냅다. 즉,
만약 i 의 값이 7 이라면 이라는 뜻.
if 문은 언제나 괄호 안의
조건이 참이라면 중괄호 속의
내용을 실행하게 되고,
아니면 중괄호 속의
내용을 실행하지 않고 지나친다.
따라서, 만약 i 의 값이 7 이라면,
printf("당신은 행운의 숫자 7 을 입력했습니다");
를 실행 한 후 중괄호 밖으로 빠져 나간다.
그 후 다시 아래로 순차적으로 실행하게 된다.
즉, 마지막으로 return 0; 가 실행됩다.
그런데, i 의 값이 7 이 아니라면,
if 문의 중괄호 속의 내용은 실행되지 않고
지나쳐 버립니다. 왜냐하면 if 문 에서
i == 7 이 ‘거짓’ 이 되기 때문이다.
따라서 그냥 return 0 만 실행이 됩다.
참고적으로 == 와 같이 어떠한 두 값 사이의
관계를 나타내 주는 연산자를 관계 연산자
라고 부른다. 이 때, 관계 연산자의 좌측에
있는 부분을 좌변, 우측에 있는 부분을
우변이라 한다.
(즉, 3 == 2 와 같은 경우 3 은 좌변,)
(2는 우변 이라 부른다)
또한, 알아야 될 또 한가지 중요한 것은,
사실 관계 연산자는 어떠한 관계를 연산 한 후에,
참 이면 1 을, 거짓이면 0 을 나타내게 된다.
다시 말해, if 문은 참,
거짓에 따라서 중괄호
속의 내용을 실행 하느냐,
하지 않느냐 결정하는 것
처럼 보이지만 실제로는,
if 문 속의 조건이 0 인가
(거짓), 0 이 아닌가 (참) 에
따라서 실행의 유무를 판별하게 된다.
따라서, if (0) 이라 한다면
그 중괄호 속의
내용은 절대로 실행되지 않고,
if(1) 이라 한다면 그 중괄호 속의
내용은 100% 실행되게 된다.
/* 나눗셈 예제 */
#include <stdio.h>
int main () {
double i, j;
printf("나누고 싶은 두 정수를 입력하세요 :");
scanf("%lf %lf", &i, &j);
printf("%f 를 %f 로 나눈 결과는 : %f \n", i, j, i / j);
return 0;
}
성공적으로 컴파일 후
10 과 3 을 입력하였다면
아래와 같이 나오게 된다
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
나누고 싶은 두 정수를 입력하세요 :10
3
10.000000 를 3.000000 로 나눈 결과는 : 3.333333
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
성공적으로 되었다.
그런데 위에서 나온 소스 코드는 우리가
여태까지 바왔던 코드와 다를 바가 없다.
여태까지 배운 기능들만 이용해서 만든 것.
하지만 바로 이 부분에서 문제가 대두된다.
컴파일한 프로그램을
다시 실행시켜 1 과 0 을 차례대로
입력해 보도록하자.
즉, 1 을 0 으로 나누어 보자.
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
나누고 싶은 두 정수를 입력하세요 :1
0
1.000000 를 0.000000 로 나눈 결과는 : 1.#INF00
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
위에서 보시는 것과 같이 나눈
결과가 inf 이라는
이상한 결과를 출력되었다.
왜 일까? 왜냐하면 수학에서,
(즉 컴퓨터 에서) 어떠한 수를 0 으로
나누는 것은 금지되어 있기 때문.
위 i 와 j 변수가 double 로 선언되어
있어서 망정이지 i,j 변수를 int 형으로
선언하였다면 프로그램은 에러를
출력하고 종료 된다.
이 문제를 대수롭지 않게
여긴다면 큰 문제다.
예를들어서 여러분이
엑셀로 열심히 작업을
하였는데 실수로 어떤 수를
0 으로 나누는 작업을
하였더니 힘들게 작
업한 엑셀이 종료되 버려
파일이 날아가 버리면
여러분은 다시는 엑셀을
쓰지 않을 것. 따라서,
우리는 나누는 수 (제수)
가 0 이 아닌지 확인할 필요성이 있다.
즉, 제수가 0 이면 나누지 않고 0 이
아니면 나누는 것.
따라서 위 프로그램을
아래와 같이 수정을 해보도록 하자
#include <stdio.h>
int main() {
double i, j;
printf("나누고 싶은 두 정수를 입력하세요 : ");
scanf("%lf %lf", &i, &j);
if (j == 0) {
printf("0 으로 나눌 수 없습니다. \n");
return 0;
}
printf("%f 를 %f 로 나눈 결과는 : %f \n", i, j, i / j);
return 0;
}
만약 1 을 0 으로 나누었다면
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
나누고 싶은 두 정수를 입력하세요 :1
0
0 으로 나눌 수 없습니다.
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
그리고 다시 10 을 3 으로 나누어 보면
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
나누고 싶은 두 정수를 입력하세요 :10
3
10.000000 를 3.000000 로 나눈 결과는 : 3.333333
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
로 위와 같이 정상적으로 나타낸다.
그럼 위 소스코드를 뜯어 보도록 하자.
{
printf("0 으로 나눌 수 없습니다. \n");
return 0;
}
만약 j 의 값이 0 이라면
중괄호 속의 내용이 실행되며,
0 으로 나눌 수 없다 가 표시되고
프로그램이 종료(return 0) 된다.
반면에, j 의 값이 0 이 아니라면
중괄호 속의 내용이 실행되지 않는다.
즉, 아래의 내용이 실행되게 된다.
printf("%f 를 %f 로 나눈 결과는 : %f \n", i, j, i / j);
return 0;
이렇듯, if 문은 여러 조건에 따른
처리를 위해 사용한다.
먼저 나왔던 예제는 i 의 값이 7 일 때의
처리를 위해 if 문을 사용하였고 위의
예제는 j 의 값이 0 일 때의
처리를 위해 사용하였다.
/* 합격? 불합격? */
#include <stdio.h>
int main() {
int score;
printf("당신의 수학점수를 입력하세요! : ");
scanf("%d", &score);
if (score >= 90) {
printf("당신은 합격입니다! \n");
}
if (score < 90) {
printf("당신은 불합격 입니다! \n");
}
return 0;
}
위 소스를 성공적으로 컴파일하였다면 다음과 같이 나옵다.
만약 당신의 수학점수로 91 점을 입력하였다면,
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
당신의 수학점수를 입력하세요! : 91
당신은 합격입니다!
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
만약 당신의 수학 점수로 80 점을 입력하였다면
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
당신의 수학점수를 입력하세요! : 80
당신은 불합격 입니다!
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
와 같이 나타낸다.
if (score >= 90) {
printf("당신은 합격입니다! \n");
}
if (score < 90) {
printf("당신은 불합격 입니다! \n");
}
위 소스의 핵심이라
할 수 있는 부분은 위 두 부분입니다.
일단, if(score >= 90) 이라는
부분부터 살펴 보도록하자.
이미 짐작은 했겠지만 >= 은 ~ 이상,
즉 ~ 보다 크거나 같다 를 의미한다.
따라서, score 의 값이 90 보다
‘크거나 같으면’ if 문 안의 내용이
참 (true) 이 되어 중괄호 속의 내용이 실행된다.
따라서, 처음에 우리가 91 점을
입력하였을 때 score >= 90 이 참이 되어서
printf("당신은 합격 입니다! \n");
가 실행되다. 그런데 여기서 주의해야
할 점은 score => 90 이라고 하면 안된다는 것.
이렇게 쓰면 컴파일러는 인식을 하지 못한다.
이 부분에서 헷갈리는 사람들은
‘크거나 같다’ 라는 말 그대로 옮겨
적었다고 생각해보자.
>= 는 크거나 (>) 같다 (=) 를 합친 것이다!
마찬가지로, 아래 score < 90
도 보자면 score 가 90 미만일 때 참이다
라는 사실을 나타낸 것임을 알 수 있다.
/* 크기 비교하기 */
#include <stdio.h>
int main() {
int i, j;
printf("크기를 비교할 두 수를 입력해 주세요 : ");
scanf("%d %d", &i, &j);
if (i > j) // i 가 j 보다 크면
{
printf("%d 는 %d 보다 큽니다 \n", i, j);
}
if (i < j) // i 가 j 보다 작으면
{
printf("%d 는 %d 보다 작습니다 \n", i, j);
}
if (i >= j) // i 가 j 보다 크거나 같으면
{
printf("%d 는 %d 보다 크거나 같습니다 \n", i, j);
}
if (i <= j) // i 가 j 보다 작거나 같으면
{
printf("%d 는 %d 보다 작거나 같습니다 \n", i, j);
}
if (i == j) // i 와 j 가 같으면
{
printf("%d 는 %d 와(과) 같습니다 \n", i, j);
}
if (i != j) // i 와 j 가 다르면
{
printf("%d 는 %d 와(과) 다릅니다 \n", i, j);
}
return 0;
}
위 내용을 성공적으로 컴파일 후,
10 과 4 를 입력하였다면
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> gcc -o test test.c
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
크기를 비교할 두 수를 입력해 주세요 : 10 4
10 는 4 보다 큽니다
10 는 4 보다 크거나 같습니다
10 는 4 와(과) 다릅니다
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
와 같이 나타나게 됩니다.
이번 예제에서는 소스의 길이가 약간 길다.
하지만 따지고 보면 상당히 간단한 구조로
되어 있음을 알 수 있다.
일단 위의 예제에
관계 연산자
들의 역할에 대해 알아보도록하자.
1 . >= : 좌변이 우변보다 같거나 크면 참이 됩니다.
(6 >= 3 : 참, 6 >= 6 : 참, 6 >= 8 : 거짓)
2 . > : 좌변이 우변보다 크면 참이 됩니다.
(6 > 3 : 참, 6 > 6 : 거짓, 6 > 8 : 거짓)
3 . <= : 좌변이 우변보다 작거나 같으면 참이 됩니다.
(6 <= 3 : 거짓, 6 <= 6 : 참, 6 <= 8 : 참)
4 . < : 좌변이 우변보다 작으면 참이 됩니다.
(6 < 3 : 거짓, 6 < 6 : 거짓, 6 < 8 : 참)
5 . == : 좌변과 우변이 같으면 참이 됩니다.
(6 == 3 : 거짓, 6 == 6 : 참, 6 == 8 : 거짓)
6 . != : 좌변과 우변이 다르면 참이 됩니다.
(6 != 3 : 참, 6 != 6 : 거짓, 6 != 8 : 참)
따라서, 위 관계연산자에 따라
위 프로그램이 실행이 된다.
한 번 여러가지 숫자를
집어 넣으면서 확인해 보도록하자.
마지막으로 if 문의 구조에
대해서 간단히 정리해 보자면
if (/* 조건 */) {
/* 명령 */
}
와 같이 된다. 잊지 말도록하자!
if – else 문 시작하기
#include <stdio.h>
int main() {
int num;
printf("아무 숫자나 입력해 보세요 : ");
scanf("%d", &num);
if (num == 7) {
printf("행운의 숫자 7 이군요!\n");
} else {
printf("그냥 보통 숫자인 %d 를 입력했군요\n", num);
}
return 0;
}
만약 성공적으로
컴파일 하였다면 7 을 입력했을 때,
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> gcc -o test test.c
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
아무 숫자나 입력해 보세요 : 7
행운의 숫자 7 이군요!
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
그리고, 그 외 7 이 아닌 다른 숫자를 입력하였을 때 에는,
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
아무 숫자나 입력해 보세요 : 255
그냥 보통 숫자인 255 를 입력했군요
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
와 같이 나오게 됩니다.
자, 이제 위 소스를 뜯어 보도록하자
if (num == 7) {
printf("행운의 숫자 7 이군요!\n");
}
여태 까지 보왔듯이,
이 부분은 그냥 평범한 if 문이다.
하지만 그 다음 부분에 심상치 않은 것이 등장한다.
else {
printf("그냥 보통 숫자인 %d 를 입력했군요\n", num);
}
이번에는 여태까지 배우지
않은 것인 else 라는 것이 등장한다.
영어를 잘 하시는 분들은 지레 짐작하시고
있었겠지만 else 는 ‘그 외의~ ,
그 밖의~’ 의 뜻으로 사용되는 단어다.
그렇다면 여기서도 그러한 의미를 나타내는 것인가?
맞다. else 는 바로 ‘앞선 if 문이
조건을 만족하지 않을 때
‘ 를 나타냅니다.
즉, 앞선 if 문이 조건을 만족
안할 때 해야 할 명령을
바로 else 문에 써 주는 것.
다시 말해, else 문은
떨거지(?) 들을 처리하는 부분.
위의 경우에서도 만약
num 의 값이 7 이 아니였다면
if 문을 만족 안하게 되는 것.
그러면 자연스럽게 else 로 넘어와서
“그냥 보통 숫자인 … 를 입력했군요” 를
출력하게 되는 것. 하지만,
num 의 값이 7 이 였다면 if 문을
만족하는 것이기 때문에 else 는
거들떠 보지도 않고 넘어가게 된다.
/* if - else 죽음의 숫자? */
#include <stdio.h>
int main() {
int num;
printf("아무 숫자나 입력해 보세요 : ");
scanf("%d", &num);
if (num == 7) {
printf("행운의 숫자 7 이군요!\n");
} else {
if (num == 4) {
printf("죽음의 숫자 4 인가요 ;;; \n");
} else {
printf("그냥 평범한 숫자 %d \n", num);
}
}
return 0;
}
이번에 성공적으로 컴파일 한 후,
숫자들을 입력해 보면 비슷한 결과가
나오지만 4(死) 를 입력했을 경우
“죽음의 숫자 4 인가요 ;;; ” 가
나오게 된다.
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> gcc -o test test.c
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
아무 숫자나 입력해 보세요 : 4
나랑께? 死 번째 는 너랑께?
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
자, 이제 소스를 뜯어 보기로 하자.
else {
if (num == 4) {
printf("죽음의 숫자 4 인가요 ;;; \n");
} else {
printf("그냥 평범한 숫자 %d \n", num);
}
}
앞 if (num == 7) 부분은
이미 기록 했으니 생략하기로 하고,
else 문의 구조만 뜯어 보기로 하자.
만약 num 의 값이 4 였다고
가정을 해보도록하자.
그렇다면, 처음에 만나는
if 문에서 num == 7 이
거짓이 되므로 else 로 넘어가게 된다.
그런데, else 의 명령을 실행하려고 하는데 보니,
또 if 문이 있네요. 이번에는
if (num == 4) 가 나타낸다.
하지만 아까와는 달리
num == 4 가 참이므로 그
if 문의 중괄호 속의 명령, 즉
“죽음의 숫자 4 인가요 ;;;” 가 출력되게 된다.
그리고, 앞 예제에서 설명했듯이
if(num == 4) 아래의 else 는
무시 하게 되고, 끝나게 되는 것.
그렇다면 이제 아이디어를 확장해서
num 이 1 부터 10 일 때 까지 특별한
설명을 달기로 한다.
그러면 아래와 같이 프로그램을 짜야 되겠지.
/* 쓰레기 코드 */
#include <stdio.h>
int main() {
int num;
printf("아무 숫자나 입력해 보세요 : ");
scanf("%d", &num);
if (num == 7) {
printf("행운의 숫자 7 이군요!\n");
} else {
if (num == 4) {
printf("죽음의 숫자 4 인가요 ;;; \n");
} else {
if (num == 1) {
printf("첫 번째 숫자!! \n");
} else {
if (num == 2) {
printf("이 숫자는 바로 두번째 숫자 \n");
} else {
......(생략)......
}
}
}
}
return 0;
}
정말 믿도 끝도 없이 길어져서 나중에는
중괄호가 너무 많아 헷갈리기도 하고,
보기도 불편하게 됩다. 하지만,
C 언어는 위대한지라,
이 문제를 간단히 해결하였다.
/* 새로쓰는 죽음의 숫자 예제 */
#include <stdio.h>
int main() {
int num;
printf("아무 숫자나 입력해 보세요 : ");
scanf("%d", &num);
if (num == 7) {
printf("행운의 숫자 7 이군요!\n");
} else if (num == 4) {
printf("죽음의 숫자 4 인가요 ;;; \n");
} else {
printf("그냥 평범한 숫자 %d \n", num);
}
return 0;
}
위 코드를 실행해 보면 앞선
예제와 똑같이 작동합니다.
하지만 코드도 훨씬 보기 편해 졌고
난잡하던 중괄호도 어느 정도 정리가 된 것.
그렇다면 정말 하는 일이 똑같을 까?
Yes, 똑같다. 왜냐하면
if (/* 조건 1 */) {
// 명령 1;
} else {
if (/* 조건 2 */) {
// 명령 2;
} else {
if (/* 조건 3 */) {
// 명령 3;
} else {
// ....
}
}
}
위와 같은 코드를 단지 아래 처럼
‘간단히’ 표현한 것이기 때문
if (/* 조건 1 */) {
// 명령 1;
} else if (/* 조건 2 */) {
// 명령 2;
} else if (/* 조건 3 */) {
//명령 3;
}
....else {
// 명령 ;
}
단지, 보기 편하게 하기 위해 ‘간략하게’
줄인 꼴과 같다는 것. 마치 a = a + 10 을
a+= 10 으로 바꾼 것 처럼 말이지.
/* if 와 if- else if 의 차이*/
#include <stdio.h>
int main() {
int num;
printf("아무 숫자나 입력해 보세요 : ");
scanf("%d", &num);
if (num == 7) {
printf("a 행운의 숫자 7 이군요!\n");
} else if (num == 7) {
printf("b 행운의 숫자 7 이군요! \n");
}
// 비교
if (num == 7) {
printf("c 행운의 숫자 7 이군요!\n");
}
if (num == 7) {
printf("d 행운의 숫자 7 이군요! \n");
}
return 0;
}
성공적으로 컴파일 후,
7 을 입력하였다면
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> gcc -o test test.c
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
아무 숫자나 입력해 보세요 : 7
a 행운의 숫자 7 이군요!
c 행운의 숫자 7 이군요!
d 행운의 숫자 7 이군요!
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
와 같이 나오게 된다.
여기서 주목해야 할 점은,
출력되는 문장 앞의 알파벳 (a,c,d) 인데
이는 각 문장이 위 프로그램의
어느 부분에서 출력되는 지 알려준다.
우리가 컴퓨터 라고 생각하고 프로그램을
실행해 봅시다. 통상적으로 프로그램은
소스코드의 위에서 부터 아래 방향으로 실행된다
if (num == 7) {
printf("a 행운의 숫자 7 이군요!\n");
} else if (num == 7) {
printf("b 행운의 숫자 7 이군요! \n");
}
컴퓨터가 쭉 프로그램을 읽다가 위 부분에 도달하면
“어! if 문이군. num 의 값이 7 인지 확인해 볼까?”
라고 확인을 한다. 그런데,
참 이므로 “오, if 문이 참 이군.
그렇다면 중괄호 속의 내용을 실행해야겠다! ”
하며 “a 행운의 숫자 7 이군요” 를 출력한다.
그런데, 그 다음 부분인 else if(num == 7) 에서도
마찬가지로 num 의 값이 7 이므로 num == 7
이 참이 되어서 else if 가 참이 되어 “b
행운의 숫자 7 이군요! ” 도 출력되어야
할 것. 하지만, 결과롤 보아하니
출력이 되지 않았습니다. 왜 일까?
왜냐하면, 앞에서 누누히 설명했듯이
else 문은 전제 조건이 ‘앞의 if 문이
참이 아닐 때’ 실행 된다는 사실을 기본으로
깔고 있기 때문. 따라서,
앞의 if 문이 참이므로 실행이
될 수 없다. 따라서, “b
행운의 숫자 7 이군요! ” 도
출력되지 않는다. 참고적으로
else 문은 언제나 if 문의 결과에
따라 실행 여부가 결정되므로
언제나 else 를 사용하려면 if 도
반드시 함께 따라 사용해야 한다.
다시 컴퓨터가 쭉 읽다가 아래와 같은 문장을 발견했다
if (num == 7) {
printf("c 행운의 숫자 7 이군요!\n");
}
if (num == 7) {
printf("d 행운의 숫자 7 이군요! \n");
}
“어! if 문이군. 그런데
num 의 값이 7 이므로 이 if 문은 참이야.
중괄호 속의 내용을 실행해야지” 하면서 “
c 행운의 숫자 7 이군요!” 가 출력된다.
마찬가지로 아래도
“어! if 문이군. 그런데 num 의
값이 7 이므로 이 if 문은 참이야.
중괄호 속의 내용을 실행해야지” 하면서 “d
행운의 숫자 7 이군요!” 가 출력되는 것.
#include <stdio.h>
int main() {
float ave_score;
float math, english, science, programming;
printf("수학, 영어, 과학, 컴퓨터 프로그래밍 점수를 각각 입력해 주세요 ! : ");
scanf("%f %f %f %f", &math, &english, &science, &programming);
ave_score =
(math + english + science + programming) / 4; // 4 과목의 평균을 구한다.
printf("당신의 평균 점수는 %f 입니다 \n", ave_score);
if (ave_score >= 90) {
printf("당신은 우등생 입니다. ");
} else if (ave_score >= 40) {
printf("조금만 노력하세요!. \n");
} else {
printf("공부를 발로 합니까? \n");
}
return 0;
}
만약 성공적으로 컴파일 하였다면
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> gcc -o test test.c
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
수학, 영어, 과학, 컴퓨터 프로그래밍 점수를 각각 입력해 주세요 ! : 100
90
90
85
당신의 평균 점수는 91.250000 입니다
당신은 우등생 입니다.
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
와 같이 나오게 된다. 그 외에도,
다른 값들을 입력하면
다른 결과가 출력됨을 알 수 있다.
ave_score = (math + english + science + programming) / 4;
아마, 산술 연산을 까먹으신 분들은 없겠지?
위 식이 2 초 내로 이해가 되지 않는다면
4강 으로 다시 되돌아 가보자.
위 식은, 수학, 영어, 과학, 프로그래밍 점수의
평균을 구해서 ave_score 라는
변수에 대입하는 식이다.
if (ave_score >= 90) {
printf("당신은 우등생 입니다. ");
} else if (ave_score >= 40) {
printf("조금만 노력하세요!. \n");
} else {
printf("공부를 발로 합니까? \n");
}
위 프로그램의 핵심 부분(?) 이라
할 수 있는 이 부분을 잘 살펴보도록하자.
만약 내 평균 점수가 93 이라면,
“당신은 우등생 입니다”
가 출력되게 되죠. 그리고, 아래
else if 와 else 는 무시하고 종료.
하지만 평균 점수가 40 이라면,
위의 if (ave_score >= 90) 이 거짓이 되어
다음으로 넘어가죠. 즉,
else if (ave_score >= 30) 을 한다.
이번에는 참이 되므로,
조금만 노력하세요!
가 출력이 되고 종료.
또한, 평균점수가 10 점 이라면
위의 if 와 else if 모두 거짓이지만
else if(ave_score > 0 ) 은 참이 되어
공부를 발로 합니까? 가 출력 된다.
마지막으로 평균점수가 0 점 이하 라면,
떨거지 처리(?) 인 else 에서 참이 되어서
인생을 포기하였군요 가 실행.
/* 크기 비교 */
#include <stdio.h>
int main() {
int a;
printf("아무 숫자나 입력하세요 : ");
scanf("%d", &a);
if (a >= 10) {
if (a < 20) {
printf(" %d 는 10 이상, 20 미만인 수 입니다. \n", a);
}
}
return 0;
}
성공적으로 컴파일 후,
10 이상 20 미만의 수를 입력했다면
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> gcc -o test test.c
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
아무 숫자나 입력하세요 : 10
10 는 10 이상, 20 미만인 수 입니다.
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
와 같이 나오게 된다.
위 소스 코드는 간단하다.
우리가 여태까지 기록한거 만으로도
충분히 이해 할 수 있다!
if (a >= 10) {
if (a < 20) {
printf(" %d 는 10 이상, 20 미만인 수 입니다. \n", a);
}
}
처음에, a 의 값이 10 이상이면 참이 되어서
중괄호 속의 내용을 실행하게 되고,
또한 거기서 a < 20 이라는 if 문을
만나게 되는데 이것 조차
참이라면 printf 가 실행되겠지,.
그런데, 사실 위 문장은
아래와 같이 간단히 줄여 쓸 수 있다.
논리 연산자
논리 곱 연산자 (Logical AND)
/* 논리 연산자 */
#include <stdio.h>
int main() {
int a;
printf("아무 숫자나 입력하세요 : ");
scanf("%d", &a);
if (a >= 10 && a < 20) {
printf(" %d 는 10 이상, 20 미만인 수 입니다. \n", a);
}
return 0;
}
위 소스를 그대로 컴파일 해 보면
위와 결과가 똑같이 나온다.
그렇다면 ‘&&’ 는 무엇일까?
그 것은 바로 논리 곱(AND) 라고
불리는 논리 연산자 이다
왜 논리 “곱” 이냐면, 곱셈은 둘 중 하나라도 0 이라면 0 이 됩니다. AND 도 마찬가지로 둘 중 하나라도 0 이라면 0 이 되었죠. |
앞에서 우리는 AND 연산에
대해 기록한적이 있었다.
이 때, AND 연산의 특징은 바로
오직 1 AND 1 만이 결과가 1 이였고,
1 AND 0 또는 0 AND 0 은
모두 결과가 0 이였다.
여기서도 마찬가지 이다.
위에서도 이야기 했지만 ‘참’ 은
숫자 1 에 대응되고 ‘거짓’ 은
숫자 0 에 대응 된다.
따라서, a >= 10 이 참이라면 1 을
나타내고, 거짓이라면 0 을
나타낸다고 보시면 된다.
정확히 말하자면 C 에서 0 은 거짓, 0 이 아닌 모든 값은 참을 나타냅니다.
|
마찬가지로, a < 20 도
참 이라면 1 을 나타내고,
거짓이라면 0 을 나타낸다.
만약 a >= 10 도 참이고
a < 20 도 참 이라면
1 AND 1 을 연산하는
것과 같게 되어서
결과가 1, 즉 참이 되어 if 문의 중괄호
속의 내용을 실행하게 된다.
반면에 a < 10 라던지 a >= 20 이여서
둘 중 하나라도 조건을 만족하지 않게
된다면 1 AND 0 이나 0 AND 1 을
하는 것과 같게 되어 결과가 0 즉
거짓이 된다.
따라서 중괄호 속의
내용은 실행되지 않게 된다.
정리하자면, && 는 두 개의
조건식이 모두 ‘참’ 이 되어야
if 문 속의 내용을 실행하는 것이.
왜 & 대신에 && 를 쓸까?
그렇다면 우리가 여태 알고 있었던
AND 연산 기호인 & 를 쓰지 않고
&& 를 쓰는 것일까?
그 이유는 & 하나는,
말 그대로 비트 사이의 AND 연산을
사용 할 때 사용하는 것이로,
조건식 사이의 관계를 표현하고
싶다면 논리 곱 연산자인
&& 를 사용해야 합니다.
쉽게 말해 & 는 정확한
비트 AND 연산 결과를 제공하고,
&& 는 그냥 참 (= 1) 혹은
거짓 (= 0) 만을 알려준다.
따라서 만약에 어떠한 int 변수 a 와 b
사이에 AND 연산을 하고 싶다면
a & b 를 해야지,
a && b 를 하면 올바른
AND 연산을 수행할 수 없다.
간단히 아래 예제를 보면 알 수 있다.
#include <stdio.h>
int main() {
int a = 31, b = 15;
printf("a & b = %d\n", a & b);
printf("a && b = %d\n", a && b);
}
성공적으로 컴파일 하였다면
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> gcc -o test test.c
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
a & b = 15
a && b = 1
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
흠 그렇다면 반대로 && 자리에 & 를
써도 무방할 것 같은데 말이지.
왜냐하면 위에서도 말했듯이 0 이 아닌
모든 값들은 어차피 참으로 간주되기 때문
그런데 왜 논리식 사이에는 && 를
사용하는 것이 바람직할까?
Short Circuit Evaluation
예를 들어서 다음과 같은 문장을 생각해보도록하자.
if (height >= 180 && weight >= 90) {
}
만약에 height 가 179 라고 해봅시다.
그렇다면 굳이 그 다음의
조건식인 weight >= 90 을
확인해봐야 할까? 아니다.
AND 의 경우 어차피 둘 중 하나가
거짓이라면, 그 다음것은
확인해볼 필요도 없이
전체 연산 결과가 거짓임을 알 수 있다.
따라서 굳이 weight >= 90 을
확인해볼 필요가 없다.
위 경우 처럼 한 조건식을
확인하였는데 전체 결과가
정해져 있는 경우,
굳이 그 다음 조건식을 확인할 필요가 없다.
이 같은 경우 컴퓨터는 뒤의 조건식을
확인하지 않는데
(쓸데 없는 연산을 줄이기 위해서),
이와 같은 방식을
Short Circuit Evaluation
이라고 부른다.
(줄여서 SCE 라고 부릅시다.)
만약에
height >= 180 & weight >= 90
처럼 & 를
사용하였다면 SCE 를 적용할 수 없다.
왜냐하면 & 는 정확한 연산 결과를
제공해야 하므로 뒤에
오는 식도 반드시 계산을
해야 하기 때문 하지만 && 는 논리
결과에 따라서 0 혹은 1 만 돌려주면 되기
때문이므로 SCE 를 사용 할 수 있다.
주의 사항 |
조건식 사이의 관계를 표현하고 싶다면 반드시 논리 연산자를 사용하세요!
|
논리 합 연산자 (Logical OR)
/* 논리 합 */
#include <stdio.h>
int main() {
int height, weight;
printf("당신의 키와 몸무게를 각각 입력해 주세요 : ");
scanf("%d %d", &height, &weight);
if (height >= 190 || weight >= 100) {
printf("당신은 '거구' 입니다. \n");
printf("씨름 이나 스모 대회로··· \n");
}
return 0;
}
성공적으로 실행 후, 키를 190 이상으로
입력했거나 몸무게를 100 이상으로 입력했다면
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> gcc -o test test.c
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
당신의 키와 몸무게를 각각 입력해 주세요 : 200 90
당신은 '거구' 입니다.
씨름 이나 스모 대회로···
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
위와 같이 나오게 된다.
이번에는 || 라는 것이 등장하였다.
앞서 AND 가 && 였다는 것을 보아,
|| 는 OR 를 나타내는
논리 연산자임을 알 수 있다.
기억을 되살려 봅시다.
AND 와 OR 의 차이가 뭐였는가?
AND 가 두 조건이 모두 참 일 때,
참을 반환한다면,
OR 은 두 조건이 모두
거짓 일 때 만 거짓을 반환한다.
다시말해
(참) || (거짓) == (참)
이 된다는 것
if (height >= 190 || weight >= 100)
그렇다면 위 if 문을 살펴 보도록하자.
height >= 190 이 참 이라면,
OR 연산한 값은 weight 의
크기에 관계없이
무조건 참이 되어서 중괄호 속의
내용을 실행 한다.
또한 height >= 190 이 거짓이여도,
weight >= 100 이 참 이라면
중괄호 속의 내용을 실행하게 되죠.
따라서,
OR 논리 연산자는 조건식에서
적어도 어느 하나가
참 이라면 무조건
if 문의 내용을 실행해 주게 된다.
/* 논리 부정 */
#include <stdio.h>
int main() {
int height, weight;
printf("당신의 키와 몸무게를 각각 입력해 주세요 : ");
scanf("%d %d", &height, &weight);
if (height >= 190 || weight >= 100) {
printf("당신은 '거구' 입니다. \n");
}
if (!(height >= 190 || weight >= 100)) {
printf("당신은 거구가 아닙니다. \n");
}
return 0;
}
위 소스를 성공적으로 컴파일 한 후,
180 과 80 을 입력하였다면
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> gcc -o test test.c
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\> ./test
당신의 키와 몸무게를 각각 입력해 주세요 : 180 80
당신은 거구가 아닙니다.
PS D:\□□□□□_fFF□\□□□g□□□m□□□\F\>
와 같이 나옵니다.
위 소스에서 관심있게
살펴 보아야 할 부분은 바로 이 부분
if (!(height >= 190 || weight >= 100)) {
printf("당신은 거구가 아닙니다. \n");
}
(참고로 위의 소스와 다른 점은)
(height 앞에 ! 가 붙었다는 점)
다른 것은 다 똑같은데, 새로 붙은
! 가 무슨 역할을 하는 것 같나?
아마도 예측 하셨겠지만, ! 는
NOT 을 취해주는 연산자다.
다시 말해, 참을 거짓으로,
거짓을 참으로 반전을 시켜 준다.
다시 말해 0 은 1 로,
0 이 아닌 값은 0 으로 변환해준다.
위 경우, height >= 190 || weight >= 100 가
거짓일 경우에만, 다시 말해서
height < 190 && weight < 100 인
경우에만 중괄호 속의 내용이 실행 된다.
참고로 ! 연산자가 0 이 아닌 값은
0 으로 변환해준다는 특성을 이용해서
보통 어떠한 변수의 값이 0 이 아닌지를
판별하기 위해 아래와 같이 작성하기도 한다.
if (!p) { // p == 0 과 같은 의미이지만 더 짧기 때문에 자주 사용된다 :)
// p 가 0 일 때에만 실행된다.
}
정 리 |
if, else if, else 가 무엇 인지 알고 있습니다. 논리 연산자 &&, || 를 배웠습니다. ! 의 역할을 알고 있습니다. 0 <= a <= 1 을 잘못된 사용 예 입니다. 이 대신 0 <= a && a <= 1 과 같이 사용해야 합니다. |