티스토리 뷰

 

본 강좌는 아래 동영상 강좌와 같이 진행됩니다. 되도록이면 동영상과 같이 보시는 것을 추천합니다.

 

 

유튜브 채널 가기

 

강좌 9편 동영상 보기

 

 


  

 

 이번시간에는 프로그램 흐름을 제어하는 역할을 하는 제어문에 대해 알아보도록 하겠습니다.

 

 

 

 1. 제어문

 

 제어문은 프로그램의 흐름을 제어하는 역할을 합니다. 크게 네가지를 알아보도록 하겠습니다.

 

 ◆ break문

 break문을 만나면 지금 처리하고 있는 블럭을 빠져나가 블럭 이후의 문장을 처리합니다. 이전 조건문 중 switch문을 알아볼때 한번 나왔는데, 다시한번 살펴보도록 하겠습니다.

 

int a;

 

switch (a)

{

case 1:

printf("1입니다.\n");

break;

 

case 2:

printf("2입니다.\n");

break;

}

 

 위의 코드는 int형 변수 a의 값에 따라, 1이면 '1입니다.'를, 2이면 '2입니다.'를 화면에 출력하는 내용입니다. 이부분에서 지금 알아보고 있는 break문이 두번 쓰였고, 각각 'case 1:'과 'case 2'의 끝에 쓰인것을 알 수 있습니다. 이는 각각의 case문 아래의 내용을 실행한 후 break문을 만나서 switch문 전체를 빠져나가도록 하는 역할을 합니다. 만약

 

 int a = 1;

 

switch (a)

{

case 1:

printf("1입니다.\n");

 

case 2:

printf("2입니다.\n");

break;

}

 

실행 결과

 

1입니다.

2입니다.

 

 이와 같이 break문을 하나 빼면 a가 1이므로 화면에 '1입니다.'를 출력한 후, switch문을 빠져나가지 않고, 그 다음 '2입니다.' 까지 출력하게 됨을 알 수 있습니다. 다른 예를 하나 더 들어보면

 

int a;

 

for (a = 1; a <= 10; a++)

{

if ( a > 5)

break;

 

printf("a = %d\n", a);

}

 

 

실행 결과

 

a = 1

a = 2

a = 3

a = 4

a = 5

 

 for문 안에서 if문을 사용했습니다. 먼저 for문은 a가 1일때부터 10보다 작거나 같을때까지 a를 1씩 증가시키면서 반복작업을 합니다. 그 안의 if문은 만약 a가 5보다 크다면 조건이 만족을 하여 break문을 만나게 되고, 반복문을 빠져나가는 역할을 합니다.

 

 이처럼 break문은 {} 의 블럭으로 이루어진 반복문이나 조건문 중 switch case문 등을 빠져나가는 용도로 많이 사용됩니다.

 

 ◆ continue문

 continue문은 반복문 안에서 사용되며, 이것을 만나면 반복문의 조건을 판단하는 줄로 바로 이동합니다. 예를 들어

 

int a;

 

for (a = 1; a <= 10; a++)

{

if ((a % 2) == 1)

continue;

 

printf("a = %d\n", a);

}

 

실행 결과

 

a = 2;

a = 4;

a = 6;

a = 8;

a = 10;

 

  for문은 위의 break의 예처럼 a가 1부터 10보다 작거나 같을때까지 1씩 증가시키며 반복 작업을 합니다. 그다음 if문은 a를 2로 나누어 나머지가 1일 경우 continue문을 만나서 아래 printf()를 만나지 않고 곧바로 for문으로 돌아가게 됩니다. 그래서 결과는 짝수만 출력이 되게 됩니다.

 

 while문도 동일하게 continue문을 만나면 맨 처음 while문으로 돌아가게 되는데, do while문은 조금 다릅니다.

 

int a = 0;

 

do

{

++a;

 

if ((a % 2) == 1)

continue;

 

printf("a = %d\n", a);

} while (a <= 10);

 

실행 결과

 

a = 2;

a = 4

a = 6

a = 8

a = 10

 

 이전의 for문의 예제와 동일하게 예제를 작성해봤습니다. 여기서 주목해야 할 곳은 continue문을 만나면 어느곳으로 이동하느냐일 것입니다. 맨 처음에 continue문은 반복문의 조건을 판단하는 줄로 이동한다고 했습니다. 여기서는 do로 이동하는 것이 아니라 while();로 이동하게 됩니다.

 

 ◆ return문

  return문은 어느곳에서나 이 구문을 만나면 해당 함수를 빠져나가게 됩니다.

 

void main()

 

}

