기본 중의 기본인데, 헷갈리는 것들만 정리해보겠다.
생략가능
- if, for, while 전부 다 실행문이 한 줄이면 중괄호를 생략해도 된다.
- while은 일반적으로 변화식이 루프 본체에 포함되므로 생략할 일이 거의 없다.
- 제어문 내부에 제어문이 존재할 때, 내부의 제어문이 생략가능하면 그것을 감싸고 있는
제어문 역시 중괄호를 생략할 수 있다. -> 좋은 형태는 아닌듯하다.- if는 한 줄, else는 여러 줄일 때 if만 중괄호 생략 가능하다.
값을 할당할 때 사용한다. if-else 문으로 완벽하게 바꿀 수 있다. if-else 문보다 코드의 길이를 획기적으로 줄일 수 있지만, 가독성이 좋지 않다는 단점이 있다. 잘 쓰이는 것 같지는 않다.
조건식이 참이면 값1, 거짓이면 값2가 결과값이다.
예시 1
#include <stdio.h>
int main(void)
{
for (int i = 0; i < 10; ++i)
printf("%d%c", i, (i < 9) ? ',' : '\n');
return 0;
}
출력
0,1,2,3,4,5,6,7,8,9
그나마 가장 유용하게 사용한 예시이다. 반복문으로 출력할 때, 삼항 연산자를 활용해서 마지막 인덱스에서 자연스러운 출력을 가능하게 한다.
예시 2
#include <stdio.h>
int main(void)
{
int num;
scanf("%d", &num);
printf("%d is a %s number\n", num,
(num > 0) ? "positive" : (num == 0) ? "zero" : "negative")
return 0;
}
입력
1
출력
1 is a positive number
이렇게 2단계로 작성가능하다. 앞에서부터 검사한다. 가장 앞의 num > 0
조건이 거짓일 경우에 뒤에 있는 삼항 연산자로 한 번 더 검사한다. 한 번만 써도 가독성이 떨어지는데 이건 너무하다. 혼자만 알아볼 수 있는 이런 방식으로 코드를 짜지 말자.
조건식의 괄호에는 정수식만 가능하다. if-else 문보다 조건 검사 횟수가 적기 때문에 속도가 더 빠르다. 따라서 조건식이 정수식이라면 가능한 switch 분기문으로 바꿔주는 것이 좋다.
예시 1
#include <stdio.h>
int main(void)
{
int score;
scanf("%d", &score);
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';
}
printf("score: %d -- grade: %c\n", score, grade);
return 0;
}
대표적인 예시다. 각 case마다 break
를 걸어준다. 조건식의 결과값에 해당하는 case로 점프되고 그 지점부터 실행이 계속된다. 따라서 break
를 걸어주지 않으면 그 case만 실행되는 것이 아니기 때문에 원치않는 결과가 나타날 수 있다. default는 if-else 문의 else와 같은 역할을 하는데, 어떤 case에도 해당되지 않으면 default로 넘어온다. default는 마지막에 있기 때문에 굳이 break
를 걸지 않아도 된다. 써주기도 하던데 어떤 차이가 있는지 잘 모르겠다.
예시 2
#include <stdio.h>
int main(void)
{
int num;
scanf("%d", &num);
switch (num) {
case 1:
case 2:
printf("1 또는 2입니다.\n");
break;
case 3:
case 4:
printf("3 또는 4입니다.\n");
break;
default:
printf("default\n");
}
return 0;
}
break
를 걸어주지 않아서 다음 case까지 넘어가는 것을 fall through 라고 한다. 예시 2와 같이 유용하게 사용할 수 있는 경우가 많다. 이렇게 활용하려면 동일한 실행을 하는 case가 연속되어야함을 주의하자.
for 문은 아래와 같이 작성된다.
for문에서 사용될 변수 i
를 for문 내부의 초기화에서 선언해도 되고, for문 외부에서 미리 선언해도 된다. for문 내에서 선언하는 것이 최신 문법인 것 같다. 필요에 따라서 for문 외부에서 선언하기도 하는데, 루프를 종료한 후에 for문에서 사용된 루프 인덱스 i
의 값이 필요할 때 주로 외부에서 선언한다. 증감에서 일반적으로 i++
로 많이쓴다. 근데 내부적으로 i++
원래 값을 증가시키고 결과값은 증가시키기 전의 값이라서 따로 저장이 필요하다. ++i
에 비해서 메모리를 더 사용하는 것이다. 뭔 큰 차이가 있겠냐만은 그렇다고 하니까 나는 ++i
로 사용하겠다.
위와 같은 순서로 for문이 실행된다. 루프 인덱스 i
가 초기화 되거나 증감이 이루어진 후에 먼저 조건을 확인하고 조건이 만족되었을 때 루프 본체로 넘어가서 실행문이 실행된다. 이런 순서로 진행되므로 루프가 종료될 때 i
에 저장된 최종값은 조건식 i < 3
에 해당되지 않는 3
이다.
while문 외부에서 제어 변수가 선언되어야 하고 내부에는 반드시 제어변수의 증감이 필요하다. 예시1이 가장 일반적인 형태이지만, 예시2와 같이 무한루프와 break를 활용하는 것이 더 편할 때도 많다.
예시1
#include <stdio.h>
int main(void)
{
int i = 1; // 제어변수 초기화
while (i <= 10) { // 조건식
printf("%d ", i);
++i; // 증감
}
return 0;
}
예시2
#include <stdio.h>
int main(void)
{
int i = 1;
while (1) {
if (i > 10)
break;
printf("%d ", i);
++i;
}
return 0;
}
while문과 달리 조건과 상관없이 무조건 한 번은 실행된다. 수치해석을 수행할 때 주로 while문을 사용하는데, 조건을 검사하기 위해서는 루프를 한 번 돌린 결과값이 필요할 경우가 있다. 이 때 루프 본체의 긴 코드를 while문 앞에 한 번 더 써줘야 한다. 함수로 빼기에도 두 번 밖에 안 쓰기 때문에 애매하다. 이 때 사용하면 좋다. 그 외에는 굳이 사용할 필요는 없을 것 같다. 파이썬에는 없는 C만의 문법이다. 아래는 앞선 while문의 예시1을 do-while로 똑같이 구현한 것이다.
#include <stdio.h>
int main(void)
{
int i = 1; // 제어 변수(초기식)
do {
printf("%d ", i);
++i; // 증감
} while (i <= 10); // 조건식
return 0;
}
조건식이 마지막에 나오고, 세미콜론이 끝에 붙는다는 것을 주의하자.