C언어 이론 정리 - 04

Lee Pil Ung·2021년 12월 5일
0

C

목록 보기
4/6
post-thumbnail

📖 C언어 이론 정리 - 04

C언어 이론 정리 파트 04
자료 참조 : TCP School.com

- 제어문

제어문(control flow statements)

C 프로그램은 절차적 프로그램(procedural program) 또는 명령형 프로그램(Impretative program)에 속한다.

C 프로그램에는 수많은 명령문이 포함되어 있으며, 이 명령문은 처음부터 끝까지 순서대로 실행된다.

따라서 원하는 결과를 얻기 위해서는 프로그램의 이러한 순차적인 흐름을 제어해야만 한다.

이때 사용하는 명령문을 제어문이라고 하며, 이러한 제어문에는 조건문, 반복문 등이 있다.

이러한 제어문에 속하는 명령문들은 중괄호{}로 둘러싸여 있으며, 이러한 중괄호 영역을 블록(block)이라고 한다.

- 조건문(conditional statements)

조건문은 주어진 조건식의 결과에 따라 별도의 명령을 수행하도록 제어하는 명령문이다.

조건문 중에서도 가장 기본이 되는 명령문은 바로 if 문이다.

C언어에서 사용하는 대표적인 조건문의 형태는 다음과 같다.

  1. if 문

  2. if / else 문

  3. if / else if / else 문

  4. switch 문

if문

if 문은 조건식의 결과가 참(true)이면 주어진 명령문을 실행하며, 거짓(false)이면 아무것도 실행하지 않는다.

if 문을 순서도로 표현하면 다음 그림과 같다.

C언어에서 if 문의 문법은 다음과 같다.

✅ 문법

if (조건식)

{
    조건식의 결과가 참일 때 실행하고자 하는 명령문;
}

위의 코드에서 블록에 속한 명령문은 중괄호({})를 기준으로 오른쪽으로 들여쓰기가 되어 있는 것을 볼 수 있다.

📝 예제

int num = 3;

if (num < 5)
{
    printf("입력하신 수는 5보다 작습니다.\n");
}
if (num == 5)
{
    printf("입력하신 수는 5입니다.\n");
}
if (num > 5)
{
    printf("입력하신 수는 5보다 큽니다.\n");
}
// 실행 결과
입력하신 수는 5보다 작습니다.

if 문을 3번 연속해서 사용하여, 사용자가 입력한 수와 숫자 5를 비교하여 그 결괏값을 출력하는 예제이다.

🚩 if 문에서 실행될 명령문이 한 줄 뿐이라면 중괄호({})를 생략할 수 있다.

if / else 문

if 문과 함께 사용하는 else 문은 if 문과는 반대로 주어진 조건식의 결과가 거짓(false)이면 주어진 명령문을 실행한다.

if / else 문을 순서도로 표현하면 다음 그림과 같다.

✅ 문법

if (조건식)
{
    조건식의 결과가 참일 때 실행하고자 하는 명령문;
}
else
{
    조건식의 결과가 거짓일 때 실행하고자 하는 명령문;
}

📝 예제

else 문을 사용하면 앞선 if문의 예제를 좀 더 직관적으로 표현할 수 있다.

#include <stdio.h>

int main()
{
  int num = 5;

  if (num < 5)
  {
      printf("입력하신 수는 5보다 작습니다.\n");
  }
  else
  {
      if (num == 5)
      {
          printf("입력하신 수는 5입니다.\n");
      }
      else
      {
          printf("입력하신 수는 5보다 큽니다.\n");
      }
  }
}
// 실행 결과
입력하신 수는 5입니다.
  • 🚩 else 문에서도 실행될 명령문이 한 줄뿐이라면 중괄호({})를 생략할 수 있다.

if / else if / else 문

else if 문은 if 문처럼 조건식을 가질 수 있기 때문에 중첩된 if 문을 좀 더 간결하게 표현할 수 있도록 해준다.

하나의 조건문 안에서 if 문과 else 문은 단 한 번만 사용될 수 있다.

하지만 else if 문은 여러 번 사용될 수 있어서 복잡한 조건도 표현할 수 있다.

if / else if / else 문을 순서도로 표현하면 다음 그림과 같다.

✅ 문법

if (조건식1)
{
    조건식1의 결과가 참일 때 실행하고자 하는 명령문;
}
else if (조건식2)
{
    조건식2의 결과가 참일 때 실행하고자 하는 명령문;
}
else
{
    조건식1의 결과도 거짓이고, 조건식2의 결과도 거짓일 때 실행하고자 하는 명령문;
}

📝 예제