int a;

 

for (a = 1; a <= 10; a++)

{

if (a > 5)

return;

 

printf("a = %d\n", a);

}

 

printf("---출력 완료---\n");

 

실행 결과

 

a = 1

a = 2

a = 3

a = 4

a = 5 

 

 위의 예제는 a가 5보다 크다면 return문을 만나 main()함수를 빠져나가버립니다. 그래서 반복문 뒤의 printf()를 만나지 않고 프로그램이 종료가 되게 됩니다.

 

 return문은 함수를 다룰 때 좀 더 자세히 알아보겠습니다. 우선은 위와 같이 main()함수를 빠져나가 프로그램이 종료 된다고만 알아두시면 되겠습니다.

 

 ◆ goto문

 goto문은 프로그래머가 지정한 줄로 실행을 이동합니다.

 

int a;

 

for (a = 1; a <= 10; a++)

{

if (a > 5)

goto abc;

 

printf("a = %d\n", a);

 

abc: 

 

실행 결과

 

a = 1

a = 2

a = 3

a = 4

a = 5

 

 위의 예에서는 a가 5보다 클때 goto문을 만나 abc라는 곳으로 이동하게 됩니다. goto문을 쓸때는 반드시 위의 'abc:' 와 같이 '이름표 상수'를 이동하고자 하는 곳에 만들어놓고 이동시키게 됩니다.

 

 goto문은 프로그램의 흐름을 임의로 바꾸는 것이기 때문에 코드를 알아보기 어려우며, 종종 오류발생의 원인이 되기 때문에, 가급적이면 이것을 사용하는 것보다는 자연스레 위에서 아래로 순차적으로 실행이 되고 종료가 되게끔 프로그래밍하는 것이 좋습니다.

 

 

 

 2. 제어문의 적용

 

 이번시간에 알아본 제어문을 사용해서 성적관리 프로그램에 다음과 같은 메뉴를 만들어보도록 하겠습니다.

 

*** 성적관리 프로그램 ***

1. 학생 성적 입력

2. 성적 확인

 

Q. 프로그램 종료

 

작업할 번호를 입력하세요 :

 

 강좌가 진행되면서 메뉴항목을 추가, 변경할 것입니다. 우선 메뉴를 출력하고, 사용자 입력을 받아 봅시다.

 

char menuChoice = ' ';        // 이전 강좌의 endLoop 변수의 이름을 변경

 

do

 

{

// 메뉴 출력

printf("*** 성적관리 프로그램 ***\n");

printf("\n");

printf("1. 학생 성적 입력\n");

printf("2. 성적 확인\n");

printf("\n");

printf("Q. 프로그램 종료\n");

printf("\n");

printf("작업할 번호를 입력하세요 : ");

 

// 메뉴 선택

menuChoice = getchar();

 

...

 

} while (menuChoice != 'Q' && menuChoice != 'q');

 

 지난번에 프로그램을 끝내는 용도로 endLoop라는 변수를 하나 만들었었는데, 이제 메뉴에서 처리할 것이기 때문에 이름이 맞지 않아서 menuChoice라고 변경을 했습니다. 그렇기 때문에 맨 아래 do while 문의 조건에 쓰인 변수명도 변경을 해 줍니다.

 

 이제 메뉴 입력을 받았으니 메뉴 선택에 따른 처리를 해 봅시다. 메뉴 선택에 대한 처리는 switch case문이 가장 적합합니다.

 

// 메뉴 선택

menuChoice = getchar();

 

switch (menuChoice)

{

case '1':

{

}

break;

 

case '2':

{

}

break;

 

case 'Q':

case 'q':

break;

}

 

 프로그램 종료 항목인 'Q'는 어차피 do while문을 빠져나가는 조건이므로 여기서는 별다른 처리를 해줄 필요가 없습니다. 이제 1번 항목의 중괄호 안에 '사용자 입력' 부분을 복사하여 붙여넣습니다.

 

case '1':

{

// 사용자 입력
printf("이름을 입력하세요 : ");

scanf_s("%s", name, sizeof(name));

printf("국어점수를 입력하세요 : ");

scanf_s("%d", &scoreKOR);

printf("수학점수를 입력하세요 : ");

scanf_s("%d", &scoreMAT);

printf("영어점수를 입력하세요 : ");

scanf_s("%d", &scoreENG);

printf("과학점수를 입력하세요 : ");

scanf_s("%d", &scoreSCI);

 

getchar();

printf("평가를 입력하세요 : ");

gets_s(comment, sizeof(comment));

 

}

break;

 

2번 항목도 이전에 만들었던 코드를 복사해서 붙여넣으면 됩니다.

 

case '2':

{

// 총점 계산

scoreTotal = scoreKOR + scoreMAT + scoreENG + scoreSCI;

// 평균 계산

scoreAverage = (float) scoreTotal / 4;

 

// 평균값에 대응하는 등급 구하기

if (scoreAverage >= 90)

grade = 'A';

else if (scoreAverage >= 80)

grade = 'B';

else if (scoreAverage >= 70)

grade = 'C';

else if (scoreAverage >= 60)

grade = 'D';

else

grade = 'F';

 

// 화면 출력

printf("%s의 성적\n", name);

printf("등급 : %c\n", grade);

printf("국어 점수 : %d\n", scoreKOR);

printf("수학 점수 : %d\n", scoreMAT);

printf("영어 점수 : %d\n", scoreENG);

printf("과학 점수 : %d\n", scoreSCI);

printf("총점 : %d\n평균 : %.1f\n", scoreTotal, scoreAverage);

printf("평가 : %s\n", comment);

}

break;

 

 

 이렇게 하고 나니 전시간에 넣은 코드 두줄이 남습니다.

 

printf("\n계속하려면 Enter, 끝내려면 Q키를 눌러주세요\n");

endLoop = getchar();

 

 위에서 언급한대로 프로그램 종료는 메뉴에서 처리하기 때문에 이 두줄은 필요가 없어졌습니다. 주석처리하거나 (/* */로 감싸거나 줄 앞에 // 를 붙입니다.) 삭제해줍니다.

 

 따로따로 설명해 복잡해 보일수도 있으니 지금까지 수정된 소스코드 전체와 비교해봅시다.

 

#include <stdio.h> 

 

void main()

{

char name[20] = "홍길동";   // 이름

char grade = 'B';                 // 등급

int scoreKOR = 80;              // 국어점수

int scoreMAT = 75;              // 수학점수

int scoreENG = 86;              // 영어점수

int scoreSCI = 92;               // 과학점수

char comment[200];        // 평가

 

int scoreTotal = 0;            // 총점

float scoreAverage = 0.0F;       // 평균

 

char menuChoice = ' ';        // 메뉴 선택

 

do

{

// 메뉴 출력

printf("*** 성적관리 프로그램 ***\n");

printf("\n");

printf("1. 학생 성적 입력\n");

printf("2. 성적 확인\n");

printf("\n");

printf("Q. 프로그램 종료\n");

printf("\n");

printf("작업할 번호를 입력하세요 : ");

 

// 메뉴 선택

menuChoice = getchar();

 

switch (menuChoice)

{

case '1':

{

 // 사용자 입력
printf("이름을 입력하세요 : ");

scanf_s("%s", name, sizeof(name));

printf("국어점수를 입력하세요 : ");

scanf_s("%d", &scoreKOR);

printf("수학점수를 입력하세요 : ");

scanf_s("%d", &scoreMAT);

printf("영어점수를 입력하세요 : ");

scanf_s("%d", &scoreENG);

printf("과학점수를 입력하세요 : ");

scanf_s("%d", &scoreSCI);

 

getchar();

printf("평가를 입력하세요 : ");

gets_s(comment, sizeof(comment));

 

}

break;

 

case '2':

{

// 총점 계산

scoreTotal = scoreKOR + scoreMAT + scoreENG + scoreSCI;

// 평균 계산

scoreAverage = (float) scoreTotal / 4;

 

// 평균값에 대응하는 등급 구하기

if (scoreAverage >= 90)

grade = 'A';

else if (scoreAverage >= 80)

grade = 'B';

else if (scoreAverage >= 70)

grade = 'C';

else if (scoreAverage >= 60)

grade = 'D';

else

grade = 'F';

 

// 화면 출력

printf("%s의 성적\n", name);

printf("등급 : %c\n", grade);

printf("국어 점수 : %d\n", scoreKOR);

printf("수학 점수 : %d\n", scoreMAT);

printf("영어 점수 : %d\n", scoreENG);

printf("과학 점수 : %d\n", scoreSCI);

printf("총점 : %d\n평균 : %.1f\n", scoreTotal, scoreAverage);

printf("평가 : %s\n", comment);

}

break;

 

case 'Q':

case 'q':

break;

}

} while (menuChoice != 'Q' && menuChoice != 'q');

}

 

 이제 잘 동작하는지 실행해봅시다.

 


 메뉴가 잘 나옵니다. 1번을 입력해 입력해봅시다.

 


 잘 됩니다. 2번 메뉴를 선택해 입력된 값을 확인해봅시다.

 

 

 출력은 잘 되는데, 메뉴가 두번 출력되네요. 이것은 출력문을 알아볼때 설명했던 입력버퍼가 비워지지 않아서 발생하는 현상입니다. 이것을 해결하기 위해 다음과 같이 수정해줍니다.

 

// 화면 출력

printf("%s의 성적\n", name);

printf("등급 : %c\n", grade);

printf("국어 점수 : %d\n", scoreKOR);

printf("수학 점수 : %d\n", scoreMAT);

printf("영어 점수 : %d\n", scoreENG);

printf("과학 점수 : %d\n", scoreSCI);

printf("총점 : %d\n평균 : %.1f\n", scoreTotal, scoreAverage);

printf("평가 : %s\n", comment);

 

getchar();

 

 

 다시 실행해봅시다.

 


 잘 고쳐졌습니다.

 

 이제 마지막으로 메뉴에 없는 값을 입력했을때 처리를 해봅시다. 다음과 같이 switch case문을 수정해줍시다.

 

...

case 'Q':

case 'q':

break;

 

default:

printf("잘못 입력하셨습니다.\n\n");

getchar();

} 

 

 잘 되는지 실행해봅시다.

 


 잘 되는것을 확인할 수 있습니다. 이처럼 프로그래밍을 할때는 예외에 관한 처리를 해주는 것이 나중에 프로그램의 오류를 줄이는데 큰 도움이 됩니다.

 

 아래는 지금까지 수정한 최종 소스코드입니다.

 

#include <stdio.h> 

 

void main()

{

char name[20] = "홍길동";   // 이름

char grade = 'B';                 // 등급

int scoreKOR = 80;              // 국어점수

int scoreMAT = 75;              // 수학점수

int scoreENG = 86;              // 영어점수

int scoreSCI = 92;               // 과학점수

char comment[200];        // 평가

 

int scoreTotal = 0;            // 총점

float scoreAverage = 0.0F;       // 평균

 

char menuChoice = ' ';        // 메뉴 선택

 

do

{

// 메뉴 출력

printf("*** 성적관리 프로그램 ***\n");

printf("\n");

printf("1. 학생 성적 입력\n");

printf("2. 성적 확인\n");

printf("\n");

printf("Q. 프로그램 종료\n");

printf("\n");

printf("작업할 번호를 입력하세요 : ");

 

// 메뉴 선택

menuChoice = getchar();

 

switch (menuChoice)

{

case '1':

{

 // 사용자 입력
printf("이름을 입력하세요 : ");

scanf_s("%s", name, sizeof(name));

printf("국어점수를 입력하세요 : ");

scanf_s("%d", &scoreKOR);

printf("수학점수를 입력하세요 : ");

scanf_s("%d", &scoreMAT);

printf("영어점수를 입력하세요 : ");

scanf_s("%d", &scoreENG);

printf("과학점수를 입력하세요 : ");

scanf_s("%d", &scoreSCI);

 

getchar();

printf("평가를 입력하세요 : ");

gets_s(comment, sizeof(comment));

 

}

break;

 

case '2':

{

// 총점 계산

scoreTotal = scoreKOR + scoreMAT + scoreENG + scoreSCI;

// 평균 계산

scoreAverage = (float) scoreTotal / 4;

 

// 평균값에 대응하는 등급 구하기

if (scoreAverage >= 90)

grade = 'A';

else if (scoreAverage >= 80)

grade = 'B';

else if (scoreAverage >= 70)

grade = 'C';

else if (scoreAverage >= 60)

grade = 'D';

else

grade = 'F';

 

// 화면 출력

printf("%s의 성적\n", name);

printf("등급 : %c\n", grade);

printf("국어 점수 : %d\n", scoreKOR);

printf("수학 점수 : %d\n", scoreMAT);

printf("영어 점수 : %d\n", scoreENG);

printf("과학 점수 : %d\n", scoreSCI);

printf("총점 : %d\n평균 : %.1f\n", scoreTotal, scoreAverage);

printf("평가 : %s\n", comment);

 

getchar();

}

break;

 

case 'Q':

case 'q':

break;

 

default:

printf("잘못 입력하셨습니다.\n\n");

getchar();

}

} while (menuChoice != 'Q' && menuChoice != 'q');

}

 

 지금까지 제어문에 대해 알아보았습니다. 다음 시간에는 비주얼스튜디오로 프로그램 오류를 잡는 '디버깅' 방법에 대해 알아보면서 프로그램이 동작하는 흐름을 따라가보며 확인해보도록 하겠습니다.

댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31