드디어 루프다. 루프는 반복문으로써 반복해서 입력할 일이 많을 때 사용한다. 그중 for 루프를 먼저 보자.
for (int i = 0; i < 5; i++)
cout << "for 반복문" << endl;
실행 결과.
형식은 for(초기화; 조건 검사; 갱신)하고 밑에다가 반복해서 작업할 코드를 입력한다. 한 문장을 쓰면 위와 같이 쓰면 되지만, 여러 줄이라면 코드 블럭({})을 통해 구분해주어야 한다.
for 문에 컴파일러가 입장하면 먼저 초기화식을 거치고, 조건 검사를 한다. (위의 구문에서 초기화한 변수 i는 for문 내에서 선언이 되었기 때문에 for문이 끝나면 사라진다.) 그리고 만약 조건 검사가 참이라면, 루프 몸체라고 부르는 그 밑 구문 or 코드 블럭을 실행한다. 그 후 갱신을 한다. 그 후에는 초기화를 거치지 않고 조건 검사 → 코드 실행 → 갱신만 반복하다가 조건 검사가 거짓이라면, for 구문을 빠져 나온다.
이 구문에서 갱신 부분에 증가 연산자(++)가 사용되었다. i++는, i = i + 1와 같다. 그러니까 i에 1 더하라는 것이다. 반대로 --는 감소연산자로서, i--는 i = i - 1, 즉 i에 1 빼라는 것이다. 반드시 이런 것만 쓰는 게 아니라 다른 어떤 코드도 가능하다. 가령 이런식으로도 가능하다.
int by = 5;
for (int i = 0; i < 100; i = i + by)
cout << i << endl;
int a = 10;
int b = 20;
cout << "a = " << a << ": b = " << b << endl;
cout << "a++ = " << a++ << ": ++b = " << ++b << endl;
cout << "a = " << a << ": b = " << b << endl;
실행 결과.
잘 보면 a, b 둘 다 결국 1이 더해졌지만, 접두어 방식이 먼저 더해진 것을 알 수 있다.
그럼 다음 두 코드에는 어떤 차이점이 있을까? 평소 궁금했던 건데...
for (n = lim; n > 0; --n)
...
for (n = lim; n > 0; n--)
...
답은 별 차이가 없다! 부수 효과의 차이가 있긴 하다는데, 그렇게 중요한 건 아닌 것 같다.
참고로 증가 / 감소 연산자는 포인터에도 사용 가능하다.
위에서 예시로 들었던 i = i + by는 '조합 대입 연산자'라고 부른다. 이 구문은 좀 더 간단하게 쓸 수 있다.
i += by
여러 가지 조합 대입 연산자는 다음과 같다.
연산자 | 효과(L은 왼쪽 피연산자, R은 오른쪽 피연산자) |
---|---|
+= | L+R를 L에 대입한다 |
-= | L-R를 L에 대입한다 |
*= | L*R를 L에 대입한다 |
/= | L/R를 L에 대입한다 |
%= | L%R를 L에 대입한다 |
비슷하게 '관계 표현식'이라고 해서 수학시간에 배운 부등호 비교가 있다. 정리하면 다음과 같다.
연산자 | 의미 |
---|---|
< | 작다 |
<= | 작거나 같다 |
== | 같다 |
> | 크다 |
>= | 크거나 같다 |
!= | 같지 않다 |
(※ '='와 '=='를 헷갈리지 않도록 주의하자!!)
이 표현식을 거치면 true or false로 나오기 때문에 루프의 조건 검사 표현식으로 쓰기 딱 알맞다. 다음과 같이 말이다.
for (x = 20; x > 5; x--)
for (x = 1; y != x; ++x)
for (cin >> x; x == 0; cin >> x)
관계 연산자는 산술 연산자보다 우선순위가 낮기 때문에 다음 코드에서 표현식1은 표현식3이 아니라 표현식2와 같다.
x + 3 > y - 2 // 표현식1.
(x + 3) > (y - 2) // 표현식2.
x + (3 > y) - 2 // 표현식3.
또한 콤마 연산자라고 해서 여러 구문을 동시에 나타낼 수 있다. 가령 다음과 같은 것이다.
int i = 10;
int j = 0;
for (int k = 0; i > 5; i--, j++)
{
cout << "i의 값 : " << i;
cout << " j의 값 : " << j << endl;
}
실행 결과.
i와 j가 동시에 변한다.
조건 검사 부분에는 참 거짓을 판단하는 어떤 코드도 가능하다. 가령 다음과 같은 코드도 가능하다.
int i;
for (i = 5; i; i--)
cout << "i의 값 : " << i << endl;
cout << "i의 값이 " << i << "이므로 for문 종료.";
실행 결과.
그러니까 i가 0일 때는 실행되지 않고, for문을 나온 것이다. 왜냐하면 참 거짓 구문에서는 오직 0 만이 false로 간주되기 때문이다.
for문 코드 블록 안에서 선언된 변수는 그 밖에서는 사용할 수 없다. 그럼 만약 다음과 같은 코드는 어떨까?
int x = 10;
for (int i = 0; i < 5; i++)
{
int x = 5;
cout << "x의 값 : " << x << endl;
}
cout << "x의 값 : " << x << endl;
for문 전에 선언된 변수는, for문 밖으로 나와야 비로소 적용이 된다. 하지만 이렇게 쓰는 코드는 가독성이 안 좋을 것 같다.