Team Curio

비주얼 노벨 한국어 패치 팀 큐리오

프로그래밍

11.c 언어강좌 (8)

연이v 2009. 7. 9. 16:09
반응형
SMALL

=============================================================================
C 프로그래밍 8회
=============================================================================

오늘은 흐름 제어중 반복문에서 저번에 하지못한 while와 do-while에 대해 공부하겠습니다.
그리고 나서 함수에 값 전달하는 방법과 배열에 대해 공부하도록 하죠.

1. while문
우선 while문에 대해 알아보죠.
while문은 for문처럼 반복문이지만 for문보다 사용법은 간단합니다.
우선 사용법을 알아보죠.
while(조건) { /* 하나 이상의 C언어 문장 */ . . }
이렇게 사용하는데, 여기서 조건이 만족하는 동안만 while문 내의 문장들을 실행합니다.
이거 역시 문장이 하나이면 {}를 생략할수 있습니다.
그럼 예제를 볼까요?

/* 파일 이름 : C8-1.C 프로그램 내용 : while문 예제.. */
#include void main()
{
int a=1;
int total=0;
2
while(a<=100) { total+=a;
a++;
}
printf("%d\n",total);
}

while문을 보면 a<=100일때 까지만 반복하는 반복문 입니다.
while문 안에를 보면 total+=a를 하고 있는데, 이건 total=total+a라는것은 언젠가 설명 했고
이걸 실행 한 후에 a++로 a를 1증가시키고 있습니다.
이렇게 계속 되다 보면 total=total+1, total=total+2... 이렇게 계속 실행이 되겠죠?
그래서 나중엔 1부터 100까지의 합이 total에 들어가고 그것이 출력되게 되죠.
그러므로 5050이 출력됨니다.

2. do-while문
그럼 이번엔 do-while문에 대해 알아보죠.
do-while문도 while문과 비슷하지만.
이건 조건이 밑에 있다는 것이 다름니다.
우선 사용법을 보죠.
do { /* 하나 이상의 C언어 문장 */ . . } while(조건);
이렇게 사용합니다.
이것은 처음에 문장들이 실행 된 후, 조건이 만족하면 또 실행시키고 하는 식으로 실행됨니다.
while문에서는 처음부터 조건이 만족하지 않으면 한번도 실행되지 않지만,
do-while문은 처음부터 조건이 만족하지 않더라도 최소한 한번은 실행이 됨니다.

/* 파일 이름 : C8-2.C 프로그램 내용 : do-while문 예제.. */
#include
#include void main()
{
int yn;
do { printf("Continue(Y/N)?");
yn=getche();
putchar('\n');
}
while(yn!='Y' && yn!='N');
}

이 프로그램은 "Continue(Y/N)?"이라는 메시지를 출력하고 Y또는 N이 입력되면 종료되고
다른 것이 입력되면 계속 입력을 받는 것 입니다.
잘 분석해 보시면 왜 그렇게 되는지는 쉽게 아실수 있을겁니다.

3. goto문
goto문은 사실 강좌에 넣으려고 하지 않았지만, 그래도 C의 일부분 이므로 설명은 드리죠.
goto문은 특정 라벨로 뛰어 넘어 버리는 기능을 합니다.
사용법은...
goto 라벨;
이렇게 사용하죠.
여기서 라벨은 같은 함수 내에 존재해야 합니다.
라벨의 정의는 이렇게 하죠.

라벨명:

라벨명은 함수명이나 변수명과는 겹쳐도 상관 없고 서로 함수가 다르다면 라벨명이 겹쳐도 됨니다.
하지만 같은 함수 내에서 라벨명이 겹쳐서는 않되며, 라벨명도 심볼과 같은 규칙에 따라 지어져야 하죠.
즉 라벨명의 첫문자는 반드시 영문자 또는 언더스코어(_)가 와야 하고,
그 뒤로는 영문자, 숫자, 언더스코어만 올수 있다는 것이죠.
또한가지 라벨을 정의할때는 뒤에 :를 붙이지만, goto문에서 라벨을 쓸때는
이걸 쓰면 않된다는 것 입니다.
예를 들어
Label:
이런 라벨이 있을때
goto Label:;
이렇게 해서는 않되고,
goto Label;
이렇게 해야 한다는 것 입니다.
goto문은 C같은 구조화 프로그래밍 언어 에서는 거의 쓸모가 없습니다.
또한 대부분의 C 프로그래머들은 goto문의 사용을 꺼려하고 있습니다.
이유는 goto문을 많이 사용할 경우 프로그램을 보기가 힘들어지고 복잡해 보이기 때문이죠.
그러므로 되도록 goto문의 사용은 줄이고, 함수나 C언어의 강력한 제어문들을 사용해
프로그래밍을 하는 습관을 들여야 합니다.