else if 문을 사용하면 앞선 if else 예제를 더욱 간결하게 표현할 수 있다.

#include <stdio.h>

int main()
{
  int num = 7;

  if (num < 5)
  {
      printf("입력하신 수는 5보다 작습니다.\n");
  }
  else if (num == 5)
  {
      printf("입력하신 수는 5입니다.\n");
  }
  else
  {
      printf("입력하신 수는 5보다 큽니다.\n");
  }
}
// 실행 결과
입력하신 수는 5보다 큽니다.
  • 🚩 else if 문에서도 실행될 명령문이 한 줄뿐이라면 중괄호({})를 생략할 수 있다.

삼항 연산자에 의한 조건문

C언어에서는 if / else 문을 앞서 배운 삼항 연산자를 이용하여 간단히 표현할 수 있다.

switch 문

switch 문은 if / else 문과 마찬가지로 주어진 조건 값의 결과에 따라 프로그램이 다른 명령을 수행하도록 하는 조건문이다.

이러한 switch 문은 if / else 문보다 가독성이 더 좋으며, 컴파일러가 최적화를 쉽게 할 수 있어 속도 또한 빠른 편이다.

하지만 switch 문의 조건 값으로는 int형으로 승격할 수 있는(integer promotion) 값만이 사용될 수 있다.

즉, C언어에서는 char형, short형, int형 변수리터럴과 나중에 배우게 될 열거체까지 사용할 수 있다.

따라서 if / else 문보다는 사용할 수 있는 상황이 적은 편이다.

✅ 문법

switch (조건 값)

{
    case1:
        조건 값이 값1일 때 실행하고자 하는 명령문;
        break;
    case2:
        조건 값이 값2일 때 실행하고자 하는 명령문;
        break;
    ...
    default:
        조건 값이 어떠한 case 절에도 해당하지 않을 때 실행하고자 하는 명령문;
        break;
}

default 절은 조건 값이 위에 나열된 어떠한 case 절에도 해당하지 않을 때 실행된다.

이 구문은 반드시 존재해야 하는 것은 아니며 필요할 때에만 선언할 수 있다.

  • 🚩 default 절의 위치가 반드시 switch 문의 맨 마지막일 필요는 없다.

📝 예제

#include <stdio.h>

int main()
{
  int num = 2;

  switch (num)
  {
      case 1:
          printf("입력하신 수는 1입니다.\n");
          break;
      case 2:
          printf("입력하신 수는 2입니다.\n");
          break;
      case 3:
          printf("입력하신 수는 3입니다.\n");
          break;
      case 4:
          printf("입력하신 수는 4입니다.\n");
          break;
      case 5:
          printf("입력하신 수는 5입니다.\n");
          break;
      default:
          printf("1부터 5까지의 수만 입력해 주세요!");
          break;
  }
}
// 실행 결과
입력하신 수는 2입니다.

각 case 절 및 default 절은 반드시 break 키워드를 포함하고 있어야 한다.

break 키워드는 조건 값에 해당하는 case 절이나 default 절이 실행된 뒤에 전체 switch 문을 빠져나가게 해준다.

만약에 break 키워드가 없다면, 조건에 해당하는 switch 문의 case 절 이후의 모든 case 절이 전부 실행될 것이다.

📝 예제

다음 예제는 앞서 살펴본 예제에서 break 키워드를 모두 삭제한 예제이다.

#include <stdio.h>

int main()
{
  int num = 2;
  switch (num)
  {
      case 1:
          printf("입력하신 수는 1입니다.\n");
      case 2:
          printf("입력하신 수는 2입니다.\n");
      case 3:
          printf("입력하신 수는 3입니다.\n");
      case 4:
          printf("입력하신 수는 4입니다.\n");
      case 5:
          printf("입력하신 수는 5입니다.\n");
      default:
          printf("1부터 5까지의 수만 입력해 주세요!");
  }
}
// 실행 결과
입력하신 수는 2입니다.
입력하신 수는 3입니다.
입력하신 수는 4입니다.
입력하신 수는 5입니다.
1부터 5까지의 수만 입력해 주세요!

위의 예제처럼 break 키워드가 없으면, 조건 값에 해당하는 case 절뿐만 아니라 그 이후에 등장하는 모든 case 절과 default 절이 전부 실행됨을 알 수 있다.

다음 예제는 조건 값으로 여러 개의 char형 문자를 검사하는 예제이다.

#include <stdio.h>

