본문으로 바로가기
반응형

제어문

변수의 선언과 초기화

변수는 메모리공간의 이름으로 자료형을 가진다. 변수의 선언시 실제 일어나는 일은 변수가 자료형의 크기만큼 메모리를 할당받는다. 메모리 공간을 할당하고 이름을 부여한 다음부터는 그 이름을 가지고 할당된 메모리 공간을 조작하는 것이 가능하다.

변수를 사용하기 위해서는 변수의 값을 주어야 하는 데 이것을 변수의 초기화 라고 한다.

변수가 선언되고 초기화 되기 전에는 변수의 값이 정해지지 않는다. 이때 변수는 미정값을 가진다고 한다.

이 경우에는 변수 num1과 num2가 선언되어 각각 4바이트씩의 메모리 공간을 할당 받는다. 현재 변수 num1의 값이 정해지지 않은 상태에서 num1의 값을 사용하므로 프로그램의 실행결과는 예측할 수 없다. 변수는 선언 후 그 값을 이용할 때는 반드시 초기값을 주어야 한다.

지금 같은 경우 num1, num2는 쓰레기값(미정값)으로 메모리에는 cc 로 가득 채워져있는데 그 값에 10을 더해서 결국 쓰레기값이므로 비쥬얼 스튜디오에서는 에러를 일으켜서 이러한 컴파일을 막아두었다.

 

 

선택문

선택문에는 if문과 if-else문, 그리고 switch 문이 있다. if문은 주어진 조건을 만족하면 실행되고, 만족하지 않으면 실행되지 않는다. if-else문은 조건을 만족하면 if절이 수행되고, 그렇지 않으면 else절이 수행된다. switch문은 여러 개의 명령문 중에서 조건을 만족하는 명령문 하나를 골라 실행하는 선택문이다.

 

 

if문

if라는 단어는 "만약에 어떠한 조건이 만족된다면" 이라는 뜻을 지닌다. 단어의 의미처럼 주어진 조건이 만족될 경우만 실행된다. 구문형식은 다음과 같다. if의 기준은 0이다. 즉, ( 조건식 ) 의 기준은 0이냐 아니냐로 따지면 된다.

if는 키워드이며 반드시 소문자를 사용한다. 조건식은 항상 논리값인 참 또는 거짓 값을 가지며 괄호로 둘러싸인다. 실행할 명령문은 하나의 명령문일 수도 있고 여러 개의 명령문으로 이루어진 복합문일 수도 있다. 복합문일 경우에는 항상 중괄호({ })로 둘러 싸인다.

C언어에서 if는 0일때 거짓, 0이 아닐때 참으로 동작한다. C#에서는 조건문이 항상 bool형으로 컴파일러가 잡아내기때문에 에러로 잡아내게 된다. 하지만 지금처럼 코드를 작성하게되면 어떻게 될까?

 

#include <stdio.h>
int main(void) {
	if (-1) {
		printf("참\n");
	}
	else
	{
		printf("거짓\n");
	}
}

 

if에 -1을 넣었는데도 '참'이 출력되었다. 아무숫자나 조건문에 넣어도 0이아닌 숫자를 넣으면 무조건 참으로 출력될 것이다. 실수도 마찬가지로 0.0f는 거짓이며, 0.0f가 아닌 값들은 참이다.

 

이번엔 0을 넣어보자.

#include <stdio.h>
int main(void) 
{
	if (0) 
    {
		printf("참\n");
	}
	else
	{
		printf("거짓\n");
	}
}

다른 숫자는 모두 참이지만 0만 '거짓' 이 출력되는 것을 확인할 수 있다. 비교적 최근에 사용하는 언어들은 if 조건문에 true(참), false(거짓)과 같은 전용 자료형을 가지고 있지만 C언어는 0일 거짓으로, 그 이외의 값을 모두 참으로 사용한다.

 

C언어를 처음 배우고 나면 다음과 같이 if의 조건식 안에서 = (할당 연산자)를 사용하는 실수를 범하게 된다.

 

아래 예제를 살펴보자.

#include <stdio.h>
int main(void)
{
	int num1 = 5;

	if (num1 = 10)  // num1에 10을 할당. 0 이외의 숫자는 참이므로 10은 참.
		printf("10입니다.\n");
}

if의 조건식에 num1 = 10처럼 지정해버리면 num1에 10이 할당(저장)되고, if는 num1에 들어있는 값 대로 조건을 판단하게 된다. 따라서 10은 0이외의 값이기때문에 "10입니다."가 출력된다. 만약 조건식을 num1 = 0으로 지정하면 0은 거짓이므로 아무것도 출력되지 않는다.

 

출처 : https://dojang.io/mod/page/view.php?id=130

조건식에 == 대신 =를 사용하는 실수는 보통 컴파일 에러가 나지 않는다. 그래서 원하는 결과가 출력되지 않을때 오류를 잡아내기가 힘들고, 코드가 복잡해지면 눈에 잘 띄지도 않는다. 조건식을 작성할때는 이 부분을 항상 주의해야한다.

 