4. 함수에 값 전달.
여러분이 어떤 함수를 만든다고 합시다.
그 함수는 printf와 같이 어떤 내용을 화면에 출력하는 함수이죠.
그런데 화면에 무언가를 출력하기 위해선 그 출력할 내용을 전달받아야 겠죠?
어떻게 하면 전달받을수 있을까요?
바로 그 방법에 대해서 자세히 알아보도록 하죠.
저번 2회때 함수에 대해 배울때 인수라는 것이 있었습니다.
그때 인수는 함수가 어떤 처리를 할때 필요해서 전달받을 데이터라고 했죠.
이 인수를 통해서 함수가 값을 전달받을수 있습니다.

(1) 인수가 정확히?
인수에 대해 정확히 말하자면 함수에서 값을 전달받는데 쓰이는 변수를 말합니다.
즉 변수의 일종이죠.
아니 일종이 아니고 변수라고 생각하세요.
단 함수 시작시에 전달받을 값이 들어가게 됨니다.

(2) 인수 만들기.
인수는 어떻게 만들까요?
저번 2회때 함수 만드는 방법에 나와 있던것처럼 함수이름 옆에 있는 ()안에 인수를 나열해 주면 됨니다.
()안에 마치 변수를 선언하듯이 인수를 만들어 주면 되죠.(인수가 변수니까 당연한 거죠?)
예를 들어 아무 값도 리턴하지 않고, 인수는 정수형태 a와,b를 가진 func라는 함수는
void func(int a, int b) { . . . }
이런식으로 만들수 있겠죠?

(3) 인수의 사용
이제 인수가 변수라는건 알고 계시죠?
그러므로 인수 사용은 변수와 똑같다는 것도 아시겠죠? 뭐 더이상 설명드릴 것두 없군요.
그럼 중요한것 한가지 말씀드리죠.
우선 예제를 보세요.

/* 파일 이름 : C8-3.C 프로그램 내용 : 함수 예제 */
#include void func(int data)
{
data=10;
}
void main()
{
int var=1;
func(var);
printf("%d\n",var);
}

이 예제를 잘 보세요.
여기서 main함수에는 var이란 변수가 있죠?
그리고 그 변수에 초기값으로 1을 주었죠.
그런다음 func를 호출했는데, 인수로 var이란 변수를 주었죠?
그럼 func함수를 보세요.
func함수에는 data라는 인수가 있는데 이 함수 호출시에 var이란 변수에는 1이 들어있었으므로
data에도 1이 들어갑니다.
func에서는 data를 10으로 바꾸고 있군요.
그럼 이렇게 data를 10으로 바꿨는데, main함수의 var이란 변수도 10으로 바뀔까요?
이 프로그램을 실행해 보시면 아시겠지만 바뀌지 않습니다.
함수 호출시에 변수를 인수로 주면 단지 변수에 들어있는 값을 복사해서 전달해 줄 뿐이죠.
그러므로 바뀌지 않습니다.
이렇게 함수에 값 전달시 변수에 들어있는 값을 그냥 복사해서 전달해 주는 호출 방법을
Passing by value라고 합니다.

5. 배열
배열은 저번에 문자열을 배울때 문자배열 때문에 간략히 설명 드린 적이 있습니다.
이번엔 그 배열에 대해 좀더 자세히 배워보도록 하겠습니다.
배열이란 데이터 구조의 하나로 데이터들을 일정 수 만큼 늘어놓은 구조라고 생각하시면 됨니다.
이때 각각의 데이터를 배열의 원소라고 합니다.
배열은 많은 데이터를 관리할때 편하죠.

(1) 배열의 선언
배열은 변수와 마찬가지로 사용전에 선언해야 합니다.
선언은 다음과 같이 합니다.

데이터형태 배열명[배열크기];

이렇게 하죠.
여기서 데이터 형태는 배열에 저장할 데이터에 형태이고, 배열명은 그 배열을 상징하는 심볼, 배열 크기는 몇개의 데이터를 늘어놓을 것 인지를 정하는 것 입니다.
예를 들어 정수 형태의 데이터를 10개 늘어놓은 Array라는 배열은
int Array[10];
이렇게 선언합니다.

(2) 배열의 사용
배열을 선언했으면 사용법도 알아야 겠죠?
배열 사용은

배열명[첨자] = 값;
변수 = 배열명[첨자];

이런 식으로 사용합니다.
여기서 첨자는 배열의 늘어놓은 데이터중 몇번째 원소를 사용할 건인지를 정하는 것 입니다.
그리고 첨자의 시작은 0부터라는 것을 기억하세요.
예를 들어 아까 Array라는 배열의 첫번째 원소에 10을 넣을때는

Array[0]=10;