int main()
{
  char ch = 'a';
  switch (ch)
  {
      case 'a':
      case 'A':
          printf("이 학생의 학점은 A입니다.\n");
          break;
      case 'b':
      case 'B':
          printf("이 학생의 학점은 B입니다.\n");
          break;
      case 'c':
      case 'C':
          printf("이 학생의 학점은 C입니다.\n");
          break;
      case 'd':
      case 'D':
          printf("이 학생의 학점은 D입니다.\n");
          break;
      case 'f':
      case 'F':
          printf("이 학생의 학점은 F입니다.\n");
          break;
      default:
          printf("학점을 정확히 입력해 주세요!(A, B, C, D, F)");
          break;
  }
}
// 실행 결과
이 학생의 학점은 A입니다.

- 반복문(iteration statements)

반복문이란 프로그램 내에서 똑같은 명령을 일정 횟수만큼 반복하여 수행하도록 제어하는 명령문이다.

프로그램이 처리하는 대부분의 코드는 반복적인 형태가 많으므로, 가장 많이 사용되는 제어문 중 하나이다.

C언어에서 사용되는 대표적인 반복문의 형태는 다음과 같다.

  1. while 문

  2. do / while 문

  3. for 문

while문

while 문은 특정 조건을 만족할 때까지 계속해서 주어진 명령문을 반복 실행한다.

C언어에서 while 문의 문법은 다음과 같다.

✅ 문법

while (조건식)

{
    조건식의 결과가 참인 동안 반복적으로 실행하고자 하는 명령문;
}

while 문은 우선 조건식이 참(true)인지를 판단하여, 참이면 내부의 명령문을 실행한다.

이렇게 내부의 명령문을 전부 실행하고 나면, 다시 조건식으로 돌아와 또 한 번 참인지를 판단하게 된다.

이렇게 표현식의 검사를 통해 반복해서 실행되는 반복문을 루프(loop)라고 한다.

#include <stdio.h>

int main()
{
  int i = 0;
  int num = 5;

  while (i < num)
  {
      printf("while 문이 %d 번째 반복 수행중입니다.\n", i + 1);
      i++; // 이 부분을 삭제하면 무한 루프에 빠지게 됨
  }
  printf("while 문이 종료된 후 변수 i의 값은 %d입니다.\n", i);
}
// 실행 결과
while 문이 1 번째 반복 수행중입니다.
while 문이 2 번째 반복 수행중입니다.
while 문이 3 번째 반복 수행중입니다.
while 문이 4 번째 반복 수행중입니다.
while 문이 5 번째 반복 수행중입니다.
while 문이 종료된 후 변수 i의 값은 5입니다.

while 문 내부에 조건식의 결과를 변경하는 명령문이 존재하지 않을 때는 프로그램이 영원히 반복되게 된다.

이것을 무한 루프(infinite loop)에 빠졌다고 한다.

반복문에서는 조건식이 거짓일 때 반복문이 종료 되지만, 무한루프는 조건식이 항상 참이기 때문에 반복문이 종료되지 않고 무한히 실행되는 반복문을 의미한다. 무한 루프에 빠진 프로그램은 영원히 종료되지 않는다.

무한 루프는 특별히 의도한 경우가 아니라면 반드시 피해야 하는 상황이다.

따라서 while 문을 작성할 때는 조건식의 결과가 어느 순간 거짓(false)을 갖도록 조건식의 결과를 변경하는 명령문을 반드시 포함시켜야 한다.

위의 예제에서 조건식의 결과를 변경하는 명령문인 i++를 제거하면, 변수 i의 값은 언제나 0이기 때문에 무한 루프에 빠지게 된다.

do / while문

while 문은 루프에 진입하기 전에 먼저 조건식부터 검사한다.

하지만 do / while 문은 먼저 루프를 한 번 실행한 후에 조건식을 검사한다.

즉, do / while 문은 조건식의 결과와 상관없이 무조건 한 번은 루프를 실행한다.

✅ 문법

do {
    조건식의 결과가 참인 동안 반복적으로 실행하고자 하는 명령문;
} while (조건식);

📝 예제

#include <stdio.h>

int main()
{
  int i = 0;
  int num = 3;

  do {
      printf("do / while 문이 %d 번째 반복 수행중입니다.\n", i + 1);
      i++;
  } while (i > num);

  printf("do / while 문이 종료된 후 변수 i의 값은 %d입니다.\n", i);
}
// 실행 결과
do / while 문이 1 번째 반복 수행중입니다.
while 문이 종료된 후 변수 i의 값은 1입니다.

위의 예제가 만약 while 문이었다면 단 한 번의 출력도 없었을 것이다.

하지만 do / while 문은 조건식의 결과와 상관없이 무조건 한 번은 루프를 실행해 준다.

for 문

