Do it! c언어 입문 독학 6일차
Do it! c언어 입문 이라는 책을 보면서 혼자 공부하는 시간을 가져보자. 이 내용들은 모두 이 책에 기재되어 있다.
<책 출처>
김성엽. 『Do it! C언어 입문』. 이지스퍼블리싱(2018)
<8장: 조건문>
제어문
제어문은 프로그램의 실행 흐름을 제어하는 문법으로, C언어에서는 다음과 같은 두 가지 형태의 제어문을 제공한다.
1. 조건문: 예외 사항에 대처하기 위한 문법
→ if, switch
2. 반복문: 반복 행위를 효과적으로 표현하기 위한 문법
→ for, while, do~while
if 조건문
if조건문의 기본적인 문법 구성은 다음과 같다.
if(조건수식) 명령문;
괄호 안에 있는 조건 수식의 결과 값이 참으로 나오면 그 뒤에 명시한 명령문 1개를 수행하는 문법이다. 여기에서 참은 0이 아닌 모든 값을 의미한다.
단일 문장을 수행하는 if 조건문
#include<stdio.h>
void main()
{
int data = 5; /* 명령문1 */
if(data > 3) printf("data는 3보다 큰 수입니다. \\n"); /* 명령문2 */
printf("작업 종료 \\n"); /* 명령문3 */
}
출력 결과: data는 3보다 큰 수입니다.
작업 종료
조건 수식의 결과 값이 참일 때 하나의 단일 명령문만 수행한다.
참일 때: 명령문 1 → 명령문 2 → 명령문 3
거짓일 때: 명령문 1 → 명령문 3
복합 문장을 수행하는 if 조건문
#include<stdio.h>
void main()
{
int score = 92; /* 명령문 1-1 */
char grade; /* 명령문 1-2 */
/* score >= 90 비교 연산의 결과 값은 참이기 때문에
{}에 포함된 명령문들을 모두 수행함 */
if(score >= 90) {
grade = 'A'; /* 명령문 2 */
printf("점수는 %d이고 등급은 %c입니다.\\n",score,grade); /* 명령문3 */
}
printf("작업 종료\\n"); /* 명령문4 */
}
출력 결과: 점수는 92이고 등급은 A입니다.
작업 종료
조건 수식의 결과 값이 참일 때 {}로 모아 놓은 명령문들을 모두 수행한다.
참일 때: 명령문 1 → 명령문 2 → 명령문 3 → 명령문 4
거짓일 때: 명령문 1 → 명령문 4
if 조건문을 사용할 때 주의 사항
1. 대입 연산자와 관계 연산자의 혼동
<대입 연산자를 잘못 사용한 예>
int data = 5;
if(data = 3) {
/* data는 3에서 4가 됨 */
data++;
}
/* 최종 data 값은 4 */
= 연산자는 대입 연산자로, 말 그대로 대입을 하는 것이기 때문에 주의하자.
<대입 연산자를 올바르게 사용한 예>
int data = 5;
if(data == 3) {
data++;
}
/* 최종 data 값은 5 */
프로그램에서는 수치가 같은지 확인할 때 == 연산자를 사용한다.
2. 세미콜론으로 인한 오류
<단일 문장에서 잘못 사용>
int data = 5;
if(data > 3);
data++; /* data는 6이 됨 */
<복합 문장에서 잘못 사용>
int data = 5;
int result = 0;
if(data > 3);
{
data++;
result = data; /* data는 6이 됨 */
}
if문 바로 뒤에는 세미콜론을 붙이지 않는다. 항상 조건 수식 다음에 나오는 명령문부터 세미콜론을 붙일 것.
if ~ else ~ 조건문
조건문을 사용하다 보면 상황이 서로 반대되는 조건을 나열해야 할 때가 있는데, 이때 if else 조건문을 사용한다. if else 조건문을 사용하면 조건 수식은 한 번만 수행하고, 간결해진다.
단일 if ~ else ~ 문
#include<stdio.h>
void main()
{
int data = 5; /* 명령문1 */
if(data > 3) printf("data는 3보다 큰 수입니다.\\n"); /* 명령문2 */
else printf("data는 3보다 작거나 같은 수입니다.\\n"); /* 명령문3 */
printf("작업 종료 \\n"); /* 명령문4 */
}
출력 결과: data는 3보다 큰 수입니다.
작업 종료
참일 때: 명령문 1 → 명령문 2 → 명령문 4
거짓일 때: 명령문 1 → 명령문 3 → 명령문 4
복합 if ~ else ~ 문
#include<stdio.h>
void main()
{
int score = 92; /* 명령문 1-1 */
char grade; /* 명령문 1-2 */
if(score >= 90) {
grade = 'A'; /* 명령문2 */
printf("점수는 %d이고 등급은 %c입니다.\\n",score,grade); /* 명령문3 */
} else {
grade = 'B'; /* 명령문4 */
printf("점수는 %d이고 등급은 %c입니다.\\n",score,grade); /* 명령문5 */
}
printf("작업 종료\\n"); /* 명령문6 */
}
출력 결과: 점수는 92이고 등급은 A입니다.
작업 종료
참일 때: 명령문 1 → 명령문 2 → 명령문 3 → 명령문 6
거짓일 때: 명령문 1 → 명령문 4 → 명령문 5 → 명령문 6
#if문이 복합 문장일 때, else문은 단일 문장이 가능하다. 반대로 if문이 단일 문장일 때 else문도 복합 문장이 가능하다.
if ~else ~ 조건문과 비슷한 조건 수식 연산자
조건 수식 연산자는 if else 조건문과 비슷한 형태를 가지는 연산 수식으로, 조건문과 달리 연산자이기 때문에 명령을 처리하고 나면 결과 값을 반환하는 형태로 되어 있다.
💡 결과 값 = (조건 수식)? 수식 1 : 수식 2;
조건 수식의 결과 값이 참이면 수식 1의 결과 값을 사용하고 거짓이면 수식 2의 결과 값을 사용한다.
→ 조건 수식 연산자는 단일 문장으로 구성된 명령문만 사용할 수 있다.(단점)
<두 문법 비교>
<if ~ else ~ 조건문>
if(data > 5) return 1;
/* data가 5보다 크면 1을 반환함 */
else return 0;
/* data가 5보다 작거나 같으면 0을 반환함 */
<조건 수식 연산자>
return (data > 5) ? 1 : 0;
중첩된 if 조건문
if 조건문을 사용하다 보면 조건 수식이 만족되어 실행하는 명령문 안에 또 조건문이 포함되는 경우가 있다. 이를 중첩된 조건문이라 한다.
중첩된 if문 예
#include<stdio.h>
void main()
{
/* 2015년 12월 31일을 3개의 정수 변수에 나누어서 대입함 */
int year = 2015, month = 12, day = 31;
/* 일을 하루 증가시키면 day가 31에서 32가 됨 */
day++;
/* 일이 31일을 초과하면 1일로 바뀌고 월을 증가시킴 */
if(day > 31) {
month++; /* 월을 증가시키면 month가 12에서 13이 됨 */
day = 1; /* 월이 증가되었으니 해당 월의 처음인 1일로 변경함 */
/* 월이 12월을 초과하면 1월로 바꾸고 연도를 증가시킴 */
if(month > 12) {
year++; /* 연도를 증가시키면 year가 2015에서 2016이 됨 */
month = 1; /* 연도가 증가되었으니 12월에서 1월로 변경함 */
}
}
printf("Date: %d년 %d월 %d일\\n",year,month,day);
}
출력 결과: Date: 2016년 1월 1일
중첩된 if ~ else ~ 문 예제
#include<stdio.h>
void main()
{
/* 점수를 86점으로 설정함 */
int score = 86;
/* 점수에 따른 등급을 저장할 변수를 선언함 */
char grade;
if(score >= 90) { /* 90점 이상인 경우 */
grade = 'A';
} else { /* 90점보다 작은 경우 */
if(score >= 80) { /* 80점 이상이고 90점보다 작은 경우 */
grade = 'B';
} else { /* 80점보다 작은 경우 */
if(score >= 70) { /* 70점 이상이고 80점보다 작은 경우 */
grade = 'C';
} else { /* 70점보다 작은 경우 */
if(score >= 60) { /* 60점 이상이고 70점보다 작은 경우 */
grade = 'D';
} else { /* 60점보다 작은 경우 */
grade = 'F';
}
}
}
}
/* 자신의 점수와 등급을 출력함 */
printf(" 당신의 점수는 %d점이고 등급은 %c입니다.\\n");
}
출력 결과: 당신의 점수는 86점이고 등급은 B입니다.
if ~ else if ~ else 조건문 예제
앞의 예제에서 더 쉽고 간단하게 만들 수 있다.
#include<stdio.h>
void main()
{
int score = 86;
char 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';
}
}
}
printf("당신의 점수는 %d점이고 등급은 %c입니다.\\n",score,grade);
}
if ~ else ~ 문은 하나의 문법이기 때문에 한 개의 문장으로 처리할 수도 있다. 즉, 여기서 더 간결하게 만들 수 있다.
#include<stdio.h>
void main()
{
int score = 86;
char 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';
printf("당신의 점수는 %d점이고 등급은 %c입니다.\\n",score,grade);
}
이런 식으로 생략 가능한 부분은 생략하여 간단하게 중첩 if문을 사용할 수 있다.
switch 조건문
C언어에서는 모든 조건문을 if문으로 표현할 수 있기 때문에 if문만 사용해도 문제가 없으나, 특정 상황에서는 if문보다 switch 조건문이 효율적일 때가 있다. 주로 변수 값이 이미 정해져 있는 상수들과 비교할 때는 switch 조건문이 유리하다.
switch 조건문의 기본 구조
switch 조건문은 정해진 상수들과 직접적인 비교를 할 수 있는 문법 구조로 되어 있다.
명령문1;
switch(수식 또는 변수)
{
case 상수1:
명령문2;
break;
case 상수2:
명령문3;
case 상수3:
명령문4;
break;
default:
명령문5;
break;
}
명령문6;
각 case문을 보면 break라는 예약어를 사용하는데 이는 현재 수행되는 case문의 작업을 중단하겠다는 뜻이다. 따라서 상수 1과 일치한다면 명령문 2만 수행한 뒤 작업을 중단하게 된다.
또한 조건 수식과 일치하는 case 상수가 없다면 default 문을 수행해 명령문 5만 수행하게 된다. default문을 사용하는 위치도 항상 마지막일 필요는 없고, case문과 case문 사이에 둘 수도 있다.
switch 조건문과 if ~ else if ~ else 문 비교
위의 if ~ else if ~else 문 예제 코드를 switch 조건문으로 바꾼 예제이다.
#include<stdio.h>
void main()
{
int score = 86;
char grade;
switch(score / 10) {
case 10:
case 9:
grade = 'A';
break;
case 8:
grade = 'B';
break;
case 7:
grade = 'C';
break;
case 6:
grade = 'D';
break;
default:
grade = 'F';
break;
}
printf("당신의 점수는 %d점이고 등급은 %c입니다.\\n",score,grade);
}
출력 결과: 당신의 점수는 86점이고 등급은 B입니다.
if 조건문에서는 범위를 비교하도록 조건 수식이 구성되어 있었는데 swith 조건문은 상수와 같은지를 비교하는 형식이 되어야 한다.
switch문은 수식의 결과 값 또는 변수의 값을 여러 개의 상수 값과 비교하는데 장점이 있으나, case문에 상수가 아닌 변수를 적을 수 없기 때문에 비교 대상이 상수가 아닌 경우에는 switch문을 사용할 수 없다는 단점이 있다.