이렇게 하는 것이죠.(첨자의 시작이 0이므로 첫번째 원소의 첨자는 0)

(3) 배열의 초기값
보통 변수들은 선언할때 초기값을 줄수 있습니다.
그런데 배열에 초기값을 줄순 없을까요?
당연히 할수 있죠..!
그런데 일반 변수의 초기값을 주는 것보다 좀 복잡합니다.
배열의 초기값을 주는 방법은

데이터형태 배열명[배열크기] = { 1번째 원소의 초기값, 2번째 원소의 초기값, ... };

이렇게 하면 됨니다.
즉 {}안에 각 원소의 순서대로 초기 값을 적어주면 되는 것이죠.
예를 들어 아까 Array배열에 1부터 10까지의 초기값을 넣어 선언하면

int Array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

이렇게 됨니다.
이렇게 하면 Array[0]에는 1이, Array[1]에는 2가... Array[9]에는 10이. 이런식으로 들어갑니다.
배열을 초기값을 주어서 선언할때는 배열크기를 생략해도 됨니다.
즉 위에것은

int Array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

이렇게만 해 줘도 된다는 것이죠.
이렇게 해 주면 초기값이 10개이므로 자동으로 배열크기를 10으로 지정해 줌니다.
하지만 초기값이 없을땐 반드시 크기를 지정해야 합니다.

int Array[];
이렇게 선언하는 건 절데로 안됨니다.
배열의 초기값을 주는건 일부만 주어도 됨니다.
즉 배열의 원소수가 10개이어도 앞에 5개만 초기값을 주어도 된다는 것이죠.
예를 들어
int Array[10] = { 1, 2, 3, 4, 5 };
이렇게 하면 앞에 5개의 원소만 초기값이 들어가고 나머지는 초기값이 없게 됨니다.
만약 배열이 문자 배열일때는 문자열 그대로를 초기값으로 주어도 됨니다.

char Array[10] = "String";
이렇게해도 된다는 것이죠.
이렇게 선언한것과
chat Array[10] = { 'S', 't', 'r', 'i', 'n', 'g' };
이렇게 선언한것의 차이는 무엇인지 아시겠죠?
처음 방법으로 선언한건 문자열을 그대로를 초기값으로 주었으므로 끝에 NULL문자가 들어가겠죠?
그러므로
chat Array[10] = { 'S', 't', 'r', 'i', 'n', 'g', NULL };
이것과 똑같은 것이 됨니다.

6. 다차원 배열
위에서 배운 형태의 배열을 1차원 배열 이라고 합니다.
하지만 배열에는 2차원 배열 3차원 배열등등 계속 이어지죠.
이렇게 2차원 배열 이상을 통틀어 다차원 배열 이라고 합니다.
사실 다차원 배열이라고 해서 1차원 배열과 크게 다를것이 없습니다.
C에서 다차원 배열은 쉽게 배열의 배열.. 이라고 생각하시면 됨니다.
예를 들어 2차원 배열은 배열의 배열이고, 3차원 배열은 배열의 배열의 배열이 되는 것이죠.

(1) 다차원 배열의 선언
1차원 배열은 선언할때 일반 변수 선언과 똑같으나 []를 붙여주고 그 안에 배열의 크기만 정해주면 되었었죠?
2차원 배열은 배열의 배열이니 선언은 1차원 배열과 똑같으나 []를 더 붙여주고
그 안에 배열 크기를 넣어주면 되는 것이죠.

데이터형태 배열명[배열크기][배열크기];
이렇게 선언해 주면 되는 것 입니다.
3차원 배열 역시 2차원 배열 선언과 똑같으나 []를 더 붙여주고 그 안에 배열 크기를 넣어 주면 됨니다.
그러니까
데이터형태 배열명[배열크기][배열크기][배열크기];
이렇게 선언해 주면 3차원 배열이 되는 것 입니다.
4차원 5차원...도 이런 식으로 []만 늘어날 뿐이죠.
예를 들어 Array라는 10*10의 크기를 갖는 2차원 정수 배열은
int Array[10][10];
이렇게 선언하면 됨니다.
만약 10*10*10의 크기를 갖는 3차원 배열이라면
int Array[10][10][10];
이렇게 선언하면 되겠죠?

(2) 다차원 배열의 사용
다차원 배열 사용시에도 단지 []만 늘어나게 됨니다.

2차원 배열의 경우

배열명[첨자][첨자] = 값;
변수 = 배열명[첨자][첨자];

이렇게 사용할수 있고, 3차원 배열의 경우는

배열명[첨자][첨자][첨자] = 값;
변수 = 배열명[첨자][첨자][첨자];