for 문은 while 문과는 달리 자체적으로 초기식, 조건식, 증감식을 모두 포함하고 있는 반복문이다.

따라서 while 문보다는 좀 더 간결하게 반복문을 표현할 수 있다.

✅ 문법

for (초기식; 조건식; 증감식)
{
    조건식의 결과가 참인 동안 반복적으로 실행하고자 하는 명령문;
}

이때 for 문을 구성하는 초기식, 조건식, 증감식은 각각 생략될 수 있다.

for 문을 사용하면 앞선 예제의 while 문을 더욱 더 간결하게 표현할 수 있다.

📝 예제

#include <stdio.h>

int main()
{
  int i;
  int num = 7;

  for (i = 0; i < num; i++)
  {
      printf("for 문이 %d 번째 반복 수행중입니다.\n", i + 1);
  }
  printf("for 문이 종료된 후 변수 i의 값은 %d입니다.\n", i);
}
// 실행 결과
for 문이 1 번째 반복 수행중입니다.
for 문이 2 번째 반복 수행중입니다.
for 문이 3 번째 반복 수행중입니다.
for 문이 4 번째 반복 수행중입니다.
for 문이 5 번째 반복 수행중입니다.
for 문이 6 번째 반복 수행중입니다.
for 문이 7 번째 반복 수행중입니다.
for 문이 종료된 후 변수 i의 값은 7입니다.

기타 제어문

루프의 제어

일반적으로 조건식의 검사를 통해 루프로 진입하면, 다음 조건식을 검사하기 전까지 루프 안에 있는 모든 명령문을 실행한다.

하지만 continue문break문은 이러한 일반적인 루프의 흐름을 사용자가 직접 제어할 수 있도록 해준다.

continue 문

continue 문은 루프 내에서 사용하여 해당 루프의 나머지 부분을 건너뛰고, 바로 다음 조건식의 판단으로 넘어가게 한다.

보통 반복문 내에서 특정 조건에 대한 예외 처리를 하고자 할 때 자주 사용된다.

📝 예제

다음 예제는 1부터 100까지의 정수 중에서 3의 배수를 제외하고 출력하는 예제이다.

#include <stdio.h>

int main()
{
  int i;
  int except_num = 3;

  for (i = 1; i <= 100; i++)
  {
      if (i % except_num == 0)
      {
          continue;
      }
      printf("%d ", i);
  }
}
// 실행 결과
1
2
4
5
7
...
97
98
100

위 예제의 출력이 저러한 형태를 가지는 것은 변수 i의 값이 3의 배수인 경우에는 continue 문을 이용하여 for 문의 printf() 함수 부분을 건너뛰고 있기 때문이다.

break문

break 문은 루프 내에서 사용하여 해당 반복문을 완전히 종료시킨 뒤, 반복문 바로 다음에 위치한 명령문을 실행한다.

즉 루프 내에서 조건식의 판단 결과에 상관없이 반복문을 완전히 빠져나가고 싶을 때 사용한다.

📝 예제

구구단에서 5단까지 각 단의 수만큼만 출력하는 예제이다.

#include <stdio.h>

int main()
{
  int i, j;

  for (i = 2; i <= 5; i++)
  {
      for (j = 1; j <= 9; j++)
      {
          printf("%d * %d = %d\n", i, j, i * j);
          if (i == j)
          {
              printf("\n");
              break;
          }
      }
  }
}
// 실행 결과
2 * 1 = 2
2 * 2 = 4

3 * 1 = 3
3 * 2 = 6
3 * 3 = 9

4 * 1 = 4
4 * 2 = 8
4 * 3 = 12
4 * 4 = 16

5 * 1 = 5
5 * 2 = 10
5 * 3 = 15
5 * 4 = 20
5 * 5 = 25

위의 예제는 두 개의 for 문을 중첩해서 사용하여 구구단을 출력하고 있다.

이때 내부의 for 문은 변수 i와 j의 값이 같아지면, break 문을 호출하여 내부의 for 문을 빠져나간다.

따라서 구구단의 각 단이 해당 단의 수만큼만 출력될 수 있다.

goto 문

goto 문은 프로그램의 흐름을 지정된 레이블(label)로 무조건 변경시키는 명령문이다.

goto 문은 다른 제어문과는 달리 아무런 조건 없이 프로그램의 흐름을 옮겨준다.

따라서 가장 손쉽게 사용할 수 있지만, 반면에 프로그램의 흐름을 매우 복잡하게 만들기도 한다.

이러한 단점 때문에 현재는 디버깅 이외에는 거의 사용되지 않는다.

profile
Frontend SoftWare Engineer(2022.06.27 ~)

0개의 댓글