6장
키워드 : C의 세 가지 루프 구조 for, while, do while
함수: fabs()
리턴값이 있는 함수 만들기
연산자 : < > <= >= != == += *= -= /= %=
관계 연산자를 사용하여 루프 제어 표현식 만들기
루프와 함께 사용하는 배열
C의 세 가지 루프 구조
C에는 총 세 가지 반복문이 있다. while문, do문, for문이다.
for문은 루프가 특정 변수를 증감시킬 때 사용하기 유용하다.
while문은 루프 본문 이전에 제어식이 평가되는 루프에 사용한다.
do문은 반대로 루프 본문이 실행이 된 다음 제어식이 평가되는 루프에 사용한다.
for
for 반복문으로 Hello, world! 100번 출력하기
#include <stdio.h>
int main()
{
for (int i = 0; i < 100; i++) // 0부터 99까지 증가하면서 100번 반복
{
printf("Hello, world!\n");
}
return 0;
}
... (생략)
Hello, world!
Hello, world!
Hello, world!
Hello, world!
for 반복문의 기본 형태
for 반복문의 괄호에 초기식, 조건식, 변화식을 지정하였고, 중괄호 안에 반복할 코드를 입력한다.
- 반복문이 처음 시작되면 i에 0이 들어가고, i가 100보다 작은지 검사한다.
- 0은 100보다 작으므로 중괄호 안의 코드를 실행한다.
- 그리고 i++를 실행하여 i를 1 증가시킨다.
- 다시 i가 100보다 작은지 검사한 뒤 i가 100보다 작으면 중괄호 안의 코드를 실행한다.
- 이 과정을 반복하다가 i가 100이 되면 i < 100 조건식이 거짓이 되므로 반복문을 종료한다.
- 초기식 int i = 0
- 반복문을 시작할 때 초기식이다. 보통 정수형 변수를 선언한 뒤 0을 할당한다.
- 이 변수를 루프 인덱스라고도 부르며 index의 첫 머리글자를 따서 i를 주로 사용한다.
- 반복에 사용할 변수는 초기식 부분에서 선언해도 되고, for 반복문 바깥에서 선언해도 된. - 조건식 i < 100
- 반복될 조건이다.
- 조건식이 참이면 계속 반복하며, 거짓이 되면 반복문을 끝낸다. - 변화식 i++
- 반복문이 한 번 실행될 때마다 수행할 식이다.
- 보통 증가 연산자 ++를 사용하여 변수의 값을 1씩 증가시킨다.
- for 반복문은 반복 횟수가 정해져 있을 때 유용하다.
초기식에서 변수 선언
초기식에서 변수를 선언(loop initial declaration)하는 것은 C99 방식이다.
- C99 방식은 코드를 간결하게 만드는 장점이 있다. 단, 변수를 루프 본체 안에서만 사용할 수 있고, 바깥에서는 사용할 수 없다.
for (int i = 0; i < 100; i++) // for 반복문 초기식에서 변수를 선언. C99 방식
{
printf("Hello, world!\n");
}
printf("%d\n", i); // 컴파일 에러: i는 for 반복문 바깥에서 사용할 수 없음
for 반복문과 세미콜론(;)
for 반복문은 if 조건문과 마찬가지로 끝에 ; (세미콜론)을 붙이면 안된다.
#include <stdio.h>
int main()
{
for (int i = 0; i < 100; i++); // for 루프 선언문 끝에 세미콜론을 붙이면 안됨
{
printf("Hello, world!\n");
}
return 0;
}
Hello, world!
- 이렇게 되면 for와 printf는 관계가 없이 떨어진 상태가 되어 반복이 되지 않고 한 번만 실행된다.
for 반복문 끝에 세미콜론을 붙이게 되면 실제로는 다음과 같은 코드가 된다. 반복할 문장이 없는 것이다.
for (int i = 0; i < 100; i++);
printf("Hello, world!\n");
for 반복문에서 중괄호 생략하기
for 반복문으로 반복할 코드가 한 줄이라면 다음과 같이 중괄호는 생략할 수 있다.
#include <stdio.h>
int main()
{
for (int i = 0; i < 100; i++)
printf("Hello, world!\n"); // 반복할 코드가 한 줄이라면 중괄호 생략
return 0;
}
... (생략)
Hello, world!
Hello, world!
Hello, world!
Hello, world!
중괄호를 생략해도 결과는 똑같다. 단, for에서 반복할 코드가 두 줄 이상일 때는 중괄호 생략에 주의해야 한다.
#include <stdio.h>
int main()
{
for (int i = 0; i < 100; i++)
printf("for 반복문\n"); // 이 줄만 반복됨
printf("Hello, world!\n"); // 이 줄은 한 번만 실행됨
return 0;
}
.... (생략)
for 반복문
for 반복문
for 반복문
for 반복문
Hello, world!
- for로 반복할 printf가 두 개인데도 중괄호를 생략하면 첫 번째 printf만 반복된다. 즉, 첫 번째 printf가 100번 반복된 뒤에 두 번째 printf가 실행되어 Hello, world!는 한 번만 출력된다
for로 반복할 코드가 두 줄 이상이라면 반드시 중괄호로 묶어줘야한다.
#include <stdio.h>
int main()
{
for (int i = 0; i < 100; i++)
printf("Hello, world!\n"); // 반복할 코드가 한 줄이라면 중괄호 생략
for (int i = 0; i < 100; i++)
{ // 반복할 코드가 두 줄 이상이라면 중괄호로 묶어줌
printf("for 반복문\n");
printf("Hello, world!\n");
}
return 0;
}
즉, 루프 본체가 한 줄이면 중괄호를 생략할 수 있고, 루프 본체가 두 줄 이상이라면 반드시 중괄호를 사용해야 한다.
입력한 횟수대로 반복하기
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
int main()
{
int count;
scanf("%d", &count); // 값을 입력받음
for (int i = 0; i < count; i++) // 0부터 입력받은 값보다 작을 때까지 반복
{
printf("Hello, world! %d\n", i);
}
return 0;
}
5 (입력)
Hello, world! 0
Hello, world! 1
Hello, world! 2
Hello, world! 3
Hello, world! 4
- scanf함수로 입력 값을 받아서 count 변수에 저장했다. 그리고 for 반복문의 조건식에서 i < count와 같이 지정하여 count에 들어있는 값보다 작을 때까지 반복한다. 여기서는 5를 입력했으므로 Hello, world!는 5번만 출력된다.
이번에는 초기값을 받은 뒤 초기값만큼 출력한다.
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
int main()
{
int count;
scanf("%d", &count); // 값을 입력받음
for (int i = count; i > 0; i--) // 입력받은 값을 감소시키면서 반복
{
printf("Hello, world! %d\n", i);
}
return 0;
}
5 (입력)
Hello, world! 5
Hello, world! 4
Hello, world! 3
Hello, world! 2
Hello, world! 1
- scanf 함수로 입력 값을 받아서 count 변수에 저장한 뒤 for 반복문의 초기값 부분에서 count를 i에 할당한다. 그리고 조건식은 i > 0, 변화식은 i--로 지정하여 반복문이 실행될 때마다 i를 감소시키고 i가 0이 되면 반복문을 끝내도록 만들었다.
- i를 따로 선언하지 않고, count를 그대로 사용할 수도 있다.
초기식 비우기
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
int main()
{
int count;
scanf("%d", &count); // 값을 입력받음
for (; count > 0; count--) // 초기값 없이 scanf에서 사용한 변수를 감소시켜서 반복
{
printf("Hello, world! %d\n", count);
}
return 0;
}
5 (입력)
Hello, world! 5
Hello, world! 4
Hello, world! 3
Hello, world! 2
Hello, world! 1
- for의 초기식 부분이 비어있다. 즉, for 반복문에 사용할 변수와 초기값이 준비되어 있으면 초기값 부분을 생략할 수 있다. 그리고 조건식과 변화식 모두 count > 0, count--처럼 count 변수를 기준으로 만들면 된다.
사실은 이렇게 초기식 부분에서 scanf 함수를 호출하는 방식으로도 작성할 수 있다.
for (scanf("%d", &count); count > 0; count--)
for 반복문에서 변수 두 개 사용하기
#include <stdio.h>
int main()
{
for (int i = 0, j = 0; i < 10; i++, j += 2) // i는 1씩 증가, j는 2씩 증가
{
printf("i: %d, j: %d\n", i, j);
}
return 0;
}
i: 0, j: 0
i: 1, j: 2
i: 2, j: 4
i: 3, j: 6
i: 4, j: 8
i: 5, j: 10
i: 6, j: 12
i: 7, j: 14
i: 8, j: 16
i: 9, j: 18
- for의 초기식에서 변수를 두 개 선언하고 0으로 초기화한다.
- 그리고 변화식에서 i는 1씩 증가시키고, j는 2씩 증가시킨다.
- 마지막으로 조건식에서는 i가 10보다 작을 때까지 반복하도록 한다.
- 변화식에서는 ++, --뿐만 아니라 +=, -=, *=, /=도 사용할 수 있다. 각 상황에 맞게 연산자를 사용하여 변수의 증가 폭을 조절하고, 변수 여러 개를 제어할 수 있다.
for 반복문으로 무한 루프 만들기
이 코드는 무한 루프라서 프로그램이 종료되지 않는다. for에서 초기값, 조건식, 변화식을 모두 생략하면 무한히 반복하는 무한 루프가 만들어진다. 이 프로그램을 실행한 상태로 두면 Hello, world!는 끝나지 않고 계속 출력된다.
#include <stdio.h>
int main()
{
for (;;) // 초기값, 조건식, 변화식을 모두 생략하면 무한 루프
{
printf("Hello, world!\n");
}
return 0;
}
... (생략)
Hello, world!
Hello, world!
Hello, world!
Hello, world!
...(계속 반복)
while
while 반복문의 동작 과정
- 여기서는 조건식 → 루프 본체 및 변화식 → 조건식으로 순환하는 부분이 루프(loop)이다.
while 반복문 실행 과정
while 반복문은 괄호 안에 조건식만 들어가고, 초기식은 반복문 바깥에 있다.
그리고 중괄호 안에 반복할 코드와 변화식이 함께 들어간다.
초기식
while (조건식) // ← 루프 선언문(loop statement)
{
반복할 코드
변화식
}
// ↑ 루프 본체(loop body) 및 변화식
- 먼저 초기식부터 시작하여 조건식을 판별한다.
- 여기서 조건식이 참이면 반복할 코드와 변화식을 함께 수행한다.
- 그리고 다시 조건식을 판별하여 참이면 코드를 계속 반복하고, 거짓이면 반복문을 끝낸 뒤 다음 코드를 실행한다.
while 반복문으로 Hello, world! 100번 출력하기
#include <stdio.h>
int main()
{
int i = 0;
while (i < 100) // i가 100보다 작을 때 반복. 0에서 99까지 증가하면서 100번 반복
{
printf("Hello, world!\n");
i++; // i를 1씩 증가시킴
}
return 0;
}
... (생략)
Hello, world!
Hello, world!
Hello, world!
Hello, world!
while 반복문의 기본 형태
- 초기식 int i = 0
- 먼저 반복문에 사용할 변수 i를 선언한 뒤 0으로 초기화 한다 - 조건식 i < 100
- 그리고 while에는 조건식만 지정한다.
- 여기서 while 반복문은 반드시 { } (중괄호) 안에 변화식을 지정해야 한다.
- 만약 조건식만 지정하고 중괄호 안에서 변화식을 생략하면 반복이 끝나지 않고 계속 실행(무한 루프)된다. - 변화식 i++
- i < 100과 같이 조건식을 지정하여 i가 100 미만일 때만 반복하고, i가 100이 되면 반복을 끝내도록 한다.
- 중괄호 안에서는 반복할 코드를 작성한 뒤 i++로 i를 1씩 증가시켰으므로 i가 0부터 99까지 증가하면서 100번 반복한다.
초기값을 1부터 시작하기
이번에는 i를 0이 아닌 1로 초기화하여 Hello, world!를 100번 출력한다.
#include <stdio.h>
int main()
{
int i = 1;
while (i <= 100) // i가 100보다 작거나 같을 때 반복.
{ // 1에서 100까지 증가하면서 100번 반복
printf("Hello, world! %d\n", i); // Hello, world!와 i의 값을 함께 출력
i++; // i를 1씩 증가시킴
}
return 0;
}
Hello, world! 1
Hello, world! 2
... (생략)
Hello, world! 98
Hello, world! 99
Hello, world! 100
- i를 1로 초기화했기 때문에 while의 조건식은 i <= 100과 같이 지정한다.
- i가 1부터 100까지 증가하므로 100번만 반복하게 된다. 만약 101이 되면 i <= 100은 거짓이므로 반복문을 끝낸다.
초기값을 감소시키기
초기값을 크게 주고, 변수를 감소시키면서 반복할 수도 있다.
#include <stdio.h>
int main()
{
int i = 100;
while (i > 0) // i가 0보다 클 때 반복. 100부터 1까지 감소하면서 100번 반복
{
printf("Hello, world! %d\n", i); // Hello, world!와 i의 값을 함께 출력
i--; // i를 1씩 감소시킴
}
return 0;
}
Hello, world! 100
Hello, world! 99
... (생략)
Hello, world! 3
Hello, world! 2
Hello, world! 1
- i가 100이고, 변화식에서 i--로 지정하여 반복을 할 때마다 변수를 1씩 감소시킨다.
- 조건식이 i > 0이므로 100에서 1까지 감소시켜서 100번이 된다. 즉, i가 0이되면 반복문을 끝낸다.
while 반복문과 세미콜론
for와 마찬가지로 while도 끝에 세미콜론(;)을 붙이면 안 된다.
#include <stdio.h>
int main()
{
int i = 0;
while (i < 100); // while 루프 선언문 끝에 세미콜론을 붙이면 안됨
{
printf("Hello, world!\n");
i++;
}
return 0;
}
- 이 코드를 컴파일하여 실행해보면 아무것도 출력되지 않는다. 세미콜론을 붙여서 while과 반복할 코드는 관계가 없이 떨어진 상태가 되고, 중괄호 안에 있는 변화식은 전혀 실행되지 않기 때문이다.
- 따라서 while은 끝나지 않는 무한 루프 상태가 되고 이렇게 되면 뒤에 오는 printf는 절대 실행되지 않는다.
while 반복문 끝에 세미콜론을 붙이게 되면 실제로는 다음과 같은 코드가 된다.
while (i < 100);
{
printf("Hello, world!\n");
i++;
}
입력한 횟수대로 반복하기
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
int main()
{
int count;
scanf("%d", &count); // 값을 입력받음
int i = 0;
while (i < count) // i가 count보다 작을 때 반복
{
printf("Hello, world! %d\n", i); // Hello, world!와 i의 값을 함께 출력
i++; // i를 1씩 증가시킴
}
return 0;
}
5 (입력)
Hello, world! 0
Hello, world! 1
Hello, world! 2
Hello, world! 3
Hello, world! 4
- scanf 함수로 입력 값을 받아서 count 변수에 저장한다.
- 그리고 while 반복문의 조건식에서 i < count와 같이 지정하여 count에 들어있는 값만큼 반복한다.
- 여기서는 5를 입력했으므로 Hello, world!는 5번만 출력된다.
초기값을 받은 뒤 초기값만큼 출력하기
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
int main()
{
int count;
scanf("%d", &count); // 값을 입력받음
while (count > 0) // count가 0보다 클 때 반복
{
printf("Hello, world! %d\n", count);
count--; // count를 1씩 감소시킴
}
return 0;
}
5 (입력)
Hello, world! 5
Hello, world! 4
Hello, world! 3
Hello, world! 2
Hello, world! 1
- scanf 함수로 입력 값을 받아서 count 변수에 저장한 뒤 조건식에서 count > 0와 같이 지정하여 count에 들어있는 값만큼 반복하도록 한다.
- 여기서는 i를 선언하지 않고 count를 바로 사용하므로 변화식은 count--로 지정하여 반복문이 실행될 때마다 count를 감소시키고 count가 0이 되면 반복문을 끝낸다.
반복 횟수가 정해지지 않은 경우
지금까지 조건식에서 반복 횟수를 정한 뒤 변수 i를 증가시키거나 감소시켜서 while 반복문을 사용했지만 while 반복문은 반복 횟수가 정해지지 않았을 때, 논리 조건에 따라 반복 여부를 결정할 때 주로 사용한다.
다음은 while 반복문 안에서 무작위로 정수를 생성한 뒤 3이 나오면 반복을 끝내는 프로그램이다.
1. 먼저 무작위로 정수를 생성하려면 srand, rand, time 함수가 필요하다.
- srand: 난수를 발생시킬 초기값인 시드(seed)를 설정한. 보통 현재 시간값을 사용한다.
- rand: 난수를 발생한다.
- time: 정수 형태로 된 현재 시간값을 반환한다.
#include <stdio.h>
#include <stdlib.h> // srand, rand 함수가 선언된 헤더 파일
#include <time.h> // time 함수가 선언된 헤더 파일
int main()
{
srand(time(NULL)); // 현재 시간값으로 시드 설정
int i = 0;
while (i != 3) // 3이 아닐 때 계속 반복
{
i = rand() % 10; // rand 함수를 사용하여 무작위로 정수를 생성한 뒤 10 미만의 숫자로 만듦
printf("%d\n", i);
}
return 0;
}
2
9
9
4
0
3
↑ 무작위 생성이므로 실행할 때마다 달라진다.
2. 현재 시간값으로 시드를 설정한다.
srand(time(NULL)); // 현재 시간값으로 시드 설정
3. 반복 구현
- 이제 while 반복문에서 i != 3과 같이 조건식을 지정하여 3이 아닐 때 계속 반복하도록 한다.
- 그리고 루프 본체에서는 i = rand() % 10;과 같이 무작위로 정수를 생성하여 변수 i에 저장한다.
- 여기서 rand 함수에서 반환된 값의 자리수가 크기 때문에 10으로 나누었을 때 나머지를 구해서 10 미만의 수로 만든다.
int i = 0;
while (i != 3) // 3이 아닐 때 계속 반복
{
i = rand() % 10; // rand 함수를 사용하여 무작위로 정수를 생성한 뒤 10 미만의 숫자로 만듦
printf("%d\n", i);
}
이처럼 while 반복문은 반복 횟수가 정해져 있지 않을 때 유용하다.
while 반복문으로 무한 루프 만들기
while에서 조건식 대신 1을 지정하면 무한히 반복하는 무한 루프가 만들어진다.
따라서 조건식 자체가 없으므로 변화식도 필요 없다.
이 프로그램을 실행한 상태로 두면 Hello, world!는 끝나지 않고 계속 출력된다.
#include <stdio.h>
int main()
{
while (1) // while에 1을 지정하면 무한 루프
{
printf("Hello, world!\n");
}
return 0;
}
... (생략)
Hello, world!
Hello, world!
Hello, world!
Hello, world!
...(계속 반복)
무한 루프를 만들 때 다음과 같이 1대신 bool값인 true를 넣기도 한다.
#include <stdio.h>
#include <stdbool.h> // bool, true, false가 정의된 헤더 파일
int main()
{
while (true) // while에 true를 지정하면 무한 루프
{
printf("Hello, world!\n");
}
return 0;
}
- 여기서는 stdbool.h 헤더 파일을 사용하여 while에 true를 지정한다.
- 1대신 true를 사용해도 동작은 달라지지 않지만 코드의 의도를 명확하게 표현할 수 있어 자주 사용되는 방식이다.
while 반복문에서 중괄호 생략하기
while반복문으로 반복할 코드가 한 줄이라면 다음과 같이 중괄호는 생략할 수 있다.
#include <stdio.h>
int main()
{
while (1)
printf("Hello, world!\n"); // 반복할 코드가 한 줄이라면 중괄호 생략
return 0;
}
... (생략)
Hello, world!
Hello, world!
Hello, world!
Hello, world!
...(계속 반복)
while 반복문은 보통 루프 본체에 변화식이 함께 들어가므로 중괄호를 생략하는 경우는 많지 않다.
do while
while 반복문은 조건식이 만족하지 않으면 반복을 하지 않고 넘어간다. do while은 코드를 최소 한 번은 실행한다.
do while 반복문 실행 과정
do while 반복문은 초기식이 반복문 바깥에 있다.
do로 시작하여 중괄호 안에 반복할 코드와 변화식이 함께 들어가며 중괄호가 끝나는 부분에 조건식을 지정한다.
초기식
do // ↓ 루프 본체(loop body) 및 변화식
{
반복할 코드
변화식
} while (조건식);
// ↑ 루프 선언문(loop statement)
- 먼저 초기식의 값과는 상관 없이 do { } 부분의 코드와 변화식을 무조건 실행한다.
- 그다음 조건식을 판별하여 참이면 코드를 계속 반복하고 거짓이면 반복문을 끝낸 뒤 다음 코드를 실행한다.
do while 반복문의 동작 과정
- 여기서는 루프 본체 및 변화식 → 조건식으로 순환하는 부분이 루프(loop)임
do while 반복문의 기본 형태
- do 다음에 오는 코드는 조건식과 상관없이 무조건 한 번은 실행된다. 따라서 printf가 한 번 실행되고, i++도 실행되어 i가 1 증가한다.
- 이 상태로 조건식에서 i가 100보다 작은지 검사한다. 아직은 i가 100보다 작으므로 계속 반복하다가 i가 100이 되면 i < 100은 거짓이 되므로 반복을 끝낸다.
- do while 반복문도 반드시 { } (중괄호) 안에 변화식을 지정해야 한다.
- 만약 조건식만 지정하고 중괄호 안에서 변화식을 생략하면 반복이 끝나지 않고 계속 실행(무한 루프)되므로 주의해야 한다.
do while 반복문으로 Hello, world! 100번 출력하기
#include <stdio.h>
int main()
{
int i = 0;
do // 처음 한 번은 아래 코드가 실행됨
{
printf("Hello, world! %d\n", i); // Hello, world!와 i의 값을 함께 출력
i++; // i를 1씩 증가시킴
} while (i < 100); // i가 100보다 작을 때 반복. 0부터 99까지 증가하면서 100번 반복
return 0;
}
Hello, world! 0
Hello, world! 1
... (생략)
Hello, world! 97
Hello, world! 98
Hello, world! 99
- 먼저 반복문에 사용할 변수를 선언한 뒤 0으로 초기화한다.
- 그리고 do 아래에 중괄호를 열고 반복할 코드와 변화식을 넣는다.
- 마지막으로 중괄호를 닫은 뒤 while에 조건식을 지정하고 세미콜론을 붙여준다.
do while을 while로만 표현하면 다음과 같다.
#include <stdio.h>
int main()
{
int i = 0;
// do에 해당하는 부분
printf("Hello, world! %d\n", i); // 처음 한 번은 실행
i++; // 처음 한 번은 실행
while (i < 100) // i가 100보다 작을 때 반복. 0부터 99까지 증가하면서 100번 반복
{
printf("Hello, world! %d\n", i); // Hello, world!와 i의 값을 함께 출력
i++; // i를 1씩 증가시킴
}
return 0;
}
Hello, world! 0
Hello, world! 1
... (생략)
Hello, world! 97
Hello, world! 98
Hello, world! 99
- while 반복문을 실행하기 전에 printf로 문자열을 출력하고 i++로 i를 1 증가시킨다.
- 이 부분은 do while에서 처음 한 번은 조건문과 상관없이 실행되는 점과 같다.
- 이처럼 do while은 처음 한 번은 실행해야 하며 그 이후에는 조건에 따라 반복해야 하는 코드를 간단하게 표현할 수 있다.
초기값을 1부터 시작하기
지금까지 초기값을 0으로 사용했다. 이번에는 i를 0이 아닌 1로 초기화하여 "Hello, world!"를 100번 출력한다.
#include <stdio.h>
int main()
{
int i = 1;
do // 처음 한 번은 아래 코드가 실행됨
{
printf("Hello, world! %d\n", i); // Hello, world!와 i의 값을 함께 출력
i++; // i를 1씩 증가시킴
} while (i <= 100); // i가 100보다 작거나 같을 때 반복. 1부터 100까지 증가하면서 100번 반복
return 0;
}
Hello, world! 0
Hello, world! 1
... (생략)
Hello, world! 97
Hello, world! 98
Hello, world! 99
- i를 1로 초기화했기 때문에 while의 조건식은 i <= 100과 같이 지정한다.
- 따라서 i가 1부터 100까지 증가하므로 100번만 반복하게 된다.
- 만약 101이 되면 i <= 100은 거짓이므로 반복문을 종료한다.
초기값을 감소시키기
지금까지 초기값을 증가시키면서 루프를 실행했다. 반대로 초기값을 크게 주고, 변수를 감소시키면서 반복할 수도 있다.
#include <stdio.h>
int main()
{
int i = 100;
do // 처음 한 번은 아래 코드가 실행됨
{
printf("Hello, world! %d\n", i); // Hello, world!와 i의 값을 함께 출력
i--; // i를 1씩 감소시킴
} while (i > 0); // i가 0보다 클 때 반복. 100부터 1까지 감소하면서 100번 반복
return 0;
}
Hello, world! 100
Hello, world! 99
... (생략)
Hello, world! 3
Hello, world! 2
Hello, world! 1
- i가 100이고, 변화식에서 i--로 지정하여 반복을 할 때마다 변수를 1씩 감소시켰다.
- 그리고 조건식이 i > 0이므로 100에서 1까지 감소시켜서 100번이 된다.
- 즉, i가 0이되면 반복문을 끝낸다.
입력한 횟수대로 반복하기
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
int main()
{
int count;
scanf("%d", &count); // 값을 입력받음
int i = 0;
do // 처음 한 번은 아래 코드가 실행됨
{
printf("Hello, world! %d\n", i); // Hello, world!와 i의 값을 함께 출력
i++; // i를 1씩 증가시킴
} while (i < count); // i가 count보다 작을 때 반복
return 0;
}
5 (입력)
Hello, world! 5
Hello, world! 4
Hello, world! 3
Hello, world! 2
Hello, world! 1
- scanf 함수로 입력 값을 받아서 count 변수에 저장했다.
- 그리고 do 다음에 반복할 코드와 변화식을 넣는다.
여기서는 i를 선언하지 않고 count를 바로 사용하므로 변화식은 count--로 지정하여 반복문이 실행될 때마다 count를 감소시킨다. - 마지막으로 while에서 조건식을 count > 0과 같이 지정하여 count에 들어있는 값만큼 반복하도록 한다..
반복 횟수가 정해지지 않은 경우
while 반복문과 마찬가지로 do while 반복문도 반복 횟수가 정해지지 않았을 때 주로 사용한다. 단, while 반복문과는 달리 최소 한 번은 실행된다는 점이 차이가 있다.
다음은 do while 반복문 안에서 무작위로 정수를 생성한 뒤 3이 나오면 반복을 끝낸다.
#include <stdio.h>
#include <stdlib.h> // srand, rand 함수가 선언된 헤더 파일
#include <time.h> // time 함수가 선언된 헤더 파일
int main()
{
srand(time(NULL)); // 현재 시간값으로 시드 설정
int i = 0;
do
{
i = rand() % 10; // rand 함수를 사용하여 무작위로 정수를 생성한 뒤 10 미만의 숫자로 만듦
printf("%d\n", i);
} while (i != 3); // 3이 아닐 때 계속 반복
return 0;
}
1
5
6
3
↑ 무작위 생성이므로 실행할 때마다 달라짐
- do 부분에서 최소 한 번은 무작위로 정수를 생성하여 출력한다. 그다음에 조건식 i != 3에 따라 i가 3이 아니면 계속 반복한다.
do while 반복문으로 무한 루프 만들기
#include <stdio.h>
int main()
{
do
{
printf("Hello, world!\n");
} while (1); // while에 1을 지정하면 무한 루프
return 0;
}
Hello, world!
Hello, world!
Hello, world!
Hello, world!...(계속 반복)
무한 루프를 만들 때 다음과 같이 1대신 bool값인 true를 넣기도 한다.
- do 다음에 반복할 코드를 작성한다.
- while에서 조건식 대신 1을 지정하면 무한히 반복하는 무한 루프가 만들어진다. 마찬가지로 조건식 자체가 없으므로 변화식도 필요 없다.
- stdbool.h를 포함하여 조건식에 1대신 true를 지정해도 된다.
코드를 한 번만 실행하기
do while의 특성을 활용하여 코드를 한 번만 실행할 수도 있다.
#include <stdio.h>
int main()
{
do
{
printf("Hello, world!\n");
} while (0); // while에 0을 지정하면 코드가 한 번만 실행됨
return 0;
}
Hello, world!
- while에서 조건식 대신에 0을 지정하면 do 부분의 코드가 한 번만 실행된다. 조건식이 거짓이므로 반복을 하지 않고 바로 끝내기 때문이다.
- 여기서 do while (0)은 별로 쓸모가 없을 것 같지만 매크로에서 유용하게 사용된다.
지금까지 for, while, do while의 다양한 사용 방법을 알아보았다.
반복문은 프로그래밍에서 비중이 큰 부분이므로 눈에 익혀두는 것이 좋다.
특히 반복문은 반복 조건 지정이 가장 중요하다.
stdbool.h를 포함하여 조건식에 0대신 false를 지정해도 된다.
함수
fabs( )
math.h 변수 타입별 절대값을 구하는 함수별 헤더 파일
변수 타입 | 함수 | 헤더 파일 |
int | abs() | stdlib.h |
long | labs() | stdlib.h |
float | fabs() | math.h |
double | fabs() | math.h |
long double | fabs() | math.h |
fabs( ) 형태
double형 값에 대한 절댓값을 구한다.
실수의 절댓값
원 개념은 '음수와 양수에 관계없이 수직선에서 원점으로부터의 거리로 나타내보자!'이다.
실수의 경우 부호만 알면 쉽게 제거할 수 있다. 따라서 절댓값은 항상 0보다 크거나 같고, 0의 절댓값은 0이다.
return문
형태와 표현식
void 함수가 아닌 함수는 반드시 return문을 통해 구체적으로 어떤 값을 반환할지를 명시해줘야한다. return문은 다음과 같은 형태를 띤다
return expression ;
표현식은 주로 그냥 상수거나 변수이다
return 0;
return status;
물론 이보다 더 복잡한 표현식도 가능하다. 대표적인 예시로 반환문에 자주 사용하는 조건문이 있다
return n >= 0 ? n : 0;
- 위의 구문이 실행되면 표현식 n >= 0 ? n : 0이 우선 평가가 될 것이다.
- 구문은 n의 값이 음수가 아닐 때 n의 값을 반환해줄 것이다, n의 값이 음수라면 0을 반환해준다.
형변환
만약 return문의 표현식의 형이 함수의 반환형과 일치하지 않는다면 표현식은 함수의 반환형으로 암시적 형변환이 된다.
예를 들어 어떤 함수가 int를 반환한다고 선언이 되었으나 return문이 double형 표현식을 포함하고 있다면 표현식의 결과값은 int로 형변환된다
.
반환형이 void인 함수에서 return 표현
(1) return문은 반환형이 void인 함수에서도 사용될 수 있다. 다만, 이 경우 표현식을 작성해주지 않는다
return; /* void 함수에서 반환(종료)한다 */
위와 같은 return문에 표현식을 넣게 되면 컴파일 오류가 발생한다.
(2) 음수 입력변수를 받으면 즉시 반환(종료)하는 함수
void print_int(int number)
{
if (number < 0) {
return;
}
printf("%d\n", number);
}
- 만약 number가 0보다 작다면 print_int는 printf를 호출하지 않고 반환할 것이다.
(3) return문은 void 함수의 마지막에 있을 수 있다
void print_pun(void)
{
printf("지금은 00시 09분 너무 졸려!\n");
return; /* 가능은 한데 굳이 필요 없음 */
}
- 위처럼 return문을 쓰는 것은 효용성이 없다. 어차피 함수는 마지막 구문이 끝나면 자동으로 반환하기 때문이다.
!! 참고 !! 만약 void 함수가 아닌 함수가 본문 마지막에 도달했다면, 즉 return문 실행이 실패했다면, 이때 반환값을 프로그램이 사용해야한다면 프로그램의 결과는 정의되어있지 않은 불능행동이다. 어떤 컴파일러는 void 함수가 아닌 함수에서 반환문 없이 본문 끝에서 "미끄러져서" 종료될 가능성을 찾게되면 "제어가 void 함수가 아닌 함수의 끝에 도달합니다control reaches end of non-void function"이라는 경고문을 출력한다.
조건 표현식
코드 작성 시 특정 조건에 해당하는 행위만 처리하고 싶을 때, 이를 위해서 1(True) 또는 0(False) 으로 결과를 처리하는 관계 연산자(비교 연산자)와 논리 연산자를 알아야 한다.
관계 연산자
종류
연산자 | 의미 |
< | 작다 |
<= | 작거나 같다 |
== | 같다 |
>= | 크거나 같다 |
> | 크다 |
!= | 같지 않다 |
결과
관계 연산자의 결과는 Boolean으로 반환된다.
fun main() {
val num1 = 20
val num2 = 30
println(num1 == num2) // 출력: false (20과 30은 같지 않음)
println(num1 != num2) // 출력: true (20과 30은 다름)
println(num1 > num2) // 출력: false (20은 30보다 작음)
println(num1 >= num2) // 출력: false (20은 30보다 작거나 같지 않음)
println(num1 < num2) // 출력: true (20은 30보다 작음)
println(num1 <= num2) // 출력: true (20은 30보다 작거나 같음)
}
관계 표현식이 포함된 문장 예시
일반적인 사용 예시
while (number < 6)
{
printf("입력한 수가 너무 작다.\n");
scanf("%d", &number);
}
관계 표현식을 문자와 함께 사용할 수 있다.
while (ch != '$')
{
count++;
scanf("%c", &ch);
}
- 이때 ASCII가 아닌 CPU가 직접 해독하고 실행할 수 있는 비트 단위로 쓰인 기계어 문자코드가 사용된다.
- 문자열 비교에는 관계 연산자를 사용할 수 없다. >> 11장
부동소수점 수와 함께 사용할 수 있다.
while (scanf("%f", &num) == 1)
sum = sum + sum;
- 부동소수점 수 비교에는 두 수가 논리적으로는 같을지라도 반올림 오차 때문에 같지 않게 될수 있기 때문에 '<', '>'만 사용하도록 스스로 자제해야 한다.
- math.h 헤더 파일에 선언되어 있는, fabs( )함수를 사용하면 부동소수점 수를 쉽게 검사할 수 있다. 이 함수는 부동소수점 값의 절대값을 리턴한다.
관계 연산자의 우선순위
관계 연산자의 우선순위는 산술 연산자보다 낮으나 대입 연산자보다는 높다.
x > y + 2 → x > (y + 2)
x = y > 2 → x = (y > 2)
- y가 2보다 크면 x에 1이 대입되고, 그렇지 않으면 0이 대입된다.
- 결코 x에 y의 값이 대입되지 않는다.
관계 연산자는 대입 연산자보다 우선순위가 높다.
x_bigger = x > y;
x_bigger = (x > y);
관계 연산자들은 우선순위가 다른 두 그룹으로 분류된다.
우선순위가 높은 그룹 : < <= > >=
우선순위가 낮은 그룹 : == !=
대부분의 다른 연산자들과 마찬가지로, 관계 연산자들도 왼쪽에서 오른쪽으로 결합한다.
ex != wye == zee
(ex != wye) == zee
- 먼저 C는 ex가 wye와 같지 않은지 검사한다. 그 후 1(True) 또는 0(False) 로 주어지는 결과값을 zee의 값과 비교한다.
연산자 우선순위
연산자(아래로 갈수록 낮아진다) | 결합 방향 |
( ) | 왼쪽에서 오른쪽으로 |
- + ++ -- sizeof // 모두 단항연산자 | 오른쪽에서 왼쪽으로 (type) |
* / % | 왼쪽에서 오른쪽으로 |
+ - | 왼쪽에서 오른쪽으로 |
< > <= >= | 왼쪽에서 오른쪽으로 |
== != | 왼쪽에서 오른쪽으로 |
= | 오른쪽에서 왼쪽으로 |
논리 연산자
참과 거짓을 연산하여 다시 참 또는 거짓을 반환한다.
종류
연산자 | 의미 | 설명 |
! | 식이 참이면 거짓, 거짓이면 참 | 논리부정 (NOT) |
&& | 두 식이 모두 참이면 결과는 참 한 식이라도 거짓이면 결과는 거짓 |
논리곱 (AND) |
|| | 한 식이라도 참이면 결과는 참 | 논리합 (OR) |
결과
논리 연산자의 결과는 Boolean으로 반환된다.
#include <stdio.h>
int main(void)
{
int i, j;
printf("숫자1 : ");
scanf("%d", %i);
printf("숫자2 : ");
scanf("%d", %j);
/* 숫자 1 : 1, 숫자 2 : 2 */
print("숫자1 < 숫자2 : %d \n", i<j); // 출력 : 1 (True)
print("숫자1 <= 숫자2 : %d \n", i<=j); // 출력 : 1 (True)
print("숫자1 == 숫자2 : %d \n", i==j); // 출력 : 0 (False)
print("숫자1 > 숫자2 : %d \n", i>j); // 출력 : 0 (False)
print("숫자1 >= 숫자2 : %d \n", i>=j); // 출력 : 0 (False)
}
'C언어 > 스터디' 카테고리의 다른 글
ch09 함수 (0) | 2024.08.10 |
---|---|
ch7 제어문_분기와 점프 (0) | 2024.08.09 |
ch6 제어문_루프 문제 (0) | 2024.08.08 |
ch5 연산자, 표현식, 문장 (0) | 2024.08.07 |
ch4 문자열과 입출력 포맷 (0) | 2024.08.06 |