이런 식으로 사용할수 있죠.
예를 들어 보죠.
아까 예로 들었던 Array라는 10*10크기의 2차원 정수 배열이 있을때,
1번째 배열의 3번째 원소에 3을 넣으려면
Array[0][2]=3;
이렇게 해 주면 됨니다.
만약 Array라는 10*10*10크기의 3차원 정수 배열이 있다고 하고,
1번째 배열의 3번째 배열의 2번째 원소에 2를 넣으려면
Array[0][2][1]=2;
이렇게 하면 됨니다.

(3) 다차원 배열의 초기값.
다차원 배열 역시 초기값을 가질수 있습니다.
다차원 배열에 초기값을 넣는것 역시 다차원 배열이 배열의 배열이라는 것을 생각하시면
쉽게 하실수 있습니다.
1차원 배열에 초기값을 지정할때는 {}안에 초기값을 원소의 순서데로 써 주면 되었었죠?
그러므로 2차원 배열은 배열의 배열 이므로 {}안에 또 {}를 써서 초기값을 주면 됨니다.
예를 들어
int Array[2][3];
이런 배열이 있다고 합니다.
이걸 초기값을 주어서 선언하면
int Array[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
이렇게 하면 되는 것이죠.
3차원 배열 이라면 {}안에 {}안에 또다시 {}안에 원소의 초기값을 써 주면 되는 것이고요.

int Array[2][3][2] = { { { 1, 2 } , { 3, 4 }, { 5, 6 } }, { { 7, 8 } , { 9, 10 }, { 11, 12 } } };
이렇게 하면 됨니다.
다차원 배열에 초기값을 지정하는 방법은 이것 말고도 그냥 1차원 배열처럼 지정하는 방법도 있습니다.
1차원 배열처럼 {}안에 배열의 모든 원소의 순서대로 초기값을 적어 주는 것이죠.
예를 들어 아까
int Array[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
이건
int Array[2][3] = { 1, 2, 3, 4, 5, 6 };
이렇게 써 주어도 상관 없습니다.

7. 배열을 인수로 전달.
아까 함수에 값 전달하는 방법을 배웠죠?
그런데 그때 배운건 일반 데이터에 대한 것이었습니다.
그럼 배열을 인수로 전달한다면 어떻게 할까요?
배열 역시 일반 데이터와 전달 방법이 똑같습니다.
그냥 인수를 배열로 만들어 주면 되죠.
예를 들어 아무 값도 리턴하지 않고, 인수로는 정수형태의 10개의 원소를 가진 a라는 배열이 있는
func라는 함수는
void func(int a[10]) { . . . }
이렇게 만들고 인수 사용도 일반 배열과 똑같이 사용하면 됨니다.
그런데 여기서 배열의 크기를 생략해도 됨니다.

void func(int a[]) { . . . }
이렇게 해도 된다는 거죠.
이렇게 해도 아무 상관 없어요.
두가지의 차이점은 전혀 없죠.
그럼 여기서 중요한것 한가지를 말씀드릴께요.
예제를 보시죠.

/* 파일 이름 : C8-4.C 프로그램 내용 : 함수 예제 */
#include void func(int data[])
{
data[0]=10;
}
void main()
{
int i;
int var[10]={ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
func(var);
for(i=0;
i<10;
i++) printf("%d\n",var);
}

이 소스는 아까 나왔던 예제를 조금 변형 시켜서 func함수의 인수를 배열로 한 것인데요.
여기서 func함수를 호출할때 var이란 변수를 인수로 주었습니다.
그리고 func함수에서는 data라는 인수로 배열을 전달받았는데,
data의 첫번째 원소를 10으로 바꾸고 있죠.
그럼 이때 main함수에 있는 var이란 배열의 첫번째 원소도 10으로 바뀔까요?
아까의 경우를 생각해 보면 바뀌지 않을것 같지만, 바뀜니다.
이유는 배열을 인수로 전달할 때는 그 주소를 전달해 주기 때문이죠.
자세한 이유는 지금 설명하기에는 무리이고, 포인터 강좌가 끝난 후에 설명해 드리죠.
지금은 그냥 바뀐다는 것만 꼭 알아두세요.
그리고 이렇게 인수 전달시 주소를 전달해 주어 함수에서 인수의 값을 바꾸면
함수를 호출한 곳의 변수도 값이 바뀌는 호출 방법을 Passing by reference라고 합니다.
이것으로 이번 강좌를 마치도록 하겠습니다.
다음 강좌 에서는 포인터에 대해 공부하도록 하죠

반응형

'프로그래밍' 카테고리의 다른 글

13.c 언어강좌 (10)  (0) 2009.07.10
12.c 언어강좌 (9)  (0) 2009.07.10
10.c 언어강좌 (7)  (0) 2009.07.09
9.c 언어강좌 (6)  (0) 2009.07.04
8.c 언어강좌 (5)  (0) 2009.07.04