
반복 제어문을 사용하여 지정된 명령어들을 조건이 만족될 때까지 반복 수행할 수 있다.
주어진 조건이 참인 동안에만 while문 내부를 반복 수행하고, 조건이 거짓이 되는 순간 루프를 빠져나와 반복문 다음에 나오는 명령문을 수행한다.
⌨️ 예제 1
#include <stdio.h>
int main() {
int i = 1; // i 값은 1부터 시작
while(i <= 5) { // i 값이 5일 때까지만 반복
printf("%d\n", i); // 반복 실행 문장(i 값 출력)
i++; // i 값에 1을 더함
}
}
🖥️ 실행 결과
1
2
3
4
5
⌨️ 예제 2
// 예제 1을 while문 대신 goto문을 사용해서 구현 가능
#include <stdio.h>
int main() {
int i = 1;
repeat :
printf("%d\n", i);
if(i < 5) {
i++;
goto repeat;
}
}
🖥️ 실행 결과
1
2
3
4
5
goto문은 안 쓰는 것이 좋기 때문에 참고만 하고 넘어가면 된다.
조건문에 항상 참이 되는 값이 올 경우, 무한히 반복되는 루프가 만들어진다.
⌨️ 예제 3
// 실행하면 1씩 증가하는 숫자를 무한히 출력하게 되는 무한 루프
#include <stdio.h>
#include <stdbool.h>
int main() {
int i = 1;
while(true) { // '참'을 의미하는 true를 조건문에 넣기
printf("%d ", i);
i++;
}
}
🖥️ 실행 결과
1 2 3 4 5 6 7 8 9 10 11 12 ...
끝없이 실행되는 코드는 ctrl + c 로 강제 정지시킬 수 있다.
⌨️ 예제 4
// 숫자 0을 입력할 때까지 무한히 반복 요청하는 프로그램
#include <stdio.h>
int main() {
int n;
while(1) { // 무한 while 루프
printf("숫자 0을 입력해 주세요.\n");
scanf("%d", &n);
if(n == 0) // n의 값이 0이면 while 루프 종료
break; // 루프 밖으로 빠져나가기
}
printf("숫자 0을 입력하셨습니다.\n");
}
🖥️ 실행 결과
숫자 0을 입력해 주세요.
2 [Enter↵]
숫자 0을 입력해 주세요.
67 [Enter↵]
숫자 0을 입력해 주세요.
0 [Enter↵]
숫자 0을 입력하셨습니다.
무한 루프를 필요에 따라 break문과 함께 사용할 수도 있다.
do~while문은 while문과 달리 조건이 아예 만족되지 않더라도 최소한 처음 한 번은 반드시 실행하게 된다는 차이점이 있다. while(조건식)문의 뒤에 세미콜론(;)을 반드시 넣어야 한다. ❗️세미콜론 빠트리면 에러 발생
⌨️ 예제 5
#include <stdio.h>
int main() {
int i = 10; // 조건을 만족하지 않는 값
do { // i 값과 상관없이 무조건 do 안의 내용을 한 번 실행
printf("%d\n", i); // 반복 실행할 문장들
i++;
} while(i <= 5); // 맨 처음 do 안의 내용 실행 후, 조건 확인
}
🖥️ 실행 결과
10
while문이었다면 아예 루프 자체가 실행되지 않아 아무것도 출력되지 않았겠지만, do~while문에서는 반복문이 한 번 실행됐다.
while문 대신 for문을 사용하면 좀 더 편하고 짧게 반복문을 작성할 수 있는 특수한 경우들이 있다.
for문의 괄호 안은 (초기식; 조건식; 증감식)으로 구성되어 있으며, 초기식은 처음 한 번만 수행된다.
❗️초기식과 조건식 뒤 세미콜론(;) 잊지 말기
⌨️ 예제 6
/* 예제 1을 while문 대신 for문으로 완벽하게 대체 가능
<for문 동작 순서>
1. i 값을 1로 초기화
2. 반복 조건 검사(참이면 3번으로, 거짓이면 루프 종료)
3. 반복 문장 실행 후 i에 증감값 계산(+1)
4. 다시 2번으로 돌아가서 실행 */
#include <stdio.h>
int main() {
int i; // 변수 i 선언
for (i = 1; i <= 5; i++) { // for문 동작 순서 참고
printf("%d\n", i); // 반복 실행 문장
}
}
🖥️ 실행 결과
1
2
3
4
5
⌨️ 예제 7
// n보다 같거나 작으면서 2의 거듭제곱인 숫자들만 출력하는 프로그램
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i *= 2) {
printf("%d\n", i);
}
}
🖥️ 실행 결과
15 [Enter↵]
1
2
4
8
이 예제에서는 변수 i의 선언과 초깃값 대입을 for문 안에서 했다.
변수를 for문의 바깥과 안에서 선언하는 것의 차이점은 다음과 같다.
바깥에서 선언 : 해당 for문 뿐 아니라 다른 곳에서도 사용 가능안에서 선언 : 해당 for문 안에서만 사용 가능한 변수가 됨괄호 안의 초기식, 조건식, 증감식을 복수로 넣거나 일부를 생략할 수도 있다. 다만 생략을 하더라도 초기식과 조건식 뒤의 세미콜론(;)은 꼭 써 줘야 한다.
루프의 변수를 for문 앞에서 초기화했다면, 괄호 안에서 생략 가능하다.
int i = 1;
for( ; i <= 5; i++) {
…
괄호 안에서 조건식을 생략하고, 반복문 안에서 if문을 사용하는 것으로 대신할 수 있다. 만약 if문 없이 그냥 조건식을 생략한다면, 조건을 무조건 참이라고 간주하여 무한 루프 구조가 된다.
for(int i = 1; ; i++) {
if(i <= 5)
실행할 문장;
else
break;
…
반복문 안에서 증감식을 수행하는 것이 더 유용할 때가 있다(예를 들어 for문 안의 특정 if문의 조건을 만족했을 때만 증감값을 계산하고 싶을 경우 등).
for(int i = 1; i <= 5; ) {
i = i + 1;
…
괄호 안에 초기식과 증감식을 여러 개 넣는 것도 가능하다.
⌨️ 예제 8
// 1부터 n까지 모든 숫자의 합을 출력하는 프로그램
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int sum = 0;
for(int i = 1; i <= n; i++) {
sum += i;
}
printf("%d\n", sum);
}
🖥️ 실행 결과
100 [Enter↵]
5050
⌨️ 예제 9
// 예제 8에선 변수 i만 괄호 안에 정의됐지만, 예제 9에서는 i와 sum 둘 다 초기식으로 넣었다.
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int i, sum;
for(i = 1, sum = 0; i <= n; sum += i, i++); // 중괄호 안에 아무것도 없어서 세미콜론으로 마무리
printf("%d\n", sum);
}
🖥️ 실행 결과
5 [Enter↵]
15
예제 8에서는 "sum += i;"이 중괄호 안에 있었지만, 예제 9에서는 변수 sum을 초기식으로 설정하면서 "sum += i;"도 증감식으로 함께 괄호 안에 들어왔다. 이 때 두 증감식의 순서를 유의해서 사용해야 한다(sum에 i 값을 더해준 후, i에 1을 더해야 함).
⌨️ 예제 10
// n개만큼 별을 출력하는 프로그램
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
printf("*");
}
printf("\n");
}
🖥️ 실행 결과
8 [Enter↵]
********
⌨️ 예제 11
// 입력한 자연수의 약수를 모두 출력하는 프로그램
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= (n / 2); i++) { // 마지막 숫자 전까지만 쉼표로 나열하기 위해 n ÷ 2
if(n % i == 0) // i가 n의 약수이면, n은 i의 배수
printf("%d, ", i);
}
printf("%d\n", n); // 마지막은 무조건 입력한 수 자기자신이므로 반복문 종료 후 실행
}
🖥️ 실행 결과
12 [Enter↵]
1, 2, 3, 4, 6, 12
⌨️ 예제 12
// 일의자리수가 3, 6, 9인 경우 * 출력하는 369게임
#include <stdio.h>
int main() {
int num;
scanf("%d", &num);
for(int i = 1; i <= num; i++) {
int k = i % 10; // i의 일의 자리수를 변수 k에 저장
if(k == 3 || k == 6 || k == 9)
printf("* ");
else
printf("%d ", i);
}
printf("\n");
}
🖥️ 실행 결과
20 [Enter↵]
1 2 * 4 5 * 7 8 * 10 11 12 * 14 15 * 17 18 * 20
자신이 포함된 반복문 한 개를 강제로 빠져나오는데 사용된다.
⌨️ 예제 13
// 숫자 0을 입력하기 전까지 무한 반복하는 프로그램
#include <stdio.h>
int main() {
for(int i = 1; ; i++) {
int n;
scanf("%d", &n);
if(n == 0) // 0을 입력하는 순간 반복 종료
break;
printf("%d번째 입력 : %d\n", i, n);
}
printf("입력을 종료합니다.\n");
}
🖥️ 실행 결과
6 [Enter↵]
1번째 입력 : 6
33 [Enter↵]
2번째 입력 : 33
0 [Enter↵]
입력을 종료합니다.
루프 실행 도중 해당 루프를 다시 실행해야할 때 사용된다. break문은 루프를 빠져나오지만 continue문은 루프의 남은 부분을 건너뛴 후, 맨 처음으로 실행 순서를 옮겨서 계속 진행한다.
⌨️ 예제 14
// 1부터 n까지 3의 배수를 제외한 숫자들의 합을 구하는 프로그램
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int sum = 0;
for(int i = 1; i <= n; i++) {
if(i % 3 != 0) { // continue문을 사용하지 않을 때 코드
sum += i; // "i ÷ 3"의 나머지가 0이 아닐때만 실행
}
}
printf("%d\n", sum);
}
🖥️ 실행 결과
8 [Enter↵]
27
⌨️ 예제 15
// 예제 14를 continue문을 사용하여 변경
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int sum = 0;
for(int i = 1; i <= n; i++) {
if(i % 3 == 0) { // continue문을 사용할 때 코드
continue; // "i ÷ 3"의 나머지가 0일 때만 루프의 선두로 복귀
}
sum += i; // "i ÷ 3"의 나머지가 0이면 건너뛰어져서 실행 안됨
}
printf("%d\n", sum);
}
🖥️ 실행 결과
4 [Enter↵]
7
for문 안에 for문이 중첩된 구조는 실제로 많이 사용되는 구조다.
⌨️ 예제 16
// 기호 *를 가로 n개 x 세로 n개의 형태로 출력하는 프로그램
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
printf("*");
}
printf("\n"); // 다음 행으로 넘어가기 위해 줄바꿈
}
}
🖥️ 실행 결과
4 [Enter↵]
****
****
****
****
중첩된 for문을 사용할 때는 바깥쪽 for문과 안쪽 for문의 변수명을 다르게 하는 것이 좋다(변수명이 같아도 문법적으로 오류는 없지만 헷갈리기 때문).
⌨️ 예제 17
// 예제 16의 변형. 기호 *를 1개부터 n개까지 n줄에 걸쳐 출력하는 프로그램
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= i; j++) { // "j <= i;"로 변경
printf("*");
}
printf("\n");
}
}
🖥️ 실행 결과
4 [Enter↵]
*
**
***
****
바깥쪽 for문에 연결된 변수 i와 안쪽 for문에 선언된 변수 j는 서로 영향을 주고받을 수 있다.
⌨️ 예제 18
// n개의 *로 이루어진 대각선을 출력하는 프로그램
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
// 왼쪽 위에서 오른쪽 아래로 내려가는 대각선
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if(i == j)
printf("*");
else
printf(" ");
}
printf("\n");
}
// 오른쪽 위에서 왼쪽 아래로 내려가는 대각선
for(int i = 0; i < n; i++) {
for(int j = n-1; j > -1; j--) {
if(i == j)
printf("*");
else
printf(" ");
}
printf("\n");
}
}
🖥️ 실행 결과
4 [Enter↵]
*
*
*
*
*
*
*
*
⌨️ 예제 19
/* 입력한 수 n개만큼 행을 출력,
각 행에는 1부터 시작하는 정수 중 홀수만 작은 순서대로 입력
1번째 행에는 1개, 2번째 행에는 2개를 입력하는 방식 */
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) { // 행 개수를 결정
for(int j = 1; j <= i; j++) { // 열 개수를 결정(1부터 i개 까지)
printf("%d ", 2 * j - 1);
}
printf("\n");
}
}
// 위의 예제 다른 버전
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= (2 * i - 1); j += 2) { // j는 (2 * i - 1)까지, 2씩 증가
printf("%d ", j);
}
printf("\n");
}
}
🖥️ 실행 결과
5 [Enter↵]
1
1 3
1 3 5
1 3 5 7
1 3 5 7 9
⌨️ 예제 20
/* 입력한 수 n개만큼 행을 출력
1번째 행에는 숫자 1을, 2번째 행에는 숫자 1 2 3을,
3번째 행에는 숫자 1 2 3 4 5를 입력하기 */
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= (2 * i - 1); j++) { // i번째 줄에서 출력되는 숫자 개수 조정
printf("%d ", j);
}
printf("\n");
}
}
// 위의 예제 다른 버전
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= (2 * n - 1); i += 2) { // 한 줄당 출력되는 숫자 개수를 변수 i에서 조정
for(int j = 1; j <= i; j++) {
printf("%d ", j);
}
printf("\n");
}
}
🖥️ 실행 결과
5 [Enter↵]
1
1 2 3
1 2 3 4 5
1 2 3 4 5 6 7
1 2 3 4 5 6 7 8 9