따라서 다른 사람이 작성한 소스코드를 보다 보면 다음과 같이 조건문과 변수값을 반대로 지정한 코드를 볼수도 있다.

if(10 == num1)
	printf("10입니다.\n");

조건식에서 비교할 값을 앞에 두면 if에서 =를 사용할때 에러가 발생하므로 실수를 방지할 수 있다.

if(10 = num1)   // 10에 num1을 할당(저장)할 수 없으므로 컴파일 에러
	printf("10입니다.\n");

 

 

if - else 문

else문은 독립적으로 사용되는 것이 아니라, if문장과 더불어 하나의 문장을 구성해서 사용된다. 구문형식은 다음과 같다.

if와 else는 키워드이다. 조건식의 논리값이 참이면 if절의 명령문 1이 수행되고, 거짓이면 else절 명령문 2가 실행된다.

 

 

 

만약, 조건에 따라 선택한 문장이 많은 경우에는 if~else 구문을 사용한다. 아래는 표준 체중이 아닌 경우에 저체중과 과체중을 구분하는 예시이다.

 

 

 

// 짝수, 홀수 구별하는 프로그램
#include <stdio.h>
#pragma warning(disable: 4996) 
int main(void) 
{
	int num;

	printf("정수를 입력하시오 : ");
	scanf("%d", &num);
	if (num % 2) {
		printf("%d는 홀수 입니다. \n", num);
	}
	else
	{
		printf("%d는 짝수 입니다. \n", num);
	}
}

 

 

// 학점 계산 프로그램
#include <stdio.h>
#pragma warning(disable: 4996) 
int main(void) 
{
	double avg;
	char grade;
	printf("평균점수를 입력하세요 : ");
	scanf("%lf", &avg);
	if (avg >= 90.0) grade = 'A';
	else if (avg >= 80.0) grade = 'B';
	else if (avg >= 70.0) grade = 'C';
	else grade = 'F';

	printf("학점은 %c입니다. \n", grade);
	return 0;
}

 

 

 

 

switch 문

if문이 두 명령문 중에서 하나를 실행하는 선택문인 데 비해서 switch 문은 여러 개의 명령문 중에서 하나를 실행하는 선택문이다. 복잡한 if~else 문장을 간결해 보이게 한다는 장점을 지니고 있으나 사용될 수 있는 영역은 if~else에 비해 제한적이다.

 

 키워드 switch문 뒤의 괄호 속에 정수값을 가지는 변수 또는 수식이 올 수 있다. 변수의 경우는 int형이나 char형이 올 수 있지만, 실수형은 올 수 없다. switch문의 실행부는 중괄호에 둘러싸인다. 각 case문은 키워드 case로 시작하여 정수값을 가지는 상수와 콜론(:)이 오고, 그 뒤에 명령문이 온다. 정수값을 가지는 상수는 int형이나 char형이다. switch문의 case내에는 중첩적인 switch문이 올 수 있다.

 

 default문은 위의 case문이 하나도 실행되지 않았을 경우 실행된다. default문은 생략될 수 있으나 오류나 예외일 경우의 메시지를 출력하는데 사용하면 편리하다. 마지막으로 모든 case문의 끝에는 break문이 포함되어 있음을 볼 수 있다.

 

 break문을 만나게 되면 break문을 가장 가까이서 감싸고 있는 블록(괄호)를 빠져 나오게 된다. break문이 없다면, switch의 정수값과 일치하는 case문을 수행하고 switch문을 벗어 나는 것이 아니라, 조건이 만족되는지는 확인하지 않고 그 이하를 모두 실행해 버린다.(break문을 만날 때 까지)

 

// 로또 당첨확인 프로그램
#include <stdio.h>
#pragma warning(disable: 4996) 
int main(void) {
	int lot;

	printf("당첨 번호를 입력하세요: ");
	scanf("%d", &lot);

	switch (lot) {
	case 11:
		printf("1등 : 10억\n");
		break;
	case 22:
		printf("2등 : 3억\n");
		break;
	case 33:
		printf("3등 : 10억\n");
		break;
	default:
		printf("당첨번호가 없습니다.\n");
		break;
	}
}

 

 

goto문

goto문은 가장 원시적인 프로그램의 제어 방법이다. 아무 조건없이 프로그램의 제어를 변경시키기 때문에 프로그램의 논리적 체계를 흩뜨려 프로그램을 이해하기 힘들게 만든다.

 

사용법은 다음과 같다.

 

다음 예제를 살펴보자.

int main()
{
    goto TEST2;

TEST1:
    printf("1\n");

TEST2:
    printf("2\n");
    goto TEST1;

    return 0;
}

시작하자마자 goto로 TEST2로 가서 2를 출력하고, goto로 TEST1로 가서 1을 출력해서 다시 내려가면서 TEST2에서 2를 출력하고 goto로 TEST1로 가서 1을 출력하고 ...   의 무한 반복되는 예제이다.

 

goto문은 이전의 베이직이나 포트란 프로그래밍에서 많이 사용되었지만, 프로그램의 논리적 구조를 해치기 때문에 파스칼이나 C 프로그램에서는 가급적 사용하지 않는 것이 좋다.

반응형