BACKRUSH  대화방입장  유닉스명령  다음  자료실  Ascii Table   Exploit   원격접속  달력,시간   프로세스   오이까기  
지하철노선   Whois   RFC문서   SUN FAQ   SUN FAQ1   C메뉴얼   PHP메뉴얼   너구리   아스키월드 아이피서치
c언어 강좌

Ⅰ. C언어의 개요

1. C언어의 개발

C언어는 Dennis Ritchie와 Ken Thompson이 Bell연구소에서 Unix를 개발하던중 1972년 Dennis Ritchie에 의해 개발 되었다.

㟍 C언어의 발전 과정

ALGOL 60

⇩ 1960년 국제 위원회 설계

CPL (Combined Programming Language)

⇩ 1963년 케임브리지 대학 및 런던대학

BCPL (Basic Combined Programming Language)

⇩ 1967년 케임브리지 대학(Martin Richards)

B언어

⇩ 1970년 Bell 연구소 (Ken Thompson)

C언어

1972년 Bell 연구소 (Dennis Ritchie)

2. C언어의 특징

급속도로 보급되어 널리 사용되고 있는 가장 인기있고 중요시 되고 있는 프로그래밍 언어로서 다음과 같은 특징을 가지고 있다.

1)전산 이론 및 실무 적용상에 절대적으로 필요한 제어 구조, 자료 구조 및 연산자를 충 분히 갖추고 있는 현대식 언어이다.

2)하향식 설계(top-down design), 구조적 프로그래밍(structured programming)

그리고 모듈식 설계(modular design)가 용이하여 신뢰성 있고 이해하기 쉬운 프로 그램을 만들 수 있다.

3)컴퓨터의 기능을 최대한도로 이용할 수 있는 효율적인 언어이기 때문에 프로그램을 간 결하게 작성하여 신속하게 수행 할 수 있다.

4)시스템 간에 호환성이 매우 높다. 즉 어떤 시스템에서 사용되던 C프로그램을 수정없 이 또는 약간의 수정으로 다른 시스템에서도 실행시킬 수 있다.

5)고급 프로그래밍 언어와 어셈블리의 장점을 취한 중간 수준의 시스템 프로그래밍 언어 이다. (UNIX, MS-DOS, DBASEⅢ+등을 작성)

3. 번역기(Compiler)의 종류

쉽게 접할 수 있는 C언어의 종류는 다음과 같은 것들이 있다.

1)Compiler type : Lattice C, Turbo C, Microsoft C, XENIX C, UNIX C

2)Interpreter type : RUN/C Professional

4. C언어의 미래

C언어는 간결하면서도 효율적이고 강력한 언어이기 때문에 퍼스널 컴퓨터에서부터 슈퍼 컴퓨터에 이르는 각종 시스템에서 널리 사용되고 있다.

1980년대 이후 소프트웨어 하우스, 전산 전공자 및 일반 애호가들에게 급격히 보급되고 있으며 앞으로 그 대상과 활용범위는 더욱 빠른 추세로 확산될 전망이다.

5. C언어의 사용

C언어는 컴파일러형 언어이기 때문에 C언어 프로그램을 작성하여 실행시키려면 다음과 같은 절차가 필요하다.

1)에디터(editor)를 사용하여 C프로그램(원시 코드)을 작성한다.

2)에디터로 작성한 C프로그램을 컴파일(compile)하여 목적코드(object code)를 만든다.

즉, C언어로 작성한 프로그램을 컴퓨터가 직접 이해하여 실행할 수 있는 기계어 프로그 램으로 번역(compile)한다.

3)C라이브러리에서 작성한 라이브러리 목적코드와 최종적으로 링크(link)하여 실행 화일 (.exe 화일)을 만든다.

4)실행이 가능한 실행 화일을 로드시켜 실행한다. 즉, 실행화일의 이름을 입력하여 실행 시킨다.

6. C프로그램의 예

main()

{

printf("이제부터 C 프로그래밍을 시작합시다!");

}


C언어에서 대문자(upper-case)와 소문자(lower-case)가 구별되어 사용되며, C프로그램은 소문자로 작성하는 것을 원칙으로 한다는 점을 주의하여야 한다. 그리고 프로그램 코딩시 FORTRAN이나 COBOL등의 언어에서 처럼 코딩하는 열이 정해져 있는 것이 아니라 한 행의 어느 열에서 코딩을 시작해도 상관이 없다. 이것은 프로그램을 매우 읽기 쉽게 작성할 수 있도록 하는 좋은 수단이 된다.

Ⅱ. C언어의 이해를 위한 기초 지식

1. 예제 프로그램과 실행 결과

◎ 예제 프로그램(c2-01.c)

main( )

{

printf("이제부터 C 프로그래밍을 시작합시다!");

}

◎실행 결과

c>c2-01

이제부터 C 프로그래밍을 시작합시다!

2. main( )함수

C프로그램은 하나 이상의 함수들로 구성되며, 반드시 main( ) 함수로 시작된다. 이에 대해서는 제Ⅵ장의 함수에서 자세히 설명하기로 한다.

위 프로그램에서 "{"는 main( )함수의 시작을 나타내고 "}"는 main( )함수의 끝을 나타낸다. 즉 main( )에서 ( )는 함수를 나타내며 "{"와 "}"사이의 내용으로 구성된다.

3. 주석문(comment)

주석문이란 프로그램이 어떠한 목적으로 누구에 의해서 작성되었는가 또는 각 루틴이나 문장의 논리에 대한 설명을 기술하는 것으로 프로그램을 문서화 할 목적으로 많이 사용된다. 주석문은 /*로 시작해서 */로 끝나는 문자들의 집단을 의미하며 그 사이에는 어떠한 문자라도 사용이 가능하고 프로그램 중 여백 문자가 들어갈 수 있는 곳이면 어디든지 기술항 수가 있다.

/*와 */로 둘러싸인 주석문은 컴파일시에 하나의 여백문자로 취급되기 때문에 주석문을 많이 사용하여도 처리 속도에는 차이가 없다.

『보기』주석문의 예

/*-------------------------

* test program

*------------------------

*/

4. 문장(statement)

문장이란 프로그램을 구성하는 기본적인 요소로서 문장의 끝을 나타내는 세미콜론(;)을 반드시 포함하고 있다. 즉 프로그램이란 어떠한 기능들을 수행하는 문장들로 구성된다고 말할 수 있다.

『보기』문장의 예

int counter, sum;

counter = 0 ;

sum = sum + counter ;

printf ("C 프로그래밍");

문장의 종류에 대해서는 제Ⅲ장에서는 보다 구체적으로 설명하기로 한다.

5. printf( )함수

printf( )는 하나의 표준 라이브러리 함수로서 데이터를 표준 출력 장치인 모니터로 출력할 때 사용한다.

printf( )함수에 의하여 문자열이나 숫자를 출력할 때에는 printf다음의 괄호 속에 출력할 형식과 출력할 내용을 인용부호(" ")로 감싸서 표시한다.

1) 문자열의 출력

문자열을 출력하려면 printf다음의 괄호 속에 출력할 문자열을 인용 부호 내에 기술 하면 된다.

『실습 2-02 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c2-02.c :문자열의 출력

*----------------------------------------------------------------------------------------------*/

main( )

{

printf("무궁화 "); /* "무궁화 "를 출력 */

printf("무궁화 \n"); /* "무궁화 "를 출력한 후 줄을 바꿈 */

printf("우리 나라 꽃\n"); /* "우리 나라 꽃"을 출력후 주바꿈 */

printf("\n"); /* 줄을 바꿈 */

printf("삼천리 강산에\n"); /*"삼천리 강산에" 출력후 줄 바꿈 */

printf("우리 나라 꽃"); /* "우리 나라 꽃"을 출력 */

}

☞실행 결과

c>c2-02

무궁화 무궁화

우리 나라 꽃

삼천리 강산에

우리 나라 꽃

【참고】아래의 두 문장은 다음과 같이 한 문장으로 표시할 수 있다.

printf("우리 나라 꽃\n");

printf("\n"); ⇨printf("우리나라 꽃 \n\n");

g line feed(줄바꿈)

printf("우리 나라 꽃\n\n");

) H line feed(줄바꿈)

출鵨할 문자열

'\n'은 다음 줄의 처음부터 출력을 시작하라는 의미를 갖는 하나의 문자로서 개행(new line 또는 line feed)문자라고 한다. (개행 문자에 대해서는 Ⅴ장의 '문자 데이터의 처리'에서 상세히 설명하기로 한다.)

《연습 1》아래의 그림을 출력하는 프로그램을 작성하여라.

☞실행 결과

*

***

*****

*******

*********

1)printf( ) 함수를 5개 사용하여 작성하여라.

2)printf( ) 함수를 1개 사용하여라.

《연습 2》아래의 두 단어를 실행 결과와 같이 출력하는 프로그램을 작성하여라.

Programming , Language

☞실행 결과

Programming

Language

2) 수치 데이터의 출력

수치 데이터를 출력할 때에는 아래의 예제에서와 같이 출력할 숫자의 출력 형식과 출력할 수치를 printf다음의 괄호 속에 기술한다.

『실습 2-03』예제 프로그램

/*-----------------------------------------------------------------------------------------------------

* c2-03.c : 수치 데이터의 출력

*----------------------------------------------------------------------------------------------------- */

main( )

{

printf("%d",1); /* 1을 출력 */

printf("%d",2); /* 2를 출력 */

printf("%d\n",3); /* 3을 출력하고 줄을 바꿈 */

printf("%d\n",123); /* 123을 출력하고 줄을 바꿈 */

printf("%d\n",-345); /* -345를 출력하고 줄을 바꿈 */

printf(" %d",123); /* 3개의 공백뒤에 123을 출력 */

printf(" %d\n",-345); /* 3개의 공백뒤에 -345출력후 줄바꿈 */

printf("3 + 5 = %d\n", 3+5); /* "3 + 5 = 8"을 출력후 줄바꿈 */

printf("%d + %d = %d\n",3,5,3+5); /* "3 + 5 = 8"을 출력후 줄바꿈 */

}

☞실행 결과

c>c2-03

123

123

-345

123 -345

3 + 5 = 8

3 + 5 = 8

⊙해설

위 예제에서 사용된 출력 형식 '%d'는 정수형 데이터를 10진수 형식으로 출력할 때 사용하는 형식 지정 문자열로서 그 의미는 다음과 같다.

g 출력할 데이터

printf("%d \n", 3);

) H line feed(줄바꿈)

형식 지정 문자열

(%d는 정수형 데이터를 10진수로 출력할 때 사용한다.)

printf("%d + %d = %d\n",3,5,3+5);

| ) H 3+5의 연산 결과값을 출력할 위치

| 5의 출력 위치

+-→ 3의 출력 위치

6. 상수와 변수

1) 상수(constant)

상수란 연산에 이용되는 자료로서 그 값이 한 번 정의되면 프로그램이 실행되는 도 중에 그 값이 변화 되지 않고 일정한 값을 유지하는 자료를 말한다.

◇ 상수의 예 --- 10, -234, 32767, -567.89, -0.00008

2) 변수(variable)

변수란 프로그램이 실행되는 동안에 그 처리 대상이 되는 자료나 처리된 결과를 기 억시킬 기억 장소의 이름을 말하는 것으로 상수와는 달리 프로그램이 실행되는 도중에 그 값이 변할 수 있다.

◇변수의 예 --- a, b, c, add, sub, mul, div

3) 변수명을 만드는 규칙

①변수명으로 사용할 수 있는 문자는 A∼Z, a∼z, 0∼9, _이다.

②변수명의 첫문자는 반드시 영문자나 _로 시작되어야 한다.

③변수명은 32자까지만 유효하다. (8문자만 유효한 것도 있음)

④예약어는 변수명으로 사용할 수 없으나 변수명 내에 포함되는 것은 관계없다.

⑤영문자의 대, 소문자는 별개의 것으로 구분된다.

『보기』변수명의 예

사용가능한 예

사용 불가능한 예

이 유

i

integer_var

Number_of_pen

Seoul_88_Olympic

a*b

value of sum

3dollor

int

*기호 사용 불가

공백 사용 불가

첫문자가 숫자

예약어


※ 상수와 변수의 예

counter = counter + 30

| | X상수

+---------+---→변수

위 문장은 변수 counter의 내용에 30을 더하여 변수 counter에 다시 대입 시키라는 의미이다.

※ 예약어(reservd word)

예약어란 그 의미와 용도가 미리 정의되어 있는 단어로서 정의된 용도로 사용하지 않거 나 철자가 틀리면 오류가 발생한다.

예약어의 예를 들면 다음과 같은 것들이 있다.

①흐름의 제어에 관한 예약어 --- for, while, do, if , else, switch, case, default

break, countinue, goto, return

②데이터 형에 관한 예약어 --- char, double, float, int, long, short, struct, union

unsigned, typedef, enum, void

③기억 장소의 종류에 관한 예약어 --- auto, extern, register, static

④기타 --- sizeof

예약어들에 대한 구체적인 설명은 필요할 때마다 하나 하나 설명하기로 한다.

7. 정수형 데이터의 사용

C프로그래밍 언어는 다음과 같은 기본적인 데이터의 형을 준비하고 있다.

+-- 정수형 ------+- short

(단정수형)

| +- unsigned short(무부호 단정수형)

| +- int (정수형)

| +- unsigned int (무부호 정수형)

기본형 -----+ +- long(장정수형)

| +- unsigned long(무부호 장정수형)

+-- 실수형 ------+- float (실수형)

| +- double (배정도 실수형)

+-- 문자형 ------+- char (문자형)

+- unsigned char(무부호 문자형)

모든 데이터의 형을 구체적으로 설명하는 것은 초보자들에게 혼동만 초래할 우려가 있으므로 제Ⅲ장이 끝날 때까지는 정수형 데이터 만을 사용하기로 한다.

1)정수형 데이터

정수형 데이터는 소수점 이하를 포함하지 않는 정수의 형태를 갖는 데이터를 말하는 것으로 다음과 같은 종류들이 있다.

정수형의 자료를 나타내는 int형은 2Byte(즉 1Word,16Bit)이므로 나타낼수 있는 수치의 종류는 65,536가지이다.(2의 16승 - 수학시간에 졸지 않은사람은 다 안다) 부호를 사용할 필요가 없는 정수형 변수(Unsigned int)는 0에서 65,536까지 범위를 나타낼 수가 있으나, 일반 int형 변수는 양수, 0 ,음수를 모두사용해야 하므로 반으로 나누어 -32,768 ~ 32,767 ( 0은 편의상 양수에 속한다 )사이의 범위를 가지게 되는 것이다.

그러면, int a = 32767, b = 1, sum;

sum = a + b ; 에서 sum의 값은 얼마일까?

바로,오버플로우가 발생한다. 실제는 32768이 되지만 범위를 넘어서므로sum의 값은 -1이라는 어처구니 없는 값이 발생한다. 그러므로 우리는 연산을 할 때, 수치형의 범위를 고려하여야 괴짜 프로그램을 생산하지 않게 된다.

컴퓨터에서는 모든 자료를 2진수로 취급한다.

int a=15라고 했을때,컴퓨터내부에서는 a를 000000000001111(int형은2바이트이므로)로기억한다.

그러면, int b=-15라고 했을 때 어떻게 기억을 할까?

컴퓨터는 2진수로 음수를 표현할 때 2의 보수를 취하는 방법을 이용하는데

그 방법은 아래와 같다.

(1) 양수값에다가 1의 보수를 취한다(비트반전).

(2) (1)의 결과에 1을 더한다.

15 => (1) 1111111111110000 (1의 보수를 취함)

(2) 1111111111110001 => -15 (1을 더함)

부호를 고려하는 정수형(int)의 경우에는맨좌측 최상위비트가 0이면 양수로,1이면 음수로 본다.

하지만 unsigned int(부호없는 정수)형의 경우에는 양수만을 취급하므로최상위 비트를 고려하지 않는다.

예를 들어보자. 1111111111110001가 int형이라면,

최상위비트가 1이므로 이 값은 음수이므로 2의 보수를 취

하여 0000000000001111(15)의 음수값인 -15가 된다.

반면에 1111111111110001이 unsigned int형이라면,

최상위비트와는 관계없이 10진수로 65521이 된다.

장황하게 설명을 하였는데, 기본적으로 알아두어야 할 내용이므로 언급하였다.(전산학에서는 기본적인 내용이다) 일반적인 프로그램에서는 정수형이나 배정도 정수형 변수로도 프로그램작성이 가능하나, 수학적인 계산이 조금이라도 들어가는 프로그램에서는실수형이 필요하게 된다.

⑴int형 (부호있는 정수형)

int형은 일반적으로 컴퓨터가 사용하는 표준 워드(word)의 크기를 사용한다. 따라서 16비트 컴퓨터에서 사용되는 C언어는 16비트를 사용하여 int형 데이터를 표현하고 32비트 컴퓨터에서는 32비트를 사용하여 int형 데이터를 표현한다.

int형 데이터를 16비트를 사용하여 표현하는 경우에 사용할 수 있는 수의 범위는

-32768∼32767이고 32비트를 사용하여 표현하는 경우에는 -2147483648∼2147483647까지이다.

⑵unsigned int(부호없는 정수형)

int형의 음수 영역을 양수 영역으로 사용하는 표현 방식이다. 따라서 부호가 -인 음수는 사용할 수 없다. 일반적으로 양수 데이터만을 취급하는 경우에 사용한다.

16비트 컴퓨터에서 사용할 수 있는 수의 허용 범위는 0 ~ 65535까지이고 32비트를 사용하는 경우에는 0 ~ 4294967295까지이다.

⑶short형(short int형)-- 부호있는 단정수형

기억 용량이 적은 컴퓨터에서 적은 기억 용량으로 많은 정수형 데이터를 기억시키기 위하여 마련한 것으로 대부분의 경우 16비트로 데이터를 표현한다. 16비트 컴퓨터에 사용되는 C언어에서는 int형과 그 사용 범위가 같다.

32비트 컴퓨터에서 사용되는 C언어의 경우에는 일반적으로 int형은 32비트로 표현하고 short형은 16비트로 표현된다.

short형으로 표현할 수 있는 수의 범위는 -32768 ~ 32767까지이다.

⑷unsigned short형 (부호없는 단정수형)

short형의 음수 영역을 양수 영역으로 사용하는 표현 방식이다. 따라서 부호가 -인 음수는 사용할 수 없다. unsigned short형으로 사용할 수 있는 수의 허용 범위는 0 ~ 65535까지이다.

⑸long형(장정수형)

long형으로 처리하기 힘든 큰 정수를 처리하기 위하여 마련된 것으로 32비트로 정수를 표현하는 방식이다. 따라서 long형으로 처리할 수 있는 수의 범위는 -2147483648 ~ 2147483647까지이다. 32비트 컴퓨터에서 사용되는 C의 경우에는 int형과 사용범위가 같다.

⑹unsigned long형(부호있는 장정수형)

long형의 음수 영역을 양수 영역으로 사용하는 표현 방식이다. 따라서 부호가 -인 음수는 사용할 수 없다. unsigned long형으로 표현할 수 있는 수의 범위는 0 ~ 4294967295까지이다.

㟍 정수형 데이터의 종류는 다음과 같다. (16비트 컴퓨터의 경우)

종 류

크기

부호

허 용 치

용 도

int

unsigned int

short

unsigned short

long

unsigned long

2B

2B

2B

2B

4B

4B

-32768~32767

0~65535

-32768~32767

0~65535

-2147483648~2147483647

0~4294967295

정수 처리

양의 정수 처리

정수 처리

양의 정수 처리

큰 정수 처리

큰 양 정수 처리


㟍 16비트 컴퓨터를 사용하여 문제를 해결할 때 큰 정수를 취급하지 않을 경우에는 long형 을 사용하지 않는 것이 바람직하다. 왜냐하면 long형은 int형이나 short형을 사용할 때 보다 연산 속도가 떨어질 뿐만 아니라 메모리를 많이 차지하기 때문이다.

일반적으로 정수형 데이터 처리시에는 표준 워드 크기를 사용하는 int형을 사용하는 것이 좋다.

《연습 3》int형 데이터(정수형 데이터 또는 고정 소수점 데이터)의 표현 형식 중 2의 보 수 표현법에 대하여 설명하여라. (단, 16비트를 사용하여 13과 -13을 예로 사용 할 것)

《연습 4》unsigned int형 데이터의 표현 형식을 설명하여 보자. (단, 16비트로 0부터 65535까지 표현되는 이유를 설명하여라.)

『실습 2-04』

/*----------------------------------------------------------------------------------------------

* c2-04.c : 정수형 데이터의 출력

*--------------------------------------------------------------------------------------------- */

main( )

{

printf("%d\n",123);

printf("%d\n",-123);

printf("%d\n",32768);

printf("%d\n",65535);

printf("%d\n\n",1234567);

printf("%u\n",1);

printf("%u\n",-1);

printf("%u\n",-32768);

printf("%u\n",65535);

printf("%ld\n",123L);

printf("%ld\n",-123L);

printf("%ld\n\n",4294967295L);

printf("%lu\n",1L);

printf("%lu\n",-1L);

printf("%lu\n\n",4294967295L);

}

☞ 실행 결과

c>c2-04

123

-123

-32768

-1

-10617

1

65535

32768

65535

123

-123

-1

1

4294967295

4294967295

long형 상수를 나타낼 때에는 숫자 끝에 L 또는 l 을 붙이는 것이 좋다.

123L이나 -123L은 큰 숫자는 아니지만 32비트(bit)의 long형 데이터로 취급된다.

《연습 5》아래 문장들의 실행 결과를 『실습 2-04』의 실행 결과에서 확인한 후 실행 결 과와 같이 출력된 이유를 설명하라.

printf("%d\n",32768);

printf("%d\n",65535);

printf("%d\n\n",1234567);

printf("%u\n",-1);

printf("%u\n",-32768);

printf("%ld\n\n",4294967295L);

printf("%lu\n", -1L);

2)정수형 데이터의 형 선언

C프로그램에서 사용될 모든 변수는 반드시 그 변수가 사용되기 전에 int, short, long등의 형선언을 해 주어야 한다. 그래야 선언된 변수의 이름과 데이터의 형이 성립되고 기억 장소가 할당된다.

『보기』정수형 변수의 선언 예

int counter; /* int형 변수 counter를 선언 */

int a, b, c; /* int형 변수 a, b, c를 선언 */

unsigned int a, y, x; /* unsigned int형 변수 x, y, z를 선언 */

long var_1, var_2; /* long형 변수 var_1, var_2를 선언 */

int a=0, b=10, c=30; /* int형 변수 a, b, c를 선언하면서 각변수에 */

/* 0,10,30을 초기값으로 기억 */

int a, b, c;는 다음과 같이 3개의 선언문으로 선언할 수도 있다.

int a;

int b;

int c;

3) 실수 표현 방법

컴퓨터에서 실수(float형)를 표시하는 경우에는 부동소숫점 형식을 이용한다. 부동소수점 형식에서는 하나의 수치를 표시하는데에 4Byte를 할당한다. 첫 byte는 그 수치의 부호와 지수를 표시하며 남은 3 byte로는 1 byte 당10진수 2자리를 BCD형식으로 표시한다. BCD(Binary Coded Digit)는 우리말로 2진화 10진수라고 부르며, 4비트로 10진수 1자리를 표시하는 형식을말한다.

4비트로 표시할 수 있는 수의 종류는 2의 4승(0 ~ 15까지)가지가 있지만BCD에서는 0에서 9까지만 표시한다. 1994를 BCD로 표시하면,

+----+----+----+----+

|0001|1001|1001|0100| (4비트로 10진수 1자리를 표시)

+----+----+----+----+

1 9 9 4

예를 들어 float a=1994; 일때 컴퓨터에서는,

+---------------------------+

| (이 영역은 BCD형식으로) |

+----+----+----+----+----+----+----+----+

|xyyy|yyyy|0001|1001|1001|0100|0000|0000| (총 4 byte)

+++--+---++----+----+----+----+----+----+

|| | 1 . 9 9 4 0 0

|+------+

| | * 소수점은 항상 이 위치에 있는 걸로 간주

| |

| +---------- 지수(10의 멱승을 나타냄) .여기선 0000011

|

+-------------- 부호(양수이면 0, 음수이면 1) .여기선 0

==> 1.99400 * 10의 3승 (1994.00) : 실수 표현 방식이다.

위에서 보면 지수의 표현을 7bit로 하고 있다. 7비트로 할 수 있는 자료의 종류는 128가지인데, 음수, 양수를 구분해야 하므로 지수의 범위는 -64에서 63까지가 된다.

위에서 보듯이 실수형(float) 자료의 유효 수치는 6자리이다. 그러므로 7자리 이상의 수치를 기억시키는 경우에는 7번째 자리에서 반올림이 행하여진다.

C에서는 수치의 유효 자리수를 2배로 늘리기 위해 배정도 실수형(double)을 지원한다. 배정도 실수는 8byte로 표시하게 되며, 유효자리수는 14자리로 늘어난다.

( 총 8 byte )

+----+----+----+----+----+----+----+----+ +----+----+----+----+

|xyyy|yyyy|0000|0000|0000|0000|0000|0000|....|0000|0000|0000|0000|

+++--+---+++---+----+----+----+----+----+ +----+----+----+----+

|| | | |

|+------+ +-----------------------------....--------------------+

|지수비트 7 byte (유효자리수는 14자리로 늘어난다)

|

부호비트

8. 대입 연산자와 연산식

대입 연산자(assignment operator) '='는 그 오른쪽의 수식의 값을 왼쪽의 변수에 대입할 때 사용하는 연산 기호로서 치환 연산자라고 한다.

그리고 대입 연산자를 사용한 수식을 대입 연산식(assignment expression) 또는 대입식이라고 한다.

『보기』대입식의 예

a=10; /*10을 변수 a에 대입(기억)시키라는 의미 */

b=a; /*변수 a의 값을 변수 b에 대입 */

i=i+1; /*변수 i에 1을 더한 값을 i에 대입 */

x=y=z=0; /*0을 변수 x, y, z에 대입 */

x=y=z=0;은 x=0, y=0, z=0;과 같은 의미이다.

대입식에서 '='기호 왼쪽의 피연산자는 변수뿐만 아니라 대입이 가능한 모든 것으로 각종 변수, 배열 요소, 구조체 구성원, 포인터의 대상체 등이 올 수 있으며(당분간은 반드시 변수를 사용하여야 한다고 생각하기로 하자), 오른쪽 피연산자는 어떠한 종류의 수식이 사용되어도 관계없다.

그리고 C언어에서는 대입식 자체가 어떠한 값을 갖는다는 사실을 기억해야 한다. 대입식의 값은 '='기호 좌측의 변수에 기억된 값이 된다. 예를 들면 a=0; 이라는 대입식의 값은 0이된다. 왜냐하면 위 식의 연산 결과 a의 값이 0이기 때문이다. 따라서 아래의 왼쪽 3개의 대입식을 오른쪽과 같이 하나의 대입식으로 나타낼 수 있다.

a = 0;

b = a + 10; ⇒ c = ( b = ( a = 0 ) + 10 ) + 20;

c = b + 20;



9. 산술 연산자와 산술식

덧셈, 뺄셈, 곱셈, 나눗셈, 나머지 계산 등을 수행할 목적으로 사용하는 연산 기호를 산술 연산자(arithmetic operator)라고 하며 산술 연산자에 의하여 결합된 식을 산술식(arith-

metic expression) 또는 산술 연산식이라고 한다.

산술 연산자의 종류와 그 기능 및 연산 우선 순위를 표로 나타내면 다음과 같다.

산술 연산자의 종류와 그 기능

연 산 자

명 칭

기 능

사용예

우선순위

-

*

/

%

+

-

부호 연산자

곱셈 연산자

나눗셈 연산자

나머지 연산자

덧셈 연산자

뺄셈 연산자

부호 전환

곱셈

나눗셈

나머지 계산

덧셈

뺄셈

-a

a*b

a/b

a%b

a+b

a-b

1

2

2

2

3

3



산술식에서 연산 기호를 생략해서는 안되며, 연산 순위를 강제로 변경 시킬 때 사용하 는 괄호는 반드시 소괄호만을 사용하여야 한다.

산술식 내에 괄호가 사용되었으면 괄호 안의 수식이 제일 먼저 실행되고 동일한 우선 순위인 경우에는 왼쪽에서 오른쪽으로 연산이 수행된다.

『보기』산술식의 우선 순위

x + ( a + b ) * d

| +---+ |

| ① |

| +-------+

| ②

+-----------+


나머지 연산자

나머지 연산자 %는 두 정수 데이터를 나눗셈한 후 그 나머지 값을 구할 때 사용한다.

예를 들어 30 % 4의 경우

30 ÷ 4 = 7 2 이므로 구하는 값은 2가 된다.

나머지 연산자 사용시 주의 사항

① 나눗셈 연산자 /를 사용하여 두 개의 정수끼리 나눗셈을 수행할 때 나눗셈 결과 에서 발생하는 소수이하는 무조건 잘라 버리고 정수값만 취한다.

[보기] 5 / 2의 값 2

② 정수형과 실수형 연산의 경우 연산 결과는 실수형이 된다.

[보기] 5. / 4의 값 1.25

위와 같이 두 피연산자 중 어느 하나가 실수형이면 나머지 정수형 데이터도 실수 형으로 변환된 후 연산이 이루어 진다.

『실습 2-05 』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c2-05.c : 실습 연산자의 활용

*---------------------------------------------------------------------------------------------*/

main( )

{

int a, b, add, sub, mul, div, mod;

a=10, b=5;

add=a+b;

sub=a-b;

mul=a*b;

div=a/b;

mod=a%b;

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

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

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

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

printf("%d%%%d=%d\n",a,b,mod); /* %기호를 출력하려면 %를 두개 */

/* 사용한다. (제Ⅴ장 참고) */

}

☞ 실행 결과

c>c2-05

10+5=15

10-5=5

10*5=50

10/5=2

10%5=0


《연습 6》아래 대입식(치환식)을 실행한 후 각 변수의 값은 ?

1. a=b=c=0;

2. c=(b=(a=5)+1)+2;

참고

C언어에서 대입식은 그 자체가 값을 갖는다. 예를 들면 a=5;의 값은 =기호 우측의 상 수값 5가 대입된 값 자체가 된다. 즉 a=5;의 값은 5인 것이다.

《연습 7》다음 대입식의 연산 순위를 표시하여라.

1. c=(a-b)*c;

2. s=a/b*-c;

《연습 8》아래 프로그램의 실행 결과를 표시하여라.

main( )

{

int a,b,c,d,e;

a=10;

b=c=20;

d=a+b+c;

e=(a-b)*c;

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

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

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

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

printf("(a-b)*c=%d\n",e);

}

《연습 9》a=10, b=20을 정수형 변수에 기억시킨 후 a와 b의 값을 바꾸어 기억시키고 a와 b의 값을 출력시키는 프로그램을 작성하여라.

☞ 실행 결과

초기치 ===> a=10 b=20

교환후 ===> a=20 b=10

《연습 10》1000÷30의 몫과 나머지를 구하여 출력하는 프로그램을 작성하여라.

☞ 실행 결과

1000 / 30 = 33 10

《연습 11》a=5, b=7, c=3일때 다음 식의 값을 구하여 출력하는 프로그램을 작성하여라.

c+(a-b)/(a-c)

☞ 실행 결과

3 + (5-7)^2 / (5-3) = 5

《연습 12》위 수식을 연산식으로 바꾼 후 연산 순위를 표시하여라.

<표1> 각 연산자들의 종류와 우선 순위

+-----------+-------+-----------------------------------+----+

| 대 분 류 |소분류 | 연 산 자 |결합|

| | | |규칙|

+-----------+-------+-----------------------------------+----+높다

| 일 차 식 |primery| ( ) [ ] -> . | -> |

+-----------+-------+-----------------------------------+----+

|단항 연산자| 단 항 | ! ~ ++ -- - cast연산자 * & sizeof | <- |

+-----------+-------+-----------------------------------+----+

| | 승 제 | * / % | -> |

| +-------+-----------------------------------+----+

| | 가 감 | + - | -> | 우

| +-------+-----------------------------------+----+

| |쉬프트 | << >> | -> |

| +-------+-----------------------------------+----+

| | 비 교 | < <= > >= | -> | 선

| +-------+-----------------------------------+----+

|이항 연산자| 등 가 | == != | -> |

| +-------+-----------------------------------+----+

| |비트AND| & | -> |

| +-------+-----------------------------------+----+

| |비트XOR| ^ | -> | 순

| +-------+-----------------------------------+----+

| |비트 OR| | | -> |

| +-------+-----------------------------------+----+

| |논리AND| && | -> | 위

| +-------+-----------------------------------+----+

| |논리 OR| || | -> |

+-----------+-------+-----------------------------------+----+

|삼항 연산자| 조 건 | ? : | <- |

+-----------+-------+-----------------------------------+----+

| 치 환 | | = += -= *= /= %= | |

| | 치 환 +-----------------------------------+ <- |

| 연 산 자 | | >>= <<= &= ^= != | |

+-----------+-------+-----------------------------------+----+

|순차 연산자| 순 차 | , | -> |낮다

+-----------+-------+-----------------------------------+----+

10. 비트 연산자

비트 연산자란 비트조작을 위해 쓰이는 연산자이다. 주의할 점은 오퍼랜드는 정수 또는 정수형이라야 한다.

(1) 비트합 연산자(OR- |) : 좌우의 식을 이진수로 하는 비트합을 구해준다.

a = 117, b = 216일 때 a|b의 결과

117 => 0000 0000 0111 0101

216 => 0000 0000 1101 1000

----------------------------

0000 0000 1111 1101 => 253

비트합 연산자의 용도는 바로 특정한 비트를 1로 세트시킬때 이용된다.

a = 117때 상위 4비트를 1로 한다.

117 => 0000 0000 0111 0101

1111 0000 0000 0000

----------------------------

1111 0000 0111 0101 => 1로 세트하려는 부분만 0으로

(2) 비트곱 연산자(AND- &) : 좌우의 식을 2진수로 하는 비트곱을구해준다.

a = 117, b = 216일 때 a&b의 결과

117 => 0000 0000 0111 0101

216 => 0000 0000 1101 1000

---------------------------

0000 0000 0101 0000 => 80

비트곱 연산자의 용도는 특정 비트를 0의로 리셋하려는 경우에 이용된다.

a = 44149일 때 상위 4비트를 0으로 한다.

44149 => 1010 1100 0111 0101

0000 1111 1111 1111

-------------------------------

0000 1100 0111 0101 => 0으로 리셋하려는 부분만 1로

(3) 배타적 논리합 연산자(XOR- ^) : 좌우의 식을 2진수로 하는 배타적논리합을 구한다.

a = 117, b = 216일 때 a^b의 결과

117 => 0000 0000 0111 0101

216 => 0000 0000 1101 1000

----------------------------

0000 0000 1010 1101 => 173

두 개의 비트가 동일하면 0, 다르면 1이 된다.

(4) 비트반전 연산자(NOT- ~) : ~는 부호를 반전하는 연산자로서 비트1은

0으로, 0은 1로 만든다. (1의 보수 연산자라고도 한다)

a = 117일 때 ~a의 결과

117 => 0000 0000 0111 0101

----------------------------

1111 1111 1000 1010 => -118

(5) shift 연산자( <<,>> ) : 좌측 식의 결과를 우측식만큼 비트를 이동시킨다. 이 때 밀 리는 쪽의 맨 끝 비트는 밀려나오고, 반대쪽이 마지막 비트는 0으로 채워진다.

좌측으로 쉬프트한 경우에는 맨 우측에 무조건 0이 채워지지만 우측으로 쉬프트한 경우에는 부호가 없는 정수이거나 맨 좌측의 비트가 0(양수)이면 0을 채우고, 부호가 있는 정수이고 맨 좌측의 비트가 1(음수)일 때는 1을 채운다. 즉, 쓸데 없이 부호를 바꾸지 않는다고 볼 수 있다.

a = 117일 때 a << 2 의 결과

117 => 0000 0000 0111 0101

----------------------------

00 0000 0001 1101 0100 <= 00

또한 비트 연산자는 등호와 결합해서 치환 연산자를 이룰 수 있다.

a = a >> b; 는 a >>= b, a = a& b; 는 a &= b와 같다.

초보자들은 비트 연산자들의 쓰임에 대해 의구심을 가질지 모르나, 고급프로그램에서는 아주 요긴하게 쓰이고 있다. 비트 연산이 C의 저급언어의특성을 대변하는 특징 주의 하나라고 볼 수 있다. 특히, 한글 출력에 있어서의 비트 연산의 쓰임은 필수적이다. 여러분들이 고급 과정으로 올라가면이러한 이야기들이 모두 이해가 갈 것이다. 지금 우리는 이러한 비트 연산의 기능에 대해서만 알고 있자.


11. 순차 연산자( , ) - comma 연산자

여러개의 식을 한 줄에 나열하는 기능을 가진 순차 연산자는 우선 순위가가장 낮으며, 좌결합성을 가지며, 컴머 우측에 있는 식을 평가하여 얻은값을 결과로 한다. (리스트2의 5행에 순차 연산자가 쓰였다)

x = (y = 1, y++); 는 x = 2, y = 2 가 된다.

x = (y = 1, ++y); 는 y = 1, x = ++y이므로 x = 2, y = 2가 된다.

x = (y = 1, y+1); 은 y = 1, x = y+1이므로 x = 2, y = 1이 된다.

x = (y = 1, z = 2); 는 y = 1, z = 2, x = 2가 된다.

x = (y = 3, y+2); 는 y = 3, x = 5가 된다.

<예제3> 아래 프로그램에서 x와 y의 값은 어떤 결과가 나오겠는가?

<리스트3> #include <stdio.h>

main()

{

int i,j;

i = (j = 15, j+4);

printf("i = %d, j = %d\n",i,j);

}

결과는 직접 실행해 보시기 바란다.

12. 정수형 데이터의 입력

여기에서는 표준 입력 장치인 키보드로 데이터를 변수에 입력시키기 위하여 콘솔 입력 함수 중의 하나인 scanf( )함수를 사용하기로 한다.

1) scanf( )함수의 일반 형식

scanf("형식 지정 문자열", 입력변수,입력변수 );


형식 지정 문자열이란 키보드로 입력할 데이터를 어떠한 형식으로 입력할 것인 가를 지정할 때 사용하는 것으로 다음과 같은 것들이 사용된다.

%d 10진수(decimal)의 정수로 변환하여 입력할때 사용한다.

%o 8진수(octal)의 정수로 변환하여 입력할때 사용한다.

%x 16진수(hexdecimal)의 정수로 변환하여 입력할때 사용한다.

2) 한개의 10진 정수 입력

한 개의 10진 정수 데이터를 입력할 때에는 다음과 같은 형식으로 입력한다.

scanf("%d", &a);

↓ ↴ 변수 지정 ( &:번지 연산자, a:정수형 변수)

형식 지정 문자열

%d 10진수의 정수 형태로 입력할 때 사용하는 형식 지정 문자열이다.

&a 변수 지정시에 사용되는 &는 변수 a의 번지를 나타내는 번지 연산자이다. 번지 연산자에 대한 설명은 제Ⅵ장의 '포인터'에서 상세히 하기로 하고 여기 에서는 단지 기억시킬 변수 앞에 &기호를 붙인다는 사실만 기억하기 바란다.

입력방법 scanf( )함수에 의하여 데이터를 입력할 때에는 키보드로 정수형 데이 터를 입력한 후 [Enter]키를 누르면 된다.

『 실습 c2-06 』예제 프로그램

/*-------------------------------------------------------------------------------------------------

* c2-06.c : 정수데이터의 입력

*-----------------------------------------------------------------------------------------------*/

main( )

{

int a, b;

printf("a=? ");

scanf("%d",&a);

printf("b=? ");

scanf("%d",&b);

printf("\n");

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

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

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

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

}

☞ 실행 결과

c>c2-06

a=? 30 㟺 30을 입력한 후 [Enter]를 누름

b=? 10 㟺

30 + 10 = 40

30 - 10 = 20

30 * 10 = 300

30 / 10 = 3

3) 두 개 이상의 10진 정수 입력

두 개 이상의 10진 정수를 입력하려면 다음과 같이 입력할 개수 만큼의 형식 지정 문자열과 변수를 지정하면 된다.

scanf("%d %d %d", &a,&b,&c);

↓ ↁ변수 지정

형식 지정 문자열

위와 같이 형식 지정 문자열 사이를 공백으로 구분하면 데이터 입력시에 입력할 데이터 들을 공백으로 구분하여 입력하면 된다. 만일 입력 데이터를 콤마(,)로 구분하고 싶으면 다음과 같이 공백 대신에 콤마를 사용하면 된다.

scanf("%d,%d,%d",&a,&b,&c);

『실습 2-07』예제 프로그램

/*-------------------------------------------------------------------------------------------

* c2-07.c : 두 개이상의 10진 정수 입력

*------------------------------------------------------------------------------------------*/

main( )

{

int a,b,c;

printf("a b c = ? ");

scanf("%d %d %d",&a,&b,&c); /*참고①*/

printf("\n");

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

}


☞ 실행 결과 1 ☞ 실행 결과 2

c>c2-07 c>c2-07

a b c = ? 10 20 30㟺 a b c = ? 10 㟺

10 + 20 + 30 = 60 20㟺

30㟺

10 + 20 + 30 = 60


참고①

아래와 같이 printf( )함수와 scanf( )함수를 사용하면 프로그램 실행시 아래의 실행 결과와 같이 데이터를 콤마로 구분하여 입력하여야 한다.

printf("a, b, c = ? ");

scanf("%d, %d, %d", &a, &b, &c);

☞ 실행 결과

c>c2-07

a, b, c = ? 10,20,30㟺

10 + 20 + 30 = 60

데이터의 구분 기호는 공백과 콤마(,)를 사용할 수 있다.

4) 8진수와 16진수의 입력

8진수의 정수 형태로 데이터를 변수에 입력할 때에는 형식 지정 문자열을 %o로 사용하여야 하고 16진수의 정수 형태로 데이터를 입력할 때에는 형식 지정 문자열을 %x나 %X를 사용하여야 한다. 아래에 그 사용예를 나타내었다.

『보기』8진수로 입력할 때의 형식

scanf("%o", &a);

↓ ↴ 변수 지정 ( &:번지 연산자, a:정수형 변수)

8진수 형태로 입력할 것을 지정하는 형식 지정 문자열

『보기』16진수로 입력할 때의 형식

scanf("%x", &a);

↓ ↴ 변수 지정 ( &:번지 연산자, a:정수형 변수)

16진수 형태로 입력할 것을 지정하는 형식 지정 문자열

『실습 2-08』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c2-08.c : 8진수와 16진수의 입력

*---------------------------------------------------------------------------------------------*/

main( )

{

int a, b, c;

printf("a = ? ");

scanf("%o",&a); /* 8진수의 정수로 변환하여 입력 */

printf("b = ? ");

scanf("%d", &b); /*10진수의 정수로 변환하여 입력 */

printf("c = ? ");

scanf("%x", &c); /*16진수의 정수로 변환하여 입력 */

printf("\na = %d \n", a); /*변수의 값을 10진수로 출력 */

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

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

}

☞ 실행 결과 1 ☞ 실행 결과 2

c>c2-08 c>c2-08

a = ? 100 a = ? 11

b = ? 100 b = ? 11

c = ? 100 c = ? af

a = 64 a = 9

b = 100 b = 11

c = 256 c = 175

《연습 13》위 프로그램의 실행 결과를 설명하여라.

《연습 14》3과목 점수를 키보드로 입력하되, 콤마로 데이터를 구분하여 입력한 후 그 합 과 평균을 구하여 출력하는 프로그램을 작성하여라.

☞ 실행 결과

국어,수학,영어 = 90,80,100

국어 = 90

수학 = 80

영어 = 100

총점 = 270

평균 = 90

《연습 15》다음 프로그램의 실행 결과를 생각해 보고 실제로 처리하여 그 결과를 알아보 자.

main( )

{

unsigned int a, b, c;

a = -1;

b = -2;

c = -32768;

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

printf("b = %u \n",b);

printf("c = %u \n",c);

}

unsigned int형 데이터를 10진수 형태로 출력하면 형식 지정 문자열은 %u를 사용한다.

C언어에서는 만일 허용 범위를 넘는 수치를 사용하면 범람(overflow)이 발생하여 엉뚱 한 결과를 얻게 됨에 유의해야 한다. 다른 언어에서와는 달리 overflow가 발생하여도 에러로 처리되지 않으므로 에러 메시지 역시 나타나지 않는다.

『실습 2-09』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c2-09.c : overflow발생시의 출력결과

*---------------------------------------------------------------------------------------------*/

main( )

{

int i=32767;

printf("%d\n",i);

printf("%d\n",i+1); /* overflow발생 */

printf("%d\n",i+2); /* overflow발생 */

}

☞ 실행 결과

c>c2-09

32767

-32768

-32767

《연습 16》위 프로그램의 실행 결과를 설명하여라.

5) 입력 함수

다음은 C의 표준 입력 함수들에 관하여 알아보자.

⼑ getch( )

단일문자를 입력받으며, 입력하는 문자는 화면에 표시되지 않는다(No Echo)

⼑ getchar( )

단일문자를 입력받으며, 입력하는 문자는 화면에 표시된다(Echo Back) <Enter>를 누르면 입력이 종료되며 여러문자를 입력해도 처음의 한 문 자만을 유효하게 받아 들인다.

⼑ gets( )

<Enter>를 누를 때까지 공백을 포함한 모든 문자열을 입력받는다.

13. 정수형 데이터의 출력

이미 printf( )함수는 자주 사용하여 일반적인 사용법은 이미 잘 알고 있다.

여기에서는 정수형(int형) 데이터를 8진수 형태와 16진수 형태의 정수로 출력하는 방법과 출력할 자리수를 지정하여 보기 좋게 출력하는 방법에 대하여 알아 보기로 한다.

printf( )함수의 일반 형식은 다음과 같다.

<일반형식>

printf("형식 지정 문자열", 출력 데이터);


printf( )함수에서 사용되는 형식 지정 문자열이란 데이터를 어떠한 형식으로 출력할 것인가를 지정할 때 사용하는 것으로 다음과 같은 것들을 사용한다.

%d 출력할 데이터를 10진수로 변환하여 출력할때 사용한다.

%o 출력할 데이터를 8진수로 변환하여 출력할때 사용한다.

%x 출력할 데이터를 16진수로 변환하여 출력할때 사용한다.

%X 출력할 데이터를 16진수로 변환하여 출력할때 사용한다.

%x를 사용하면 a~f까지의 수가 소문자로 출력되고 %X를 사용하면 대문자로 출력된다.

『실습 2-10』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c2-10.c : 10진수를 8진수와 16진수로 출력

*---------------------------------------------------------------------------------------------*/

main( ) /*정수형 데이터의 출력 예 */

{

printf("%d \n", 1023); /*10진수로 출력 */

printf("%o \n", 1023); /* 8진수로 출력 */

printf("%x \n", 1023); /*16진수로 출력 */

printf("%X \n", 1023); /*16진수로 출력 */

}

☞ 실행 결과

c>c2-10

1023

1777

3ff

3FF


정수형 데이터를 출력할 때 보기 좋게 출력하기 위하여 자리수를 지정하는 방법을 실습을 통하여 알아 보기로 하자.

『실습 2-11』출력 데이터의 자리수 지정

/*----------------------------------------------------------------------------------------------

* c2-11.c : 출력 데이터의 자리수 지정

*---------------------------------------------------------------------------------------------*/

main( )

{

printf("/%d/\n", 123); /*첫칸부터 123출력 */

printf("/%10d/\n", 123); /*오른쪽을 기준으로 10칸 출력 */

printf("/%-10d/\n", 123); /*왼쪽기준으로 10칸 출력 */

}

☞ 실행 결과

c>c2-11

/123/

/ 123/

/123 /

참고 : 위에서 사용된 형식 지정 문자열의 의미는 다음과 같다.

%d 출력할 숫자의 자리수를 고려하지 않고 첫칸부터 출력할 숫자의 자리수 만 큼 출력할때 사용한다.

%10d 출력할 범위를 10자리로 잡은 후 오른쪽부터 채우면서 출력할 때 사용한 다. 다시 말해서 출력할 총 자리수를 지정한 후 맨 우측자리(1자리)를 기 준으로 하여 출력할 때 사용한다.

%10d 출력할 범위를 10자리로 잡은 후 왼쪽부터 채우면서 출력할 때 사용한 다. 다시 말해서 출력할 총 자리수를 지정한 후 맨 왼쪽를 기준으로 하여 출력할 때 사용한다.

<표1> 포맷 코드 a=1234, b=3.14159, c='A', s="ABCD" (=:공백)

+-------------+--------+------------------------------------+

| code |출력형태| 설 명 |

+-------------+--------+------------------------------------+

|("%d",a) |1234 | 정수의 출력 |

|("%8d",a) |====1234| 수치를 우측을 기준으로 8자리 출력|

|("%-8d",a) |1234====| 좌측을 기준으로 8자리 출력 |

|("%+8d",a) |===+1234| 수치앞에 부호 |

|("%08d",a) |00001234| 수치앞의 공백을 0으로 채움 |

|("%+08d",a) |+0001234| 부호붙이고 공백을 0으로 채움 |

|("%f",b) |3.14159 | 실수의 출력 |

|("%8.3f",b) |===3.142| 전체 8자리, 소수 3자리 출력 |

|("%-8.3f",b) |3.142===| 좌측기준 (소수이하 반올림) |

|("%+8.3f",b) |==+3.142| 부호를 붙여서 출력 |

|("%08.3f",b) |0003.142| 앞의 공백을 0으로 채움 |

|("%+08.3f",b)|+003.142| 부호를 붙이고 공백을 0으로 채움 |

|("%c",c) |A | 문자 출력 |

|("%8c",c) |=======A| 우측을 기준으로 |

|("%-8c",c) |A=======| 좌측을 기준으로 |

|("%s",s) |ABCD | 문자열의 출력 |

|("%8s",s) |====ABCD| 우측을 기준으로 |

|("%-8s",s) |ABCD====| 좌측을 기준으로 |

+-------------+--------+------------------------------------+

⼀ 출력하려는 위치, 문자의 길이가 포맷코드보다 크면 포맷코드는 무시됨








<표2> 형 변환 기호

+----+---------------+----------------------------------------------+

|기호| 인수의 수형 | 변환의 내용 |

+----+---------------+----------------------------------------------+

| %d | 정 수 형 | 인수를 부호있는 10진수로 출력한다 |

| %u | 정 수 형 | 인수를 부호없는 10진수로 출력한다 |

|%ld | 배정도 정수형 | 인수를 부호있는 배정도 정수로 출력한다 |

|%lu | 배정도 정수형 | 인수를 부호없는 배정도 정수로 출력한다 |

| %o | 정 수 형 | 인수를 부호없는 8진수로 출력한다 |

| %x | 정 수 형 | 인수를 부호없는 16진수로 출력한다(소문자로) |

| %X | 정 수 형 | 인수를 부호없는 16진수로 출력한다(대문자로) |

| %c |문자(or정수형) | 인수를 단일문자로 출력 |

| %s |문자열 포인터 | \0앞까지의 문자열이던가 지정된 길이만큼 출력 |

| %f |부동소수점 실수| 고정 소숫점 형식으로 출력 ex: 35.45600 |

| %e |부동소수점 실수| 부동 소숫점 형식으로 출력 ex: 3.54560e+01 |

| %E | | 3.54560E+01 |

| %g |부동소수점 실수| 고정,부동 중 간단한 형식으로 출력(e) |

| %G | | (E) |

+----+---------------+----------------------------------------------+

1) %g, %G 옵션이 없다.(생각해 보면 당연한 것이다)

2) %f와 %e는 같다.(둘 다 부호,소수점,지수부의 유무에 관계없이 받아

들인다.

<예제4> 다음 프로그램의 실행결과를 적어 보아라.

/* 출력 형태 실습 - 여러가지 수를 입력해 보고 출력형 */

/* 태를 예상하는 연습을 한다 */

#include <stdio.h>

main()

{

float a;

int b;

printf("\n임의의 숫자(실수) 입력:");

scanf("%f",&a); /* 874563을 입력해보고, */

/* 0.04568을 입력해보고,*/

/* 756.355를 입력해보라 */

puts("당신이 입력한 수치를");

printf("고정소수점형식으로 출력하면 :%f\n",a);

printf("부동소수점형식으로 출력하면 :%E\n",a);

printf("\n임의의 양수를 입력하라 :");

scanf("%d",&b); /* 3654를 입력해 본다 */

printf("10진수==>8진수==>16진수\n");

printf("%d ==> %o ==> %X\n",b,b,b);

printf("\n 끝낼려면 아무키나 누르시오.");

getch();

}

14. cast 연산자 - (형) 연산자

형변환 연산자는 원하는 데이터의 형을 괄호로 묶어 연산자 앞에 지정해둠으로써 데이터 형을 변환시키는 역할을 한다.

<예제5> cast연산의 보기 - 실행결과를 예측해 보라.

<리스트5> 1: #include <stdio.h>

2: main()

3: {

4: char ch;

5: int i;

6: float fl;

7:

8: fl = i = ch = 'A'

9: printf("ch = %c,i = %d,fl = %2.2f\n",ch,i,fl);

10:

11: ch++;

12: i = fl + 2 * ch;

13: fl = 2.0 * ch + 1;

14: printf("ch = %c, i = %d, fl = %2.2f\n",ch,i,fl);

15:

16: ch = 2.0e30;

17: printf("Now ch = %c\n",ch);

18: }

<설명> 8,9행: 문자 'A'는 변수 ch에 문자로 지정됨. 정수변수 i는 'A' 를 정수로 변환한 65를 받음. fl은 65를 65.00으로 변환한 값을 받음. 11,14행: 문자변수 'A'를 정수 65로 변환하고 여기에 1을 더함. 그리고 정수 66을 문자 B로 변환하여 ch에 저장함 12,14행: ch의 값을 정수로 변환한 다음 2와 곱함. 결과(132)를 실수로 변환해 fl과 더함. 결과 197.00은 정수로 바뀌어 i에 저장됨. 13,14행: ch의 값 'B'를 실수로 변환해 2.0과 곱함. i의 값(197)을 실수로 변환해 더한다. 결과(329.00)은 fl에 저장됨. 16,17행: ch를 매우 큰 수로 치환하므로 예기치 않은 결과가 일어남.

<예제6> cast 연산자의 사용 예

<리스트6> main()

{

int i,j;

i = 372;

j = 5;

printf("%5.3f\n", (float)i / (float)j );

}

14. sizeof 연산자

sizeof는 바로 다음에 나오는 변수나 자료형이 차지하는 메모리의 바이트수를 구해주는 연산자이다.

char c;

sizeof(c); 1의 값을 가진다.

sizeof(int); 2의 값을 가진다.

이렇게 해서 C의 모든 연산자에 대해 간략하게 나마 알아 보았다.초보자들에겐 부담스러운 양이겠지만- 또, 쓸데없는 연산자가 왜이리 많냐고 -,C언어는 고급언어와 저급언어의 특징을 골고루 갖추고 있고, 저급언어의 특성을십분 활용하려면 이러한 연산자들을 잘 사용할 줄 알아야 한다.

16. 연산자를 사용한 예제들

몇 가지 예제를 통하여 연산자들의 실제 사용법에 관하여 살펴보자.

<예제7> 임의의 정수를 입력받아 그수를 2진수로 출력하는 프로그램작성.

(C는 이진수를 지원하지 않는다)

<리스트7> #include <stdio.h>

main()

{

int i,n,k;

printf("정수입력: ");

scanf("&n");

for ( i=15; i >= 0; i--) {

k = (n >> i) & 0x1; /* 쉬프트연산, 비트연산 */

printf("%1d",k);

}

}

<참고> C에서 8진수의 표기는 수치앞에 0을 붙여 표시하고, 16진수는 0x를 붙여 표시한다. 이러한 수들은 항상 부호없는 정수로 취급한다. printf ()함수의 포맷코드는 각각 %o와 %x이다.

C에서 2진수를 출력하려면 최상위 비트부터 그 비트 패턴(1/0)을 출력시키는 방법을 사용한다.

비트 패턴을출력하는 방법은 우선 출력하려는 비트를 최하위 비트가 되도록 우로 쉬프트시킨 다음 이 값을 0000000000000001과 &(AND) 연산을 시켜, 최하위 비트를 제외한 다른 모든 비트들은 0의로 ゼ한다. 만약, 자리수가 16개이면 이런 작업을 16번 반복하여 얻어진 값을 하나씩 출력한다.

<그림1> 상위에서 13번째 비트패턴을 조사하는 과정

*

0 1 0 1 1 0 1 0 1 0 0 0 1 1 1 0 원래의 수

0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 우로 13회 쉬프트

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1과 & 연산

------------------------------------

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 13번째 패턴이 구해졌다!

<예제8> 123456789 와 같이 출력하는 프로그램을 작성하여라.

*0000000* 1 (힌트: 가로+세로의 값이 10일 때와

0*00000*0 2 가로와 세로의 값이 같을 때

00*000*00 3 *을 출력하는 프로그램)

000*0*000 4

0000*0000 5

000*0*000 6

00*000*00 7

0*00000*0 8

*0000000* 9

<리스트8> main()

{

int i,j;

for (i = 1;i <= 9;i++)

for (j = 1;j <= 9; j++)

i == j || i + j == 10 ? printf("*") : printf("0");

printf("\n");

}

위의 프로그램에서 단문과 복문 혼동으로 인한 에러가 있다. 그것을 직접 찾아보기 바란다.








Ⅲ. 기본 명령문과 흐름의 제어

1. 문의 종류

C언어에서 사용되는 문장의 종류에는 다음과 같은 종류가 있다.

+----+

|문장|

+-+--+ +----------+

+-----+ 형 선언문| char, int, double, float

| +----------+

| +----------+ +-----------+

+-----+ 제 어 문 +-+-+ 판 단 문 | if~else, switch~case

| +----------+ | +-----------+

| | +-----------+

| +-+ 반 복 문 | while, for, do~while

| | +-----------+

| | +-----------+

| +-+ 분 기 문 | break, continue, goto, return

| +-----------+

| +----------+

+----+ 기 타 +--+-- comment(주석문)

+----------+ +-- expression statement(식문)

+-- compound statement(복문)

+-- null statement(공문)

1) 주석문(comment)

주석문이란 프로그램을 쉽게 이해할 수 있도록 참고가 되는 내용을 기술하는 문장으로서 '/*'로 시작해서 '*/'로 끝나는 문자들의 집단을 말한다.

[보기] 주석문의 예

/*------------------------

* Test Program

*-------------------------

*/

2) 식문(expression statement)

식문이란 연산자와 피연산자의 결합에 의하여 이루어진 식을 말하며 그 일반 형식은 다음과 같다.

<일반 형식>

expression ;

[보기] 식문의 예

sum=a+b;

y=x+(a+b)*d;

3) 단문(single statement)

프로그램은 어떤 기능을 수행하는 문장들의 집합체로 구성되는데 프로그램을 구성하는 하나하나의 문장을 단문이라고 한다.

[보기] 단문의 예

int a, b, sum;

a=b=10;

sum=a+b;

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

위의 예에서 알 수 있듯이 C언어에서 하나의 문장은 반드시 세미콜론(;)으로 끝난다. 즉 문장의 구분은 세미콜론에 의해서 이루어진다.

4) 복문(compound statement)

복문이란 논리적으로 2개 이상의 문을 { }로 둘러싸서 하나의 문처럼 사용 할 수 있도록 한 것으로 블럭(block)이라고도 한다.

복문의 일반형식은 다음과 같다.

<일반형식>

{

statement;

statement;

}


[보기] 복문의 예

if ( a> 0) {

sum=sum+a;

n=n+1;

}

else {

sum=sum-a;

n=n+1;

}

위 예에서 { }안의 두 문장은 마치 하나의 문장처럼 작동한다. 즉 if문에 의하여 a의 값이 10보다 크면 { }속의 두 문장이 실행되고 a의 값이 10보다 크지 않으면 else다음에 있는 { }속의 두 문장을 실행하게 된다.

5) 공문(null statement)

공문이란 세미콜론(;)만으로 구성된 문장을 말한다. 공문이 사용되는 대표적인 예는 다음과 같이 반복 루프에 의하여 시간을 지연시키는 경우이다.

[보기] 공문의 사용 예

for (i=1;i<=10000;i++)

; /* ;만으로 구성된 공문이다 */

위 예에서 사용된 공문은 i의 값이 1일 때부터 10000이 될 때까지 1씩 증가시키는 작업만을 단순히 반복함으로써 시간을 지연시키기 위하여 사용되었다.

6) 선언문(declaration statement)

C 프로그램 내에서 사용할 변수의 형을 선언하기 위하여 사용되는 문장을 선언문이라고 한다.

C 프로그램에서 사용될 모든 변수는 반드시 그 변수가 사용되기 전에 int, short, long등과 같은 형선언문에 의하여 미리 선언하여야 한다. 그래야 선언된 변수의 이름과 데이터의 형이 성립되고 기억장소가 할당된다.

[보기] 선언문의 예

int counter;

int a, b, c;

int a=0, b=10, c=30;


2. 관계 연산자와 연산식

1) 관계 연산자

관계 연산자는 두 데이터의 대소를 비교하여 판단할 때 사용되는 연산 기호로서 일반적으로 if문과 함께 사용된다.



[보기] 관계 연산자의 종류와 기능

연산자

기 능

우선순위

사용예

>

>=

<

<=

==

!=

~보다 크다

~보다 크거나 같다

~보다 작다

~보다 작거나 같다

~와 같다

~와 같지 않다

1

1

1

1

2

2

a > b

a >= b

a < b

a <= b

a == b

a != b



2) 관계식

두 데이터의 대소 비교를 할 목적으로 관게 연산자를 사용하여 나타낸 식을 관계 연산식 또는 관계식(relational expression)이라고 한다.

관계식도 대입식과 마찬가지로 값을 갖는다. 즉 관계식이 성립하면 관계식의 값은 1이 되고 관계식이 성립하지 않으면 관계식의 값은 0이 된다. 다시 말해서 C언어에서는 참(ture)값은 1로 간주되고 거짓(false)값은 0으로 간주된다.

예를 들어 a=10, b=20일 경우에

result = ( a > b );

라는 관계식이 성립되지 않기 때문에 ( a > b )의 연산 결과 값은 0이 되며 그 값은 result에 기억된다.

3. if 문

if문은 입력된 데이터나 연산 결과를 주어진 조건과 비교하여 조건의 성립여부에 따라 프로그램의 실행할 내용을 달리 하도록 지시하는 명령문으로서 그 일반 형식은 다음과 같다.

<일반형식>

if (조건식)

프로그램 문장;


<순서도>











조건식




False






True


프로그램 문장












[보기] if 문의 사용 예

if (counter<0)

counter = -counter;

printf("value of counter = %d\n",counter);

if문이 실행될 때 counter의 값이 0보다 작으면 counter = -counter;가 실행 된 후 printf( )함수가 실행된다.

반면에 counter가 0이상이면 counter=-counter은 무시되고 printf( )함수가 곧바로 실행된다.

『실습 3-01』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-01.c : if문 연습

*---------------------------------------------------------------------------------------------*/

main( )

{

int number, absolute;

printf("입력 데이터 = ");

scanf("%d",&number);

absolute = number;

if ( number < 0 )

absolute = -number;

printf("%d의 절대값은 %d입니다.\n", number, absolute);

}

☞ 실행 결과 1 ☞ 실행 결과 2

c>c3-01 c>c3-01

입력 데이터 = -123 입력 데이터 = 5600

-123의 절대값은 123이다. 5600의 절대값은 5600이다.

위 프로그램은 키보드로 입력한 정수형 데이터의 절대값을 구하여 출력하는 프로그램이다.

《연습 1》키보드로 정수를 입력하여 그 수가 홀수인지 짝수인지를 판별하여 출력하는 프 로그램을 작성하여라. (단, if문을 사용할 것)


4. if~else 문

if~else 문은 조건의 성립 여부에 따라 두 갈래로 분기되어 각각 다른 작업을 수행한 후 그 다음의 처리를 수행시킬 때 사용하는 명령문으로서 그 일반형식은 다음과 같다.

<일반형식>

if (조건식)

프로그램 문장1;

else

프로그램 문장2;


<순서도>













조건식




False








True




프로그램문장1


프로그램문장2












다음 문장;

[보기] if ~ else문의 사용 예

if (x>=100)

h=h+1; /* 프로그램 문장1 */

else

i=i-1; /* 프로그램 문장 2 */

if문이 실행될 때 x의 값이 100보다 크거나 같으면 h=h+1을 실행하고 x의 값이 100보다 작으면 i=i-1을 실행한다. 즉, 조건식의 성립 여부에 따라 프로그램 문장1이나 프로그램 문장2 중 어느 한쪽이 실행된다.

『실습 3-02』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-02.c : if~else문 연습

*---------------------------------------------------------------------------------------------*/

main( )

{

int number, remainder;

printf("입력 데이터 = ");

scanf("%d",&number);

remainder = number % 2;

if ( remainder == 0)

printf("%d는 짝수이다.\n",number);

else

printf("%d는 홀수이다.\n",number);

}

☞ 실행 결과 1 ☞ 실행 결과 2

c>c3-02 c>c3-02

입력 데이터 = 123 입력 데이터 = 1286

123은 홀수이다. 1286은 짝수이다.

《연습 2》두개의 정수 a, b를 입력하여 a>=b이면 c=a*b, a<b이면 c=a*a+b의 값을 다음 과 같이 출력하도록 츠로그램을 작성하라.

☞ 실행 결과 1 ☞ 실행 결과 2

a , b = ? 20,10 a , b = ? 10,20

a = 20 , b = 10 --> a >= b a = 10 , b = 20 --> a < b

c = a * b ===> 200 c = a * a + b ===> 120

《연습 3》키보드로 하나의 정수 n을 입력하여 1부터 n까지 홀수의 합과 짝수의 합을 계 산하여 출력하는 프로그램을 if~else문을 사용하여 작성하여라.

《연습 4》키보드로 하나의 데이터를 입력하여 그 절대값을 출력하는 프로그램을 if~else 문을 사용하여 작성하여라.

5. 조건 연산자(3항 연산자)

C언어에서는 if~else문을 보다 간결하게 표현하는 방법으로 조건 연산자 (? :)를 제공하고 있다. 즉 조건 연산자는 특정한 if~else문을 약식으로 간결하게 표현할 때 사용하며, 피연산자가 3개 사용 된다하여 3항 연산자라고도 한다. 그리고 조건 연산자에 의해 표현된 식을 조건 연산식이라고 하며 그 일반형식은 다음과 같다.

<일반형식>

조건식 ? 식1 : 식2



1. 조건식은 원칙적으로는 산술형 데이터나 수식이 허용되지만 일반적으로 관계식이나 논리식이 사용된다.

2. 식1과 식2의 데이터 형은 동일하거나 동일한 데이터 형으로 변환이 가능한 것이라 야 한다.

조건 연산식은 조건식의 결과가 참이면 식1의 값이 연산 결과가 되고, 조건식의 결과가 거짓이면 식2의 값이 연산 결과가 된다. 대입식이나 관계식과 마찬가지로 조건식도 값을 갖는다. 따라서 조건 연산자는 식이 사용될 수 있는 곳이면 어디든지 사용할 수 있다.

[보기] 조건 연산식의 사용 예

max = ( a> b) ? a : b;

위의 조건 연산식에서 만일 a가 b보다 크면 max의 값은 a가 되고 그렇지 않으면 max의 값은 b가 된다. 관계 연산자나 논리 연산자가 조건 연산자보다 연산 순위가 높기 때문에 조건식의 전후에 괄호를 사용하지 않아도 관계없으나 조건 연산식을 읽기 쉽게 하기 위해 일반적으로 많이 사용한다.

즉 위의 조건 연산식은 다음과 같이 if~else문으로 표현할 수 있다.

if (a>b)

max=a;

else

max=b;

《연습 5》아래의 문장을 설명하여라.

printf("부호 = %d\n",

(number<0) ? -1 : ((number == 0) ? 0 : 1 ));

『실습 3-03』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-03.c : 조건 연산자의 사용 예1

*---------------------------------------------------------------------------------------------*/

main( )

{

int a, b, c, max

printf("a, b, c = ? ");

scanf("%d, %d, %d", &a,&b,&c);

max=(a>=b) ? a : b;

max=(max>=c) ? max : c;

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

}

☞ 실행 결과 1

c>c3-03

a, b, c = ? 1,2,3

max = 3

『실습 3-04』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-04.c : 조건 연산자의 사용 예2

*---------------------------------------------------------------------------------------------*/

main( )

{

int number, sign;

printf("number = ? ");

scanf("%d", &number);

sign = (number<0) ? -1 : ((number == 0) ? 0 : 1 );

printf("부호 = %d\n",sign);

}

☞ 실행 결과 1 ☞ 실행 결과 2 ☞ 실행 결과 3

c>c3-04 c>c3-04 c>c3-04

number= ? 123 number= ? -45 number= ? 0

부호 = 1 부호 = -1 부호 = 0

6. 논리 연산자와 논리식

1) 논리 연산자

논리 연산자는 몇가지의 조건을 조합할 때 사용하는 연산 기호로 그 종류와 의미는 다음과 같다.

[보기] 논리 연산자의 종류와 기능

연 산 자

기 능

논리식의 예

우선순위

!

&&

||

논리부정(NOT)

논리곱 (AND)

논리합 (OR)

!(4>7) (참)

5>2 && 6>8 (거짓)

5>2 || 6>8 (참)

1

2

3

2) 논리식

논리식 (logical expression)이란 하나 이상의 논리 연산자에 의하여 결합된 식을 말하며 논리 연산식이라고도 한다. 논리식도 대입식이나 관계식과 마찬가지로 식 자체가 하나의 값을 갖는다. 논리식이 성립하면 논리식의 결과가 참(true)이 되어 그 값은 1이 되고 논리식이 성립하지 않으면 논리식의 결과가 거짓(false)이 되어 그 값은 0이 된다.

『실습 3-05』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-05.c : 논리 연산자의 사용 예(1)

*---------------------------------------------------------------------------------------------*/

main( )

{

int a, b;

printf("a, b = ? " );

scanf("%d,%d", &a, &b);

if ( a%3 == 0 && b%4 == 0)

printf("%d와 %d는 3과 4의 배수이다.", a, b);

else

printf("%d와 %d는 3과 4의 배수가 아니다.", a, b);

}

☞ 실행 결과 1 ☞ 실행 결과 2

c>c3-05 c>c3-05

a, b = ? 12,16 a, b = ? 12,15

12와 16은 3과 4의 배수이다. 12와 15는 3과 4의 배수가 아니다.

『실습 3-06』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-06.c : 논리 연산자의 사용 예 (2)

*---------------------------------------------------------------------------------------------*/

main( )

{

int a, b, c, d, e, f;

printf("a, b = ? " );

scanf("%d,%d", &a, &b);

c = a>b;

d = !(a>b);

e = a>10 || b<10;

f = a>10 && b<10;

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

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

printf("a>10 || b<10=====> %d \n", e);

printf("a>10 && b<10====> %d \n", f);

printf("!(a>10 || b<10)===> %d \n", !e);

printf("!(a>10 && b<10)==> %d \n", !f);

}

☞ 실행 결과 1 ☞ 실행 결과 2

c>c3-06 c>c3-06

a, b = ? 10,10 a, b = ? 10,20

a>b =============> 0 a>b =============> 0

!(a>b)============> 1 !(a>b)============> 1

a>10 || b<10=====> 0 a>10 || b<10======> 0

a>10 && b<10 ====> 0 a>10 && b<10 ====> 0

!(a>10 || b<10)====> 1 !(a>10 || b<10)====> 1

!(a>10 && b<10)===> 1 !(a>10 && b<10)====> 1

《연습 6》프로그램 <c3-06.c>의 실행 결과를 설명하여라.

《연습 7》키보드로 하나의 정수를 입력받아 3의 배수이면서 4의 배수인가를 판별하는 프 로그램을 작성하여라.

☞ 실행 결과 1 ☞ 실행 결과 2

a = ? 120 a = ? 130

120은 3과 4의 배수이다. 130은 3과 4의 배수가 아니다.

《연습 8》연도를 키보드로 입력받아 윤년인가 평년인가를 판별하여 출력하는 프로그램을 작성하여라.

참고 : 연도가 400으로 나누어 지면 윤년, 400으로 나누어지지 않지만 100으로 만 나누어 지면 평년, 100으로 나누어 지지 않지만 4로 나누어 지면 윤 년이다.

☞ 실행 결과 1 ☞ 실행 결과 2 ☞ 실행 결과 3

연도 = ? 1991 연도 = ? 2000 연도 = ? 2100

평년이다. 윤년이다. 평년이다.

《연습 9》아래 프로그램의 실행 결과를 나타내고 실행 결과와 같이 출력되는 이유를 설명 하여라.

main( )

{

int a=20, b=20, c=30;

c = ( !(a-b) ? c + a : c - b);

printf ("c = %d", c);

}

7. 복합 if문 ( else~if)

if문 속에 또 다른 if문을 포함 시키면 조건을 복합적으로 비교 판단할 수 있는데 이러한 용도로 사용되는 if문을 복합 if문(nested if문)이라고 한다.

복합 if문의 일반 형식은 다음과 같다.

<일반형식>

if (조건식1)

프로그램 문장1;

else if (조건식2)

프로그램 문장2;

else

프로그램 문장3;


<순서도>



















false









조건식1






























false





true


조건식2



























프로그램 문장1;




true

















프로그램 문장2;


프로그램 문장3;

















































다음문장;

위의 일반형식과 순서도는 다음과 같이 설명할 수 있다.

1. 만일(조건식1)이 성립되면 (프로그램 문장1)을 실행한 후 if 블럭 다음의 문장을 실행 한다.

2. 만일(조건식1)이 성립되지 않으면 (조건식2)를 비교한다. (조건식2)가 성립되면 (프로 그램 문장2)를 실행한 후 if블럭 다음 문장을 실행하고 (조건식2)가 성립되지 않으면 (프로그램 문장3)을 실행한 후 if블럭 다음의 문장을 실행한다.

『실습 3-07』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-07.c : 복합 if문 연습

*---------------------------------------------------------------------------------------------*/

main( )

{

int a;

printf("a = ? ");

scanf("%d",&a);

if (a>0)

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

else

if (a<0)

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

else

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

}

☞ 실행 결과 1 ☞ 실행 결과 2 ☞ 실행 결과 3

c>c3-07 c>c3-07 c>c3-07

a = ? 1234 a = ? -567 a = ? 0

1234 ==>양수 -567 ==>음수 0 ==>0

《연습 10》두 개의 정수 a와 b를 입력하여

1) a가 b보다 크면 a > b

2) a가 b보다 작으면 a < b

1) a가 b보다 같으면 a = b

를 출력하는 프로그램을 작성하여라.

《연습 11》점수를 입력하여 환산 등급을 판정하여 출력하는 프로그램을 작성하여라. 환 산 등급을 판정하는 기준은 다음과 같다.

등급

점수

100~90

89~80

79~70

69~60

59~0


《연습 12》숨겨진 숫자를 다음과 같은 절차로 찾는 프로그램을 작성하여라.

단, 숨겨진 숫자는 임의의 변수에 기억시켜 두기로 한다.

☞ 실행 결과

입력 데이터 = ? 200

==>숨겨진 숫자보다 작다.

입력 데이터 = ? 300

==>숨겨진 숫자보다 크다.

입력 데이터 = ? 250

==>숨겨진 숫자보다 작다.

입력 데이터 = ? 275

==>숨겨진 숫자보다 크다.

입력 데이터 = ? 260

==>숨겨진 숫자보다 크다.

입력 데이터 = ? 255

==>숨겨진 숫자보다 크다.

입력 데이터 = ? 253

==>숨겨진 숫자이다.

8. for 문

1) for문

하나 이상의 명령문을 반복하여 실행하는 기법을 루프(loop) 기법이라고 한다. C언어에는 반복 루프 제어 명령으로서 for, while, do가 있는데 이 중에서 가장 손쉽고 전형적인 반복 구조를 갖는 명령문이 for문이다.

for문의 일반형식은 다음과 같다.

<일반형식>

for (초기식 ; 조건식 ; 루프식)

반복루프


초기식 반복을 제어하는 제어 변수의 초기값을 지정하기 위하여 for루프를 시작 하기 전에 단 한번만 실행된다.

조건식 for루프를 벗어 나기 위한 조건 판단식으로서 조건식의 값이 참인 동안 만 반복 명령문을 실행하다가 조건식의 값이 거짓이 되면 for루프를 벗 어난다.

루프식 제어 변수의 값을 증가시키거나 감소시킨 후 조건식과 비교하여 조건식 이 성립하면 반복 명령문을 계속 실행하고 조건식이 성립하지 않으면 for루프를 벗어난다.

<순서도>










(초기식)

식 1































F



(조건식)


식 2
















다음 문장;





T






















반복 명령문


















(루프식)

식 3



























『실습 3-08』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-08.c : for문 연습

*---------------------------------------------------------------------------------------------*/

main( )

{

int n;

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

printf("%3d",n);

}

☞ 실행 결과

c>c3-08

1 2 3 4 5 6 7 8 9 10

『실습 3-09』for문을 잘못 사용한 예

/*----------------------------------------------------------------------------------------------

* c3-09.c : for문을 잘못 사용한 예

*---------------------------------------------------------------------------------------------*/

main( )

{

int n;

for ( n=11 ; n>1; n=n+1)

printf("%3d",n);

}

☞ 실행 결과

c>c3-08

11 12 13 14 15 16 17 18 19 20

21 22 23 24 25 26 27 28 29 30

31 32 ^c

《연습 13》프로그램 <c3-09.c>를 실행시키면 실행 결과와 같이 출력되는 이유를 설명하여 라.

《연습 14》아래의 출력 결과와 같이 1부터 10까지의 합을 계산하여 출력하는 프로그램을 작성하여라.

☞ 실행 결과

sum = 55

《연습 15》1부터 10까지의 정수 중 홀수만을 출력하는 프로그램을 작성하여라.

☞ 실행 결과

1 3 5 7 9

《연습 16》1부터 100까지의 정수 중에서 홀수의 합을 계산하여 출력하는 프로그램을 작 성하여라.

《연습 17》아래의 성적 데이터를 키보드로 입력하여 90점이상의 학생의 수와 90점 미만 의 학생수를 출력하는 프로그램을 작성하여라.

85, 68, 90, 93, 88, 73, 96, 97



2) 복합 for문 (nested for문)

프로그램의 작성 과정에서 for문에 의하여 반복 처리되는 내용을 다시 반복 시켜야 할 경우가 있는데 흔히 있는데 이 경우에는 for루프를 다시 for문으로 반복시키면 되는데 이러한 형태의 for문을 복합 for문이라고 한다.

『실습 3-10』복합 for문의 예제 프로그램 1

/*----------------------------------------------------------------------------------------------

* c3-10.c : 복합 for문 연습(1)

*---------------------------------------------------------------------------------------------*/

main( )

{

int i, j;

for ( i=1 ; i<=3; i=i+1) {

for ( j=1 ; i<=10; j=j+1)

printf("*");

printf("\n");

}

}

☞ 실행 결과

c>c3-10

**********

**********

**********

《연습 18》아래와 같은 그림을 출력하는 프로그램을 작성하여라.

☞ 실행 결과

**********

**********

**********

**********

**********

《연습 17》아래와 같은 그림을 출력하는 프로그램을 작성하여라.

☞ 실행 결과

*

**

***

****

*****


《연습 18》아래와 같은 그림을 출력하는 프로그램을 작성하여라.

☞ 실행 결과

*

***

*****

*******

*********

***********

『실습 3-11』복합 for문의 예제 프로그램 2

/*----------------------------------------------------------------------------------------------

* c3-11.c : 복합 for문 연습(2)

*---------------------------------------------------------------------------------------------*/

main( )

{

int i, j, k;

for ( i=0 ; i<=9; i++)

for ( j=0 ; i<=9; j++)

for ( k=0 ; k<=9; k++)

if (100*i+10*j+k == i*i*i+j*j*j+k*k*k)

printf("%d %d %d\n", i,j,k);

}

☞ 실행 결과

c>c3-11

0 0 0

0 0 1

1 5 3

3 7 0

3 7 1

4 0 7

《연습 21》직각 삼각형의 세변의 길이가 a, b, c라고 하면 c^2 + a^2의 식이 성립한다. 빗변 c의 값이 100이하인 경우에 위 식을 만족하는 모든수(a, b, c)를 출력하는 프로그램을 작성하여라.

9. 증가 연산자와 감소 연산자

증가 연산자 ++와 감소 연산자 --는 피연산자를 하나만 취할 수 있는 단항 연산자로서 피연산자로 수식이 사용될 수 없다.

1) 증가 연산자(++)

증가 연산자는 변수의 값을 1만큼 증가 시킬때 사용하는 연산자이다.

(1)전위형 증가 연산자 --- 증가시킬 변수 앞에 ++를 표시한 형태로서 전위형은 변수의 값을 먼저 1만큼 증가시킨 다음에 사용한다.

[보기] ++n; /* n에 1을 더한 다음에 처리한다. */

(2)후위형 증가 연산자 --- 증가시킬 변수 뒤에 ++를 표시한 형태로서 후위형은 변수의 현재값을 그대로 사용한 후에 1만큼 증가 시킨다.

[보기] n++; /*먼저 처리한 다음에 n에 1을 더한다.*/

2) 감소 연산자(--)

(1)전위형 감소 연산자 --- 감소시킬 변수 앞에 --를 표시한 형태로서 전위형은 변수의 값 을 먼저 1만큼 감소시킨 다음에 사용한다.

[보기] --n; /*n에서 1을 뺀 다음에 처리한다 */

(2)후위형 감소 연산자 --- 감소시킬 변수 뒤에 --를 표시한 형태로서 후위형은 변수의 현 재값을 그대로 사용한 후에 1만큼 감소시킨다.

[보기] n--; /*먼저 처리한 다음에 n에서 1을 뺀다. */

『실습 3-12』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-12.c : 증가 연산자와 감소 연산자의 사용 예

*---------------------------------------------------------------------------------------------*/

main( )

{

int n=0;

printf("n = %d\n, ++n); /* n에 1을 더한 후 그결과를 출력 */

printf("n = %d\n, n++); /* n의 값을 출력한 후 n에 1을 더함 */

printf("n = %d\n, n); /* 현재 n의 값을 출력 */

printf("n = %d\n, --n); /* n에 1을 뺀후 그결과를 출력 */

printf("n = %d\n, n--); /* n의 값을 출력한 후 n에서 1을 뺌 */

printf("n = %d\n, n); / * 현재의 n의 값을 출력 */

}

☞ 실행 결과

c>c3-12

n = 1

n = 1

n = 2

n = 2

n = 0

n = 0

《연습 22》아래 두 프로그램의 실행 결과를 나타내어라. 만일 실행 결과가 서로 틀리다 면 그 이유는 무엇인가 설명하여라.

[프로그램1]

main( )

{

int i, n=0, sum=0;

for (i=0;i<10;i++)

sum=sum + ++n;

printf("sum=%2d\n",sum);

}

[프로그램2]

main( )

{

int i, n=0, sum=0;

for (i=0;i<10;i++)

sum=sum + n++;

printf("sum=%2d\n",sum);

}

《연습 23》아래 문장을 사칙 연산자만을 사용한 대입식으로 바꾸어 표시하여라

sum=sum + n++;

《연습 24》x=3일때 아래의 대입식을 처리한 후 ans에 기억되는 값은 ?

ans = x / 2 + 7 * ( 1 + x++ );

《연습 25》x =10일때 아래 문장의 실행 결과는 ?

printf("x = %d, x*x++ = %d", x, x*x++);

10. 누적 대입 연산자

누적 대입 연산자는 대입 연산자의 표현을 약술한 형태로 누적 치환 연산자라고도 하며 그 종류와 의미는 다음과 같다.

[보기] 누적 대입 연산자의 종류

연산자

사 용 예

의 미

해 설

+=

-=

*=

/=

%=

a+=b

a-=b

a*=b

a/+b

a%=b

a=a+b

a=a-b

a=a*b

a=a/b

a=a%b

a+b의 값을 a에 기억

a-b의 값을 a에 기억

a*b의 값을 a에 기억

a/b의 값을 a에 기억

a%b의 값을 a에 기억


++x는 x+=1과 같고 --x는 x-=1과 같으며 y*=2*x+20은 y=y*(2*x+20)과 같다.

『실습 3-13』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-13.c : 누적 대입 연산자의 사용예

*---------------------------------------------------------------------------------------------*/

main( )

{

int i, sum=0;

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

sum+=i;

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

}

☞ 실행 결과

c>c3-13

sum = 55

《연습 26》정수 n을 입력하여 n!(1*2*3* *n)의 값을 다음과 같이 출력하도록 프로그 램을 작성하여라.

☞ 실행 결과

n=? 5

1*2*3*4*5 = 120

※ n의 값이 얼마일때 overflow가 발생하는가 관심있게 살펴보자.

《연습 27》두 개의 정수 i와 j를 입력하여 i부터 j까지의 합을 구하여 출력하는 프로그램 을 작성하여라.

☞ 실행 결과 ☞ 실행 결과

i , j = ? 1,100 i , j = ? 11,20

1부터 100까지의 합 = 5050 11부터 20까지의 합 = 155

《연습 28》1부터 10까지의 세제곱값(1^3, 2^3, 3^3 10^3)을 구하여 출력하는 프로 그램을 작성하여라.

☞ 실행 결과

n n^3

1 1

2 8

3 27

4 64

5 125

6 216

7 343

8 512

9 729

10 1000

《연습 29》키보드로 정수 n을 입력하여 n단의 내용을 출력하는 프로그램을 작성하시오.

☞ 실행 결과

몇단 = ? 8

<<8단>>

8 * 1 = 8

8 * 2 = 16

8 * 3 = 24

8 * 4 = 32

ː

《연습 30》정수 n을 입력하여 다음 수식들의 n항까지의 합을 계산하여 출력하는 프로그 램을 작성하여라.

1) 1 + 4 + 7 + 10 + 13 + + n

2) 1 + (1+2) + (1+2+3) + .......+ ( 1+2+3 +n)

《연습 31》n의 값을 키보드로 입력하여 1부터 n까지의 수 중 2, 3, 4로 나누어 지는 수 를 찾아 출력하는 프로그램을 작성하여라.

☞ 실행 결과

n = ? 100

12 24 36 48 60 72 84 96

《연습 32》두 개의 정수 i와 j를 입력하여 i부터 j까지의 3의 배수의 갯수와 그 합을 구하 여 출력하는 프로그램을 작성하여라.

☞ 실행 결과 1 ☞ 실행 결과 2

i , j = 1,10 i , j = 100,120

3의 배수의 개수 = 3 3의 배수의 개수 = 7

3의 배수의 합 = 18 3의 배수의 합 = 777

《연습 33》아래의 실행 결과와 같이 구구단 테이블을 출력하는 프로그램을 작성하여라.

☞ 실행 결과

-------------------------------------------

구 구 단 테 이 블

--------------------------------------------

2 4 6 8 10 12 14 16 18

3 6 9 12 15 81 21 24 27

4 8 12 16 20 24 28 32 36

5 10 15 20 25 30 35 40 45

6 12 18 24 30 36 42 48 54

7 14 21 28 35 42 49 56 63

8 16 24 32 40 48 56 64 72

9 18 27 36 45 54 63 72 81

-------------------------------------------

《연습 34》아래 수식을 만족하는 a와 b의 값을 께산하여 출력하는 프로그램을 작성하여 라. a b

☞ 실행 결과 * b a

a = 1 b = 4 -------------

a = 4 b = 1 5 7 4

《연습 35》두 개의 정수 a와 b를 입력하여 두 수의 최대 공약수를 구하여 출력하는 프로 그램을 작성하여라.

☞ 실행 결과 ☞ 실행 결과

a , b = ? 24,36 a , b = ? 1026,405

최대 공약수 = 12 최대 공약수 = 27

《연습 36》키보드로 정수형 숫자를 입력하여 솟수(prime number)인가 아닌가를 판정하 는 프로그램을 작성하여라.

☞ 실행 결과

number = ? 13

13은 솟수이다.

11. while문

while문은 프로그램 내의 반복 루프를 처리하기 위한 또 하나의 명령문이다.

while문의 일반형식은 다음과 같다.

<일반형식>

while (조건식)

반복루프


조건식 반복 여부를 결정하기 위하여 사용된다. 즉, 조건식이 성립되어야 while 문 다음의 반복될 명령문들이 실행되고, 조건식이 성립되지 않으면 while루프를 벗어나 while다음의 명령문을 실행한다.

<순서도>

























F





조건식
















다음 문장;





T






















프로그램문































『실습 3-14』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-14.c : while문의 연습(1)

*---------------------------------------------------------------------------------------------*/

main( )

{

int counter = 1;

while (counter <= 5) {

printf("%3d",counter);

++counter;

}

}

☞ 실행 결과

c>c3-14

1 2 3 4 5


『실습 3-15』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-15.c : while문의 연습(2)

*---------------------------------------------------------------------------------------------*/

main( )

{

int cont=1, dat, sum=0;

while (cont <= 10) {

printf("data[%d]=? ",cont);

scanf("%d", &dat);

sum += dat ;

++cont;

}

printf("\nSum = %d", sum);

}

☞ 실행 결과

c>c3-15

data[1]= ? 1

data[2]= ? 2

data[3]= ? 3

data[4]= ? 4

data[5]= ? 5

data[6]= ? 6

data[7]= ? 7

data[8]= ? 8

data[9]= ? 9

data[10]= ? 10

Sum = 55

《연습 37》for문과 while문을 비교 설명하여라.

《연습 38》아래의 실행 결과와 같이 5부터 10까지의 정수를 거꾸로 출력하는 프로그램을 while문을 사용하여 작성하여라.

☞ 실행 결과

10 9 8 7 6 5 4 3 2 1

《연습 39》1+2+3+ +n을 계산하여 합이 10,000을 최초로 넘는 n의 값과 그 합을 구하 여 출력하는 프로그램을 작성하여라.

☞ 실행 결과

1+2+3+ +141 = 10011

10000을 초과하는 수 = 141

《연습 40》두 개의 정수 a와 b를 입력하여 두 수의 최대 공약수를 구하여 출력하는 프로 그램을 작성하여라.

☞ 실행 결과 ☞ 실행 결과

a, b = ? 24,36 a, b = ? 1026,405

최대 공약수 = 12 최대 공약수 = 27

《연습 41》키보드로 임의의 정수(long형)를 입력한 후 그 숫자를 거꾸로 출력하는 프로그 램을 작성하여라.

☞ 실행 결과 ☞ 실행 결과

number = 12345 number = 578

reverse = 54321 reverse = 875

《연습 42》n!의 값을 구하여 출력하는 프로그램을 작성하여라.

☞ 실행 결과 ☞ 실행 결과

n = ? 5 n = ? 10

1*2*3*4*5 = 120 1*2*3*4*5*6*7*8*9*10 = 3628800

《연습 43》구구단 테이블을 출력하는 프로그램을 작성하여라.

12. do ~ while 문

for문이나 while문은 조건이 성립되지 않으면 반복루프를 실행시키지 않으나 do~while문은 최소한 한 번은 반복 루프를 실행한다. do~while문의 일반 형식은 다음과 같다.

<일반형식>

do

{ 반복 루프 }

while (조건식);

※ 실행 절차

1. 일단 {반복 루프}를 실행한다. 반복 루프는 단문이나 복문이 모두 사용 될 수 있다.

2. 조건식을 평가하여 조건식의 값이 참이면 {반복 루프}를 반복 실행하고 조건식 의 값이 거짓이면 {반복 루프}를 벗어나 그 다음의 문장을 실행 한다.

<순서도>















프로그램문









T






조건식















F















다음 문장;





『실습 3-16』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-16.c : do~while문의 연습

*---------------------------------------------------------------------------------------------*/

main( )

{

int counter = 1;

do {

printf("%3d",counter);

counter++;

}

while (counter <= 5 );

}

☞ 실행 결과

c>c3-16

1 2 3 4 5

《연습 44》아래의 실행 결과와 같이 5부터 10까지의 정수를 거꾸로 출력하는 프로그램을 do~while문을 사용하여 작성하여라.

☞ 실행 결과

10 9 8 7 6 5


《연습 45》1+2+3+ +n을 계산하여 합이 10,000을 최초로 넘는 n의 값과 그 합을 구하 여 출력하는 프로그램을 작성하여라.

☞ 실행 결과

1+2+3+ +141 = 10011

10000을 초과하는 수 = 141

《연습 46》두 개의 정수 a와 b를 입력하여 두 수의 최대 공약수를 구하여 출력하는 프로 그램을 작성하여라.

☞ 실행 결과 ☞ 실행 결과

a, b = ? 24,36 a, b = ? 1026,405

최대 공약수 = 12 최대 공약수 = 27

《연습 47》키보드로 임의의 정수(int형)를 입력한 후 그 숫자를 거꾸로 출력하는 프로그 램을 작성하여라.

☞ 실행 결과 ☞ 실행 결과

number = 12345 number = 578

reverse = 54321 reverse = 875

《연습 48》n!의 값을 구하여 출력하는 프로그램을 작성하여라.

☞ 실행 결과 ☞ 실행 결과

n = ? 5 n = ? 10

1*2*3*4*5 = 120 1*2*3*4*5*6*7*8*9*10 = 3628800

《연습 49》while문과 do~while문을 비교하여 설명하여라.


13. break문

break문은 for, while, do문 등을 사용한 반복 루프나 switch문으로 부터 빠져 나올때 사용하는 명령문으로서, 단지 break문을 둘러싼 루프 밖으로 빠져나온다. 중첩된(nested) 반복 루프로부터 빠져 나오려면 goto문이나 return문을 사용하는 것이 바람직하다.

break문의 일반 형식은 다음과 같다.

<일반형식>

break;

『실습 3-17』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-17.c : break문 연습

*---------------------------------------------------------------------------------------------*/

main( )

{

int i ;

long factorial = 1;

printf("1");

while(1) {

i++;

if (factorial >10000000)

break;

factorial *=i;

printf("*%d",i);

}

printf(" = %ld", factorial);

}

☞ 실행 결과

c>c3-17

n = ? 1000

1*2*3*4*5*6*7*8*9*10*11 = 39916800

14. switch문

switch문은 여러개의 문장 가운데 특정 조건을 만족하는 문장을 선택하여 수행하는 명령문이다.






switch문의 일반 형식은 다음과 같다.

<일반형식>

switch ( 식 ) {

case 값1 : 프로그램문1

[break;]

case 값2 : 프로그램문2

[break;]

case 값n : 프로그램문n

[break;]

default : 프로그램문

[break;]

}





1. (식)의 값과 값1, 값2, 값n을 비교하여 일치하는 곳의 문을 실행하고, break문에 의하여 switch문을 빠져 나온다. 만일 break문이 없으면 그 다음의 case문을 실행 한다.

2. case 값n 다음에 복수의 프로그램 문이 기술되어도 중괄호로 묶지 않는다.

3. (식)의 값과 일치하는 값이 없으면 default문이 실행된다.






<순서도>










식의 평가
























F






값 1


















프로그램문1


break;



T
















F






값 2


















프로그램문2


break;



T
















F






값 n


















프로그램문n


break;



T












default








































『실습 3-18』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-18.c : switch문 연습

*---------------------------------------------------------------------------------------------*/

main( )

{

int n ;

printf("n = ? ");

scanf("%d", &n);

switch(n) {

case 1 :

printf("one\n");

break;

case 2 :

printf("two\n");

break;

case 3 :

printf("three\n");

break;

default :

printf("not found !!\n");

}

}

☞ 실행 결과 ☞ 실행 결과 ☞ 실행 결과

c>c3-18 c>c3-18 c>c3-18

n = ? 1 n = ? 3 n = ? 7

one three not found !!

《연습 50》다음의 조건을 만족하는 프로그램을 작성하여라.

<조건> 1. 키보드로 n의 값을 입력 받는다.

2. 아래의 실행 결과와 같이 n의 값에 따라 각기 다른 모양을

출력한다.

☞ 실행 결과 ☞ 실행 결과 ☞ 실행 결과 ☞ 실행 결과

n = ? 1 n = ? 2 n = ? 3 n = ? 4

* * * **********

** ** *** ********

*** *** ***** *****

**** **** ******* ***

***** ***** ********* *

《연습 50》키보드로 임의 정수 n을 입력하여 n까지에 포함되는 모든 솟수(prime number)를 찾아 출력하여라.

☞ 실행 결과

n = ? 20

>> 솟수 ( 1~20)

2 3 5 7 11 13 17 19



15. continue문

continue문이 for, while, do문 등의 반복 루프에 사용되면 continue문 이후의 문장을 스잼(skip)하고 루프를 반복한다.(루프의 처음으로 돌아간다)

continue문의 일반 형식은 다음과 같다.

<일반형식>

break;

1. while문이나 do문에서는 조건식을 다시 조사하러 간다.

2. for문에서는 3번째 수식인 루프식을 수행한 다음 두번째의 조건식을 판단하여 루프 의 반복 여부 실행 여부를 결정한다.

『실습 3-19』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-19.c : continue문의 연습

*---------------------------------------------------------------------------------------------*/

main( )

{

int n, sum ;

for (n=1; n<=20; n++ ) {

if (n%2 ==0 || n%3 ==0)

continue;

printf("%3d",n);

sum+=n;

}

printf("\nsum = %d\n",sum);

}

☞ 실행 결과

c>c3-19

1 5 7 11 13 17 19

sum = 73

16. goto 문

goto문은 프로그램을 실행하는 도중에 특정한 곳으로 무조건 분기시킬 때 사용하는 명령문이다. 구조적인 프로그램에서는 여러개의 중첩된 루프에서 벗어나기 위하여 가끔 사용되나, 되도록이면 goto문의 사용을 피하는 것이 좋다.

goto 문의 일반 형식은 다음과 같다.

<일반형식>

goto 레이블;

label goto문에 의해 무조건 분기될 곳을 지정하기 위하여 레이블을 사용한다.

1) 레이블은 변수의 이름을 만드는 규칙에 의하여 만든다.

2) 레이블 뒤에는 반드시 콜론(:)을 붙인다.

3) 레이블은 goto문과 분기되는 명령문의 앞에 기술한다.

『실습 3-20』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-20.c : goto문의 연습(1)

*---------------------------------------------------------------------------------------------*/

main( )

{

int i, j;

for (i=1; i<=9; i++)

for (j=1; j<=9; j++)

if (10*i+j+10*j+i == 99)

goto end;

end:

printf("%d%d + %d%d = %d\n", i,j,j,i,99);

}

☞ 실행 결과

c>c3-20

18 + 81 = 99

위 프로그램은 ij+ji=99를 만족하는 수 중에서 i의 값이 가장 적은 경우를 출력하기 위 해서 goto문을 사용한 예이다.

『실습 3-21』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c3-21.c : goto문의 연습(2)

*---------------------------------------------------------------------------------------------*/

main( )

{

int x, i=1, sum=0;

while (1) {

printf("data %d = ? ", i);

scanf("%d", &x);

if (x<=0) goto end;

sum +=x;

i++;

}

end:

printf("\nsum = %d", sum);

}

☞ 실행 결과

c>c3-21

data 1 = ? 10

data 2 = ? 20

data 3 = ? 30

data 4 = ? 40

data 5 = ? 50

data 6 = ? 0

sum = 150

《연습 52》아래의 수식을 만족하는 a와 b의 값을 모두 출력하는 프로그램을 작성하여라.

a b

+ b a

-------------

8 8

《연습 53》다음 프로그램의 실행 결과는 ?

main( )

{

int i, sum=0;

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

if (i%3==0 || i%5==0)

continue;

else

sum += i

printf("sum = %d ", sum);

}

《연습 54》1부터 100까지의 정수 중에서 3의 배수이거나 5의 배수 또는 7의 배수가 아닌 수의 개수와 그 합을 출력하는 프로그램을 작성하여라.

좋은 프로그램의 평가기준

○ 과거 1) 기억 장치를 적게 사용하는 프로그램

2) 수행 시간이 짧은 프로그램

◇따라서 프로그램이 난해하여 유지 보수가 어려웠다.

○ 현재 1) 오류가 없는 프로그램

2) 이해하기 쉬운 프로그램

3) 쉽게 수정이 가능한 프로그램

4) 효율성이 높은 프로그램

◇즉 누구나 쉽게 이해하고, 신뢰성이 높을 뿐만 아니라 다른 프로그램과의 연관 관계(interface)가 더욱 중요시 된다.

구조적 프로그램(좋은 프로그램)의 구비 요건

1. 시작하는 곳이 한곳 뿐이어야 한다. (one entry point)

2. 끝나는 곳이 한 곳 뿐이어야 한다. (one exit point)

3. 실행되지 않는 부분이 포함 되어서는 안된다. (no dead code)

4. 무한 반복을 포함하지 않아야 한다. (no infinite loop)

구조적 프로그램의 제어 구조.

1. 순차 제어 구조(sequence) 하나하나의 명령처리를 순서대로 실행하도록하는 것을 말하며, 가장 기본적인 구조이다.

시작


A 프로세스


B 프로세스










2. 조건 제어 구조(choice) if~else구조라고도 하며 특정 조건의 판단에 의해 두 가지 경로중 어느 하나를 선택하도록 하는 것을 말하 며 어느 경로를 택하더라도 다시 한 곳에서 만나도록

한다.




T


A 프로세서



























u



시작



condition






























F


B 프로세서


































3. 반복 제어 구조(repetition) do ~ while구조라고도 하며 특정 조건이 만족되는 동안 특정 부분을 계속 반복하도록 하는 것을 말 한다.





A 프로세서





























true

















u











시작







condition










false

































Ⅳ. 배 열

1. 배열이란

배열이란 같은 형의 변수들의 집단을 말하며 데이터를 기억시킬 변수에 일일이 이름을 부여하는 대신에 대표적인 이름을 정하고 첨자를 붙여 개개의 변수를 정의 할 때 사용한다.

2. 1차원 배열

1) 1차원 배열의 선언

배열을 사용하기 이전에 데이터형, 배열명과 차원, 배열의 크기를 미리 선언하여야 한다.

2) 배열 선언의 일반형식

데이터형 배열명[원소의 수]

①데이터형은 int, long, double, char등과 같이 C에서 사용되는 모든 데이터형을 지정할 수 있다.

②배열명은 변수명 정하는 규칙에 의하여 만들어 사용하면 된다.

③원소의 수는 상수나 수식만을 사용할 수 있다.

④[ ]의 개수는 차원을 의미한다. 즉 1차원 배열시에는 [ ]를 하나 사용한다.

[보기] 배열 선언의 예

int man[100], woman[51]

3) 배열 원소

[ ]속에 기술하는 원소의 수는 0부터 시작하는 배열 원소의 개수이다.

[보기] 배열 원소의 구성

int man[100]

man[0]

man[1]

man[2]

man[98]

man[99]

ↁ1번째 원소 (0의 원소부터 시작) ↁ100번째 원소

배열을 구성하는 각각의 원소는 첨자를 사용하여 구분한다. 예를 들어

int mam[100];

과 같이 선언하면 man[0]는 man의 첫번째 원소이며, man[99]는 100번째 원소로서 배열 man의 마지막 원소가 된다.

『실습 4-01』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c4-01.c : 1차원 배열의 사용(1)

*---------------------------------------------------------------------------------------------*/

main( )

{

int a[5];

int index;

for (index=0; index<=4; ++index); {

printf("a[%d] = ? ", index);

scanf("%d", &a[index]);

}

for (index=0; index<=4; ++index)

printf("\na[%d] = %d", index, a[index]);

}

☞ 실행 결과

c>c4-01

a[0] = ? 10

a[1] = ? 20

a[2] = ? 30

a[3] = ? 40

a[4] = ? 50

a[0] = 10

a[1] = 20

a[2] = 30

a[3] = 40

a[4] = 50

《연습 1》10개의 정수형 데이터를 키보드로 입력한 후 그 합과 평균을 계산하여 출력하 는 프로그램을 작성하여라.

《연습 2》아래의 데이터들을 1차원 배열에 기억시킨 후 기억된 순서대로 출력하는 프로 그램을 작성하여라.

☆ 데이터 : 43, 57, 23, 87, 95, 47, 75, 84, 59, 88

《연습 3》아래의 데이터들을 1차원 배열에 기억시킨 후 기억된 역순으로 출력하는 프로 그램을 작성하여라.

☆ 데이터 : 43, 57, 23, 87, 95, 47, 75, 84, 59, 88

《연습 4》1월부터 12월까지의 각 일수를 1차원 배열에 입력시킨 후 아래의 실행 결과와 같이 출력하는 프로그램을 작성하여라.

☞ 실행 결과

1 월 = 31 일 7월 = 31 일

2 월 = 28 일 8월 = 31 일

3 월 = 31 일 9월 = 30 일

4 월 = 30 일 10월 = 31 일

5 월 = 31 일 11월 = 30 일

6 월 = 30 일 12월 = 31 일

1 년 = 365 일

《연습 5》1월부터 12월까지의 각 일수를 1차원 배열에 입력시킨 후 아래의 실행 결과와

같이 홀수 달과 날짜를 출력하는 프로그램을 작성하여라.

☞ 실행 결과

1 월 = 31 일

3 월 = 31 일

5 월 = 31 일

7 월 = 31 일

9 월 = 30 일

11 월 = 30 일

4) 배열과 메모리

배열의 각 원소들은 메모리 내의 연속된 영역에 기억되며 배열명은 이 영역의 시작 번지를 의미한다. 즉 배열명이란 엄밀한 의미로 배열의 시작 번지를 가리킨다고 말할 수 있다.

『실습 4-02』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c4-02.c : 1차원 배열의 사용(2)

*---------------------------------------------------------------------------------------------*/

main( )

{

int i, a[11];

for (i=0; i<=10; i++) {

a[i] = i;

printf("\n&a[%2d] ==> %d, a[%2d] = %d", i, &a[i], i, a[i]);

}

printf("\n\n");

printf("배열 a[0]의 번지 ==> %d\n", &a[0]);

printf("배열 a의 시작 번지 ==> %d\n", a);

}

☞ 실행 결과

c>c4-02

&a[ 0] ==> 3504, a[ 0] = 0

&a[ 1] ==> 3506, a[ 1] = 1

&a[ 2] ==> 3508, a[ 2] = 2

&a[ 3] ==> 3510, a[ 3] = 3

&a[ 4] ==> 3512, a[ 4] = 4

&a[ 5] ==> 3514, a[ 5] = 5

&a[ 6] ==> 3516, a[ 6] = 6

&a[ 7] ==> 3518, a[ 7] = 7

&a[ 8] ==> 3520, a[ 8] = 8

&a[ 9] ==> 3522, a[ 9] = 9

&a[10] ==> 3524, a[10] = 10

배열 a[0]의 시작 번지 ==> 3504

배열 a의 시작 번지 ==> 3504

위 프로그램에서 아래의 두 문장에서 사용된 &a[0]와 a는 같은 의미로 사용 되었음을 반드시 기억하기 바란다.

printf("배열 a의 시작 번지 ==> %d\n", &a[0]);

printf("배열 a의 시작 번지 ==> %d\n", a);

5) 1차원 배열의 초기화

㈀ 대입문에 의한 초기화

static int a[3];

a[0]=170, a[1]=63, a[2]=96;

㈁ 배열 선언시 초기화

배열 원소에 초기값을 대입하기 위해서는 데이터형 앞에 static이라는 단어를 기술한다. 그 이유는 제Ⅶ장의 정적변수를 설명할 때 알아보기로 한다.

배열의 초기값은 다음과 같이 { }안에 첫번째 원소부터 콤마(,)로 구분하여 기술한다.

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

『실습 4-03』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c4-03.c : 1차원 배열의 사용(2)

*---------------------------------------------------------------------------------------------*/

main( )

{

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

int i, sum=0;

for (i=0; i<10; ++i)

sum+=n[i];

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

}

☞ 실행 결과

c>c4-03

sum = 55

초기값의 개수와 배열의 크기가 일치하지 않을 경우

배열 원소를 초기화 할 때 반드시 모든 배열 원소를 초기화 할 필요는 없다.

배열을 static으로 선언할 경우, 초기값을 선언된 원소의 수보다 적게 지정하면 지정한 원소만 초기값이 설정되고 나머지 원소에는 0이 기억된다. 반대로 선언된 원소의 수보 다. 많은 데이터를 지정하면 오류가 발생한다. 만일 초기치를 지정하지 않으면 자동적 으로 모든 원소의 값은 0으로 초기화 된다.

[보기] 배열 원소의 초기화

static int n[10]={3,6,5}

위와 같이 초기치를 설정하면 n[0]=3, n[1]=6, n[2]=5가 설정되고 나머지 원소에 는 0이 설정된다.

『실습 4-04』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c4-04.c : 1차원 배열의 초기화

*---------------------------------------------------------------------------------------------*/

main( )

{

static int f[11]={0,0,1};

int i, sum=1;

for (i=3; i<=10; ++i) {

f[i] = f[i-2] + f[i-1]

sum += f[i];

}

printf(">> Fibonach's Series\n");

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

printf("%4d", f[i]);

printf("\nSum = %d", sum);

}

☞ 실행 결과

c>c4-04

>> Fibonach's Series

0 1 1 2 3 5 8 13 21 34

Sum = 88

《연습 6》아래의 그림과 같이 배열에 초기치를 부여항 후 실행 결과처럼 왼족으로 한 자 리씩 자리를 이동시켜 출력하는 프로그램을 작성하여라.

0

10

20

30

40

50

60

70

80

90

m[0]

m[1]

m[2]

m[3]

m[4]

m[5]

m[6]

m[7]

m[8]

m[9]


☞ 실행 결과

m[0]

m[1]

m[2]

m[3]

m[4]

m[5]

m[6]

m[7]

m[8]

m[9]

10

20

30

40

50

60

70

80

90

0




《연습 7》아래의 데이터들 중에서 최대값과 최소값을 구하여 출력하는 프로그램을 작성하 여라.

☆ 데이터 : 43, 57, 23, 87, 95, 47, 75, 84, 59, 88

☞ 실행 결과

최대값 = 95

최소값 = 23

《연습 8》n개의 정수를 입력하여 입력된 데이터를 분류하여 출력하는 프로그램을 작성하 여라. 단, 범위는 1부터 100사이로 하며, 분류 방법은 어떠한 알고리즘을 사용 하여도 관계없다.

☞ 실행 결과

개수 = ? 5

data[0] = ? 5

data[1] = ? 3

data[2] = ? 7

data[3] = ? 6

data[4] = ? 2

분류 결과

2 3 5 6 7

《연습 9》임의의 난수(4자리수)를 100개 만들어 배열에 기억시킨 후 오름 차순으로 분류 하여 각 줄에 10개씩 출력하는 프로그램을 작성하여라.

╣ 단, 난수는 반드시 만들어서 사용한다.

《연습 10》1차원 배열을 이용하여 아래의 처리 절차에 따라 솟수(prime number)를 구하 여 출력하는 프로그램을 작성하여라. 단, 솟수의 범위는 1부터 100까지로 한 다. 즉 배열의 요소는 101로 선언한 후에 처리한다.

╲ 처리 절차

1. 배열의 모든 요소에 0을 기억 시킨다.

2. 첨자가 2의 배수인 요소에 1을 기억시켜 2의 배수를 제가한 후 2를 출 력시킨다. 즉, 배열 원소의 값이 1이면 제거된 것으로 생각한다.

0

0

1

0

1

0

1

0

1

0

m[0]

m[1]

m[2]

m[3]

m[4]

m[5]

m[6]

m[7]

m[8]

m[9]


3. 첨자가 3인 요소가 1이 아니면 첨자가 3의 배수인 요소에 1을 기억시킨 후 3을 출력한다.

0

0

1

1

1

0

1

0

1

1

m[0]

m[1]

m[2]

m[3]

m[4]

m[5]

m[6]

m[7]

m[8]

m[9]


4. 이상의 절차를 반복한다.

╲ 출력 결과

범위 = ? 20

2 3 5 7 11 13 17 19

3. 2차원 배열

2차원 배열이란 1차원 배열을 여러개 겹쳐 놓은 것으로 생각 할 수 있다. 즉, 행과 열의 평면 구조를 가진 배열로 생각 할 수 있다.

1) 2차원 배열의 선언

2차원 배열에서도 배열 원소들을 사용하기 이전에 데이터형, 배열명과 차원, 배열의 크기 등을 미리 선언 하여야 한다.

2) 배열 선언의 일반형식

데이터형 배열명[원소의 수]

①데이터형은 int, long, double, char등과 같이 C에서 사용되는 모든 데이터형을 지정할 수 있다.

②배열명은 변수명 정하는 규칙에 의하여 만들어 사용하면 된다.

③원소의 수는 상수나 수식만을 사용할 수 있다.

④[ ]의 개수는 차원을 의미한다. 즉 2차원 배열시에는 [ ]를 두개 사용한다.

[보기] 2차원 배열의 선언 예

int box[4][5], blue[ ][20]

3) 배열 원소

[보기] 2차원 배열의 구성

int a[4][5]

a[0][0]

a[0][1]

a[0][2]

a[0][3]

a[0][4]

a[1][0]

a[1][1]

a[1][2]

a[1][3]

a[1][4]

a[2][0]

a[2][1]

a[2][2]

a[2][3]

a[2][4]

a[3][0]

a[3][1]

a[3][2]

a[3][3]

a[3][4]


『실습 4-05』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c4-05.c : 2차원 배열의 사용

*---------------------------------------------------------------------------------------------*/

main( )

{

static int a[3][3];

int i, j;

for(i=0;i<=2;i++)

for (j=0;j<=2;j++) {

printf("a[%d][%d] = ? ", i,j);

scanf("%d, ",&a[i][j]); }

printf("\n-----------------------------------------------");

printf("\n 번호 신장 체중 가슴 ");

printf("\n-----------------------------------------------\n");

for (i=0;i<=2;i++)

{ printf("%4d",i+1);

for (j=0;j<=2;j++)

printf("%6d",a[i][j]);

printf("\n"); }

printf("------------------------------\n");

}

☞ 실행 결과

c>c4-05

a[0][0] = ? 170

a[0][1] = ? 63

a[0][2] = ? 96

a[1][0] = ? 175 ------------------------------------

a[1][1] = ? 65 번호 신장 체중 가슴

a[1][2] = ? 92 ------------------------------------

a[2][0] = ? 178 1 170 63 96

a[2][1] = ? 73 2 175 65 92

a[2][2] = ? 89 3 178 73 89

------------------------------------

4) 2차원 배열의 초기화

㈀ 대입문에 의한 초기화

static int a[3][3];

a[0][0]=170, a[0][1]=63, a[0][2]=96;

a[1][0]=175, a[1][1]=65, a[1][2]=92;

a[2][0]=178, a[2][1]=73, a[2][2]=98;

㈁ 행 단위로 초기화

static int a[3][3]={{170, 63, 96}, {175, 65, 92}, {178, 73, 98}};

또는

static int a[3][3] = {

{170, 63, 96},

{175, 65, 92},

{178, 73, 98}

};

또는

static int a[3][3]={170, 63, 96, 175, 65, 92, 178, 73, 98};


4. 배열의 크기 생략

배열의 크기가 자주 변경되는 경우에는 배열 선언시에 배열의 크기를 생략할 수 있다.

1) 1차원 배열

static int n[ ] = { 1, 2, 3, 4, 5}; /* 배열의 크기는 자동적으로 5로 설정됨 */

2) 2차원 배열

행의 개수 (제1첨자)는 생략할 수 있으나 열의 개수(제2첨자 이후)는 생략이 불가능 하다.

static int n[ ][2]= {

{0,0},

{1,1}, {2,2}, {3,3},

{1,1}, {2,2}, {3,3},

}; /* 자동적으로 n[7][2]로 선언된다. */


《연습 11》3사람의 신장, 체중, 가슴 둘레의 데이터를 행 우선 순위로 2차원 배열에 기억 시킨 후 실행 결과와 같이 출력하는 프로그램을 작성하여라.

☞ 실행 결과

1 번 = ? 170,63,96

2 번 = ? 175,65,92

3 번 = ? 178,73,89

------------------------------------

번호 신장 체중 가슴

------------------------------------

1 170 63 96

2 175 65 92

3 178 73 89

------------------------------------

계 523 201 277

------------------------------------

《연습 12》아래의 실행 결과와 같이 1부터 16까지의 숫자를 배열에 기억시킨 후에 가로 의 합과 세로의 합 및 대각선의 합을 구하여 출력하는 프로그램을 작성하여라. (단, 데이터는 입력시키지 않는다.)

☞ 실행 결과

1 2 3 4 10

5 6 7 8 26

9 10 11 12 42

13 14 15 16 58

28 32 36 40 34

《연습 13》5*5의 2차원 배열을 준비한 후 가로와 세로 및 대각선의 합이 같도록 1부터 25까지의 정수를 배열하는 홀수 마방진 프로그램을 작성하여라.

☞ 실행 결과

11 24 7 20 3

4 12 25 8 16

17 5 13 21 9

10 18 1 14 22

23 6 19 2 15

《연습 14》4*4의 2차원 배열을 준비한 후 가로와 세로 및 대각선의 합이 같도록 1부터 16까지의 정수를 배열하는 짝수 마방진 프로그램을 작성하여라.

☞ 실행 결과

16 2 3 12

5 11 10 8

9 7 6 12

4 14 15 1

《연습 15》어느 학급의 모의 고사 채점 결과가 아래의 표와 같을때 이 데이터를 이용하 여 실행 결과와 같은 성적 일람표를 출력하는 프로그램을 작성하여라. (단, 번 호, 국어, 영어, 수학 데이터는 키보드로 입력한다.)

☞ 실행 결과

2학년 3반 채점 결과 2 - 3 성적 일람표

----+----+----+----- --------------------------------------------------

번호|국어|영어|수학 번호 국어 영어 수학 총점 평균 석차

1 | 70 | 85 | 92 1 70 85 92 247 82 5

2 | 65 | 70 | 73 2 65 70 73 208 69 9

3 | 95 | 85 | 70 3 95 85 70 250 83 3

4 | 96 | 85 | 80 4 96 85 80 261 87 1

5 | 90 | 80 | 64 5 90 80 64 234 78 7

6 | 73 | 65 | 78 6 73 65 78 216 72 8

7 | 64 | 54 | 80 7 64 54 80 198 66 10

8 | 90 | 80 | 85 8 90 80 85 255 85 2

9 | 67 | 90 | 93 9 67 90 93 250 83 3

10 | 73 | 85 | 87 10 73 85 87 245 82 6

---+----+----+----- ----------------------------------

총점 783 779 802 2364 79

----------------------------------


《연습 16》행렬 a와 b의 곱을 구하여 출력하는 프로그램을 작성하여라.

a= bmatrix { col { 1 # 2 # 2}

lcol {5 # 4 # 5}

col { 6 # 7 # 8}}

a= bmatrix { col { 7 # 3 # 4}

lcol {1 # 4 # 6}

col { 6 # 7 # 3}}

《연습 17》아래의 표를 보고 실행 결과와 같이 각 통의 거주자, 각 동의 거주자, 구의 총 인구를 구하여 출력하는 프로그램을 작성하여라.

(단, 3차원 배열을 사용할 것)

A 구

1 동

2 동

1 통

2 통

1 통

2 통

1반

2반

3반

1반

2반

3반

1반

2반

3반

1반

2반

3반

32

26

41

28

29

34

29

40

45

47

42

50


☞ 실행 결과

A구 인구 = 443 1동 = 190 1통 = 99

2통 = 91

2동 = 253 1통 =114

2통 =139
























Ⅴ. 문자 데이터의 처리

1. 문자형의 종류

C언어에서는 문자 형태의 데이터라 하더라도 1바이트 크기의 ASCII코드값으로 저장된다. 즉 C언어에서는 0~255까지의 숫자 (ASCII코드)로 문자형 데이터가 기억 장소에 기억되기 때문에 문자형 데이터를 출력한다는 것은 기억된 수치를 문자의 형태로 출력하는 것이 된다. 문자형 데이터의 종류는 다음과 같다.

종 류

크기

부호

허 용 치

용 도

char

unsigned char

1 Byte

1 Byte

-128~127

0~255

일반적인 영숫자

그래픽 문자 사용



2. 문자 상수

문자 상수는 단일 인용 부호 (' ')로 둘러 싸여 있는 하나의 문자로 구성되며 대부분의 퍼스널 컴퓨터에서는 1바이트 크기의 ASCII 코드값으로 저장된다. 언제나 형식 지정 문자열을 '%d'로 정의하여 int형으로 변환할 수 있다.

[보기] 문자 상수의 예

' ' space(공백) '$'

'A' '='

'B' '['

'a' '"'

3. 문자 변수

문자 변수란 문자 상수(하나의 문자)를 기억시키기 위한 변수를 말한다.

1) 문자 변수의 선언 예

char a, b;

char c = 'C', d = 'D'

2) 문자 변수의 내용 출력

char형 변수의 값을 모니터에 표시할 때에는 printf( )함수를 호출하며 형식 지정 문자열은 %c를 사용한다.

3) 문자 변수의 사용

『실습 5-01』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-01.c : 문자 변수의 내용 출력(1)

*---------------------------------------------------------------------------------------------*/

main( )

{

char a, b, c;

a = 'A', b = 'B', c = '9';

printf("%c %c %c\n", a,b,c);

}

☞ 실행 결과

c>c5-01

A B 9

『실습 5-02』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-02.c : 문자 변수의 내용 출력(2)

*---------------------------------------------------------------------------------------------*/

main( )

{

char a = 'A', b = 'Z', c = '0', d = '9';

printf("%4c%4c%4c%4c\n", a,b,c,d); /*변수 내용 출력 */

printf("%4d%4d%4d%4d\n", a,b,c,d); /*변수 내용의 ASCII값 출력 */

}

☞ 실행 결과

c>c5-02

A Z 0 9

65 90 48 57

『실습 5-03』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-03.c : int형 변수의 내용을 문자로 출력 (3)

*---------------------------------------------------------------------------------------------*/

main( )

{

char a = 65, b = 90, c = 48, d = 57;

printf("%4c%4c%4c%4c\n", a,b,c,d);

}

☞ 실행 결과

c>c5-03

A Z 0 9

《연습 1》키보드로 한 문자를 입력하여 그 문자의 ASCII 코드 값을 10진수 형태로 출력 하는 프로그램을 작성하여라.

《연습 2》 KOREA를 한 문자씩 문자변수에 대입하여 KOREA를 출력하는 프로그램을 작 성하여라.

《연습 3》아래의 실행 결과와 같이 ASCII 코드표를 출력하는 프로그램을 작성하여라. (단, ASCII 코드의 범위는 32~126까지로 한다.)

☞ 실행 결과

| 0 1 2 3 4 5 6 7 8 9 A B C D E F

--|---------------------------------

2| ! " # $ % & ' ( ) * + , - . /

3| 0 1 2 3 4 5 6 7 8 9 : ; < = > ?

4| @ A B C D E F G H I J K L M N O

5| P Q R S T U V W X Y Z [ \ ] ^ _

6| ` a b c d e f g h i j k l m n o

7| p q r s t u v w x y z { | } ~




4. 확장열

1) 확장열 (escape sequence)

단일 인용 부호(' ')안에 \가 사용되면 \다음에 있는 문자는 확장열로 인정된다. \을 포함한 확장열은 하나의 문자 상수로 취급된다.

2) 확장열의 예

확장열

ACSII코드

문자

의 미

\a

\b

\f

\n

\r

\t

\₩

\'

\"

\?

\ooo

\xhhh

\Xhhh

\0

%%

0x07

0x08

0x0c

0x0a

0x0d

0x09

0x5c

0x2c

0x22

0x3f

0ooo

0xhhh

0Xhhh

0x00

BEL

BS

FF

LF

CR

HT

'

"

?

any

any

any

null

percent

벨소리

Back Space

Form Feed

Line Feed 또는 개행(new line)

carriage return(복귀)

Horizontal Tab(수평 탭)

backslash

single quote

double quote

question mark

1~3자리의 8진수

1~3자리의 16진수

1~3자리의 16진수

아무런 동작도 하지않음

% 출력

0은 숫자를 의미하고 0다음의 o는 8진수를, x는 16진수를 의미한다.

3) 확장열을 사용하는 이유

⑴어떠한 문자 코드(ASCII, EBCDIC등)를 사용하는 컴퓨터라도 그 기능이 일치한다.

⑵기호적으로 표현하기 때문에 표현이 간결하고 판독이 용이하다.

⑶제어 문자나 특수 문자를 삽입할 수 있는 유일한 방법으로서 표현할 수 없는 제어 코 드등을 표시하기 위해서는 '\'뒤에 한개의 확장열 또는 ASCII코드를 기술하여 만든다.

<예제> 다음 프로그램의 실행결과를 적어보시오.

1: main( )

2: {

3: int a = 66;

4: float b = 3.14159;

5: char c = 65, *s = "알파벳의 첫문자는 ";

6: printf("%6d\t%-6d\n",a,a);

7: printf("%6c\t%-6c\n",a,a);

8: printf("%8.5f\t%-8.5f\n",b,b);

9: printf("%4c\t%-4c\n",c,c);

10: printf("%4d\t%-4d\n",c,c);

11: printf("\n%s%2c",s,c);

12: printf(". %s\n","끝입니다");

13: }

위의 프로그램에 이상한 부분을 발견하였는가?

char c = 65가 바로 그것인데, 문자 변수에 단일 문자를 기억시킬 때는 '로 묶는다고 하였는데 이 문장에서는 문자 변수에 수치상수를 대입하였으니 오타가 아니냐는 오인도 했을 것이다.

c를 정수형으로 선언하였다면 65가 대입이 된다. 하지만 지금은 문자형으로 선언하였으므로 아스키 코드의 65번 문자 A를 대입하라는 의미가 된다.문자 변수에 수치상수를 대입하면 C에서는 그 수치에 해당하는 아스키 값 을 문자변수에 대입하게 된다(물론,이때 수치의범위는 0 - 255 사이의정수값이라야 한다).

컴퓨터는 문자를 아스키 코드로 기억하고 저장하므로 이 코드를 수치로보느냐, 문자로 보느냐는 출력하기에 달려있다. 다시 말하면, 자료의 변환이 자유롭다는 것이다. 그러므로 정수를 %c로 출력하면 그 값을 아스키 코드로 하는 문자가 출력되며, 문자를 %d로 출력하면 그 문자의 아스키 코드가 출력되게 된다.

5. 문자열 상수

1) 문자열 상수(string constant)

문자열 상수란 인용 부호(" ")로 둘러싸인 문자들을 말하며, 문자 배열 상수(character array constant)라고도 한다. 문자열 상수는 영숫자(alphanumeric), 각종 기호 및 확장열 등으로 구성할 수 있다.

문자 배열 상수라고 하는 이유는 문자 배열로 모든 문자열을 처리하기 때문이다. [보기] 문자열 상수의 예

문자열 상수 "I'm a boy."

구성 요소 'I' '\'' 'm' ' ' 'a' 'b' 'o' 'y' '.' '\0'

배열 요소

I

'

m


a


b

o

y

.

\0

널 종료 문자(문자열의 끝을 표시) ↀ

◀ 문자열을 구성하는 첫 문자부터 널 종료 문자(null terminator)까지를 하나의 문자열로 취급한다. 즉 위 예의 문자열은 11바이트로 구성된다. 널 종료 문자는 문자열의 끝임 을 나타낼 뿐이며, 실제로 출력 되지는 않는다.

2) 문자열 상수 내에서의 확장열

『실습 5-04』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-04.c : 확장열에 의한 특수 문자의 삽입

*---------------------------------------------------------------------------------------------*/

main( )

{

printf("I'm a boy.\n");

printf("\"I'm a boy.\"\n");

printf("C:\\MSC\\WORK.C\n");

printf("\x42\x41\x53\111\103\n");

}

☞ 실행 결과

c>c5-04

I'm a boy.

"I'm a boy."

C:\MSC\WORK.C

BASIC

『실습 5-05』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-05.c : 확장열에 의한 제어 문자의 삽입

*---------------------------------------------------------------------------------------------*/

main( )

{

int i=0;

long j;

printf("\t\t\t"); /*3번째 탭위치로 이동 */

while ( i<=9 ) {

printf("%d",i);

printf("\a"); /* 벨소리 */

printf("\b"); /* back space */

i++;

for (j=1; j<=1----; j++) ; /* 시간 지연 : 공문(;)사용 */

}

}

《연습 4》위 프로그램의 실행 결과를 설명하여라.

《연습 5》커서를 2번째 탭위치로 이동시킨 후 1부터 9까지의 숫자를 왼쪽 방향으로 출력 하는 프로그램을 작성하여라.

6. 문자 데이터의 입출력

1) 한 문자의 입출력

『실습 5-06』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-06.c : 확장열에 의한 제어 문자의 삽입

*---------------------------------------------------------------------------------------------*/

main( )

{

char m;

printf("문자 = ? ");

scanf("%c", &m); /*1문자 입력 */

printf("입력된 문자 = %c\n", m); /*입력된 문자 출력 */

}

☞ 실행 결과 ☞ 실행 결과

c>c5-06 c>c5-06

문자 = ? a 㟺 문자 = ? book 㟺

입력된 문자 = a 입력된 문자 = b

2) 2문자의 입출력

『실습 5-07』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-07.c : scanf( )함수로 2문자 입력

*---------------------------------------------------------------------------------------------*/

main( )

{

char a, b;

printf("문자 = ? ");

scanf("%c%c", &a,&b);

printf("입력된 문자 = %c%c\n", a,b); /*입력된 문자 출력 */

}

☞ 실행 결과 ☞ 실행 결과

c>c5-07 c>c5-07

문자 = ? ab 㟺 문자 = ? 1234 㟺

입력된 문자 = ab 입력된 문자 = 12

3) 공백을 무시한 입력

『실습 5-08』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-08.c : 문자 데이터 입력시 공백의 무시

*---------------------------------------------------------------------------------------------*/

main( )

{

char a, b;

printf("문자 = ? ");

scanf("%c %c", &a,&b);

printf("입력된 문자 = %c%c\n", a,b); /*입력된 문자 출력 */

}

☞ 실행 결과 ☞ 실행 결과

c>c5-08 c>c5-08

문자 = ? ab cd 㟺 문자 = ? 1 2 㟺

입력된 문자 = ab 입력된 문자 = 12

4) scanf( )함수를 여러개 사용한 입력

『실습 5-09』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-09.c : 여러개의 scanf( )함수에 의한 문자 데이터의 입력

*---------------------------------------------------------------------------------------------*/

main( )

{

char a, b, c;

printf("char = ? ");

scanf("%c", &a);

scanf("%c", &b);

scanf("%c", &c);

printf("%c%c%c\n", a,b,c);

}

☞ 실행 결과 ☞ 실행 결과 ☞ 실행 결과

c>c5-09 c>c5-09 c>c5-09

char = ? 12345 㟺 char = ? 1 2 3 㟺 char = ? 1 㟺

123 1 2 2 㟺

1

2

carriage return에 의해 첫칸으로 이동된 후 출력 ↀ






5) 문자를 무시한 입력

『실습 5-10』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-10.c : 키인된 문자를 무시한 입력

*---------------------------------------------------------------------------------------------*/

main( )

{

char a, b, c;

printf("char = ? ");

scanf("%c", &a);

scanf("%*c%c%c", &b,&c);

printf("%c%c%c\n", a,b,c);

}

☞ 실행 결과1 ☞ 실행 결과2 ☞ 실행 결과3

c>c5-09 c>c5-09 c>c5-09

char = ? 12345 㟺 char = ? 1 2 3 㟺 char = ? 1 㟺 234 㟺

134 12 1

위 프로그램의 '실행결과1'에서 알 수 있듯이 형식 지정 문자열 '%*c'는 대응되는 하나의 문자를 무시하는 의미로 사용된다.

《연습 5》두개의 1 Byte 문자를 입력 받아 아래와 같은 모양을 출력하는 프로그램을 작 성하여라.

☞ 실행 결과

char = ? xy

x y

x y

x y

xy

y x

y x

y x







《연습 6》ASCII 코드를 이용하여 아래와 같은 그림을 출력하는 프로그램을 작성하여라.

☞ 실행 결과

ABCDEFGHIJKLMNOPQRSTUVWXYZ

BCDEFGHIJKLMNOPQRSTUVWXYZA

CDEFGHIJKLMNOPQRSTUVWXYZAB

DEFGHIJKLMNOPQRSTUVWXYZABC

EFGHIJKLMNOPQRSTUVWXYZABCD

FGHIJKLMNOPQRSTUVWXYZABCDE

GHIJKLMNOPQRSTUVWXYZABCDEF

HIJKLMNOPQRSTUVWXYZABCDEFG

IJKLMNOPQRSTUVWXYZABCDEFGH

JKLMNOPQRSTUVWXYZABCDEFGHI

KLMNOPQRSTUVWXYZABCDEFGHIJ

LMNOPQRSTUVWXYZABCDEFGHIJK

MNOPQRSTUVWXYZABCDEFGHIJKL

NOPQRSTUVWXYZABCDEFGHIJKLM

OPQRSTUVWXYZABCDEFGHIJKLMN

PQRSTUVWXYZABCDEFGHIJKLMNO

QRSTUVWXYZABCDEFGHIJKLMNOP

RSTUVWXYZABCDEFGHIJKLMNOPQ

STUVWXYZABCDEFGHIJKLMNOPQR

TUVWXYZABCDEFGHIJKLMNOPQRS

UVWXYZABCDEFGHIJKLMNOPQRST

VWXYZABCDEFGHIJKLMNOPQRSTU

WXYZABCDEFGHIJKLMNOPQRSTUV

XYZABCDEFGHIJKLMNOPQRSTUVW

YZABCDEFGHIJKLMNOPQRSTUVWX









아래의 프로그램은 실행 결과와 같이 두 개의 실수와 연산자(+, -, *, /)를 입력하면 그 연산 결과를 출력하는 프로그램이다.

『실습 5-20』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-20.c : 문자열의 활용

*---------------------------------------------------------------------------------------------*/

main( )

{

float value_1, value_2;

char operator;

printf("수식 = ? ");

scanf("%f%c%f", &value_1, &operator, &value_2);

if ( operator == '+')

printf("%.2f\n", value_1+value_2);

else if ( operator == '-')

printf("%.2f\n", value_1-value_2);

else if ( operator == '*')

printf("%.2f\n", value_1*value_2);

else if ( operator == '/')

printf("%.2f\n", value_1/value_2);

}

☞ 실행 결과 ☞ 실행 결과

c>c5-20 c>c5-20

수식 = ? 2+5 수식 = ? 1/3

7.00 0.33




7. 문자 배열

1)문자 배열 원소의 출력

『실습 5-11』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-11.c : 문자 배열 원소의 내용 출력

*---------------------------------------------------------------------------------------------*/

main( )

{

char c[5];

c[0]='I', c[1]='B', c[2]='M', c[3]='P', c[4]='C':

printf("%c%c%c %c%c\n", c[0], c[1], c[2], c[3], c[4]);

}

☞ 실행 결과

c>c5-11

IBM PC


『실습 5-12』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-12.c : int형 배열 변수에 의한 문자 데이터의 입출력

*---------------------------------------------------------------------------------------------*/

main( )

{

int c[5];

c[0]='I', c[1]='B', c[2]='M', c[3]='P', c[4]='C':

printf("%c%c%c %c%c\n", c[0], c[1], c[2], c[3], c[4]);

}

☞ 실행 결과

c>c5-12

IBM PC


2) 문자 배열의 초기화

『실습 5-13』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-13.c : 문자 배열의 초기화

*---------------------------------------------------------------------------------------------*/

main( )

{

static char c[8]={ 'C', 'o', 'm', 'p', 'u', 't', 'e', 'r'};

printf("%c%c%c%c%c%c%c%c\n", c[0],c[1],c[2],c[3],c[4],c[5],c[6],c[7]);

}

☞ 실행 결과

c>c5-13

Computer

참고 : static char c[8] = { 'C', 'o', 'm', 'p', 'u', 't', 'e', 'r'}; 대신에 아래의 어느 한 문 장을 사용할 수 있다.

static char c[ ] = {'C', 'o', 'm', 'p', 'u', 't', 'e', 'r'};

static char c[8] = {"Computer"};

static char c[ ] = {"Computer"};

static char c[8] = "Computer";

static char c[ ] = "Computer";

참고 : 1행에 모두 기술할 수 없는 긴 문자열은 다음과 같이 나누어 기술할 수 있다.

static char p[ ] = "Hello "

"MicroSoft C "

"Compiler \n";

즉 위 문장은 다음의 문장과 같다.

static char p[ ] = "Hello MicroSoft C Compiler \n");

3) 문자 배열 내용의 출력 (1차원 배열)

『실습 5-14』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-14.c : 문자 배열의 초기화

*---------------------------------------------------------------------------------------------*/

main( )

{

static char c[ ]= "KOREA"

printf("%c %c %c %c %c\n", c[0],c[1],c[2],c[3],c[4]);

printf("%s\n",c);

}

☞ 실행 결과

c>c5-14

K O R E A

KOREA

char형 배열의 내용을 모니터에 표시할 때에는 print( )함수에서 형식 지정 문자열 %s를 사용한다.


《연습 7》다음 프로그램을 실행시키면 아래와 같은 출력 결과를 얻을 수 없다.

그 원인을 설명하여라.

main( )

{

static char c[ ]={ 'C', 'o', 'm', 'p', 'u', 't', 'e', 'r'};

printf("%s\n", c);

}

☞ 실행 결과

Computer



『실습 5-15』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-15.c : 문자 배열의 첨자 범위

*---------------------------------------------------------------------------------------------*/

main( )

{

static char str[ ]="String";

int i;

for ( i=0; i<=10; i++)

printf("\nstr[%d] ==> %c", i, str[i]);

}

☞ 실행 결과

c>c5-15

str[0] ==> S

str[1] ==> t

str[2] ==> r

str[3] ==> i

str[4] ==> n

str[5] ==> g

str[6] ==>

str[7] ==>

str[8] ==> ##

str[9] ==>

str[10] ==>

위 프로그램의 실행 결과에서 알 수 있듯이 str[0]에서 str[6]까지만 의미를 갖으며 str[7]이후의 내용은 부정확하다. 따라서 배열 사용시 첨자는 범위내의 값을 사용하여야 한다.


4) 문자 배열 내용의 출력 (2차원 배열)

『실습 5-15』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-16.c : 2차원 문자 배열의 초기치 부여 및 출력

*---------------------------------------------------------------------------------------------*/

main( )

{

int i, j;

static char str[ ][6]={

{'K', 'O', 'R', 'E', 'A'},

{'C', 'H', 'I', 'N', 'A'},

};

for (i=0 ; i<=1; i++)

for (j=0; j<=5; j++)

printf("\nstr[%d][%d] ==> %c", i, j, str[i][j]);

}

☞ 실행 결과

c>c5-16

str[0][0] ==> K

str[0][1] ==> 0

str[0][2] ==> R

str[0][3] ==> E

str[0][4] ==> A

str[0][5] ==> /* \0 (공백문자) */

str[1][0] ==> C

str[1][1] ==> H

str[1][2] ==> I

str[1][3] ==> N

str[1][4] ==> A

str[1][5] ==> /* \0 (공백문자) */

『실습 5-17』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-17.c : 2차원 문자 배열의 초기치 부여 및 출력

*---------------------------------------------------------------------------------------------*/

main( )

{

static char c[ ][8]={ "Korea", "China", "America"};

int i;

for (i=0; i<=2; ++i)

printf("%s\n", c[i]);

}

☞ 실행 결과

c>c5-17

Korea

China

America

위 프로그램의 print( )함수에서 사용된 형식 지저 문자열 %s는 그 대상 인수 (c[i])가 가리키고 있는 번지 이후에 수록되어 있는 데이터를 string(문자열)의 형태로 출력하라는 의미를 갖는다.

%s에 의해서 출력되는 문자열은 문자열의 끝을 알리는 공문자열(\0)을 만날때까지 계속된다. 프로그램 [c5-17.c]는 이와 같은 기능을 이용하여 2차원 배열로 구성된 문자열을 문자열 단위로 출력하는 예를 나타낸 것이다.

5) 문자열의 입력

『실습 5-18』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-18.c : 문자열의 입력

*---------------------------------------------------------------------------------------------*/

main( )

{

static char str[50];

printf("문자열 = ? ");

scanf("%s", str);

printf("입력한 문자열 = %s", str);

}

☞ 실행 결과

c>c5-18

문자열 = ? Korea

입력한 문자열 = Korea

☞ 실행 결과

c>c5-18

문자열 = ? 대한민국은 민주공화국이다.

입력한 문자열 = 대한민국은

scanf( )함수는 문자열을 입력할 때에는 처음 나타나는 공백(또는 탭, 개행문자)이후의 문자열을 읽어 들이지 않는다는 점에 유의해야 한다.

scanf( )함수에 의하여 배열에 데이터를 읽어들일 때에는 번지 연산자 &를 사용하지 않음에 유의 하라. 왜냐하면 배열명은 그 배열의 첫번째 원소의 번지를 의미하기 때 문이다. 자세한 설명은 제Ⅷ장의 포인터에서 구체적으로 알아보기로 한다.

『실습 5-19』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c5-19.c : 문자 배열의 활용(1)

*---------------------------------------------------------------------------------------------*/

main( )

{

static char digits[16]={

'0', '1', '2', '3', '4', '5', '6', '7',

'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'

};

int n[64];

long int decimal;

int temp, base, index=0;

printf("변환할 수(decimal)는 ? ");

scanf("%ld", &decimal);

printf("변환할 진법(base)은 ? ");

scanf("%d", &base);

do {

n[index] = decimal % base;

index++;

decimal /= base;

}

while ( decimal !=0 );

printf("변환된 수 = ");

for (index--; index>=0; index--) {

temp = n[index];

printf("%c", digits[temp]);

}

printf("\n");

}

☞ 실행 결과 ☞ 실행 결과

c>c5-19 c>c5-19

변환될 수(decimal)는 ? 10 변환될 수(decimal)는 ? 123456

변환될 진법(base)은 ? 2 변환될 진법(base)은 ? 16

변환된 수 = 1010 변환된 수 = 1E240



























Ⅵ. 함 수

1. 함수의 개념

함수란 특정한 작업을 수행하도록 작성된 독립적인 프로그램을 말한다. 다시 말해서 함수는 일종의 규격화 된 서브루틴(subroutine)이라 할 수 있다.

함수를 사용하면 프로그램이 모듈화되어 이해하기 쉽고 수정 및 유지 보수가 용이할 뿐만 아니라 자주 사용되는 기능을 프로그램하여 필요할 때 마다 호출하여 사용하면 편리하다.

2. c프로그램의 구성과 함수

+---------------+

| 일반적인 |

| C프로그램 |

+-------+-------+ +----------------+

+-----------+ #header | 선행 처리기 명령

| +----------------+

| +----------------+

+-----------+ main ( ) | 항상 main( )함수부터 실행된다.

| +-------+--------+

| | +--------------+

| +----+ 문장 |

| +-------+------+

| |

| +-----------------+

+-----------+ 함수 a( ) | C프로그램을 구성하는 블럭

| +-------+---------+ +--------------+

| +-----------+ 문장 |

| +------+-------+

| +-----------------+ |

+-----------+ 함수 b( ) |

| +-------+---------+ +--------------+

| +-----------+ 문장 |

| +------+-------+

| |

위 블럭도에서 알 수 있듯이 C프로그램은 최소한 1개 이상의 함수로 구성 된다. 즉 C프로그램은 함수를 단위로 하여 구성된다. 이들 함수는 어떠한 순서로 배열되어 있어도 관계없으며 실행할 프로그램에는 반드시 main( )함수가 1개 포함 되어야 한다. 왜냐하면 프로그램의 실행은 main( )함수로부터 시작되기 때문이다. (함수의 형선언이 엄밀한 ANSI 기준의 C에서는 함수를 사용하기 이전에 함수를 정의하는 것이 좋다. 여기에서는 이 기준에 따르기로 한다.)

C프로그램을 구성할 때 각 기능별로 별도의 함수를 작성한 뒤 복수개의 함수를 하나로 묶어주면 전체 프로그램을 논리적으로 구조화시킬 수 있으며 프로그램의 수정이나 보완시 이에 해당하는 함수만 수정하거나 보완하면 되므로 편리하다.

C프로그램에서 함수는 블럭 맞추기의 블럭에 비유할 수 있다. 즉, 블럭 맞추기에서 블럭들을 조합하여 원하는 형태를 만들듯이 C프로그램에서도 함수들을 적당히 조합하 면 원하는 형태의 프로그램을 만들수 있기 때문이다.

3. 함수의 종류

C프로그램에서 사용할 수 있는 함수는 C언어 자체에 미리 준비되어 있는 시스템 표준 함수와 사용자가 직접 정의하여 사용하는 사용자 정의 함수의 2가지로 구분된다.

시스템 표준 함수는 컴파일러에 의해 자체적으로 준비되어 있는 함수로 사용자가 준비하지 않아도 직접 이용 할 수 있는 함수이며 printf( )함수나 scanf( )함수등을 예로 들수 있다.

반면에 사용자 정의 함수는 사용자가 직접 정의하고 작성하여야 사용할 수 있는 함수를 말한다. 여기에서는 어떠한 기능을 수행하려면 사용자가 직접 작성하여야 하는 사용자 정의 함수에 대하여 구체적으로 알아 보기로 한다.

4. 함수의 정의

C언어에서 사용자 정의 함수는 다음과 같은 형식으로 구성되어야 한다.

<일반형식>

[데이터형] 함수명 ([가인수1], [가인수2], )

가인수 선언문

{

함수 본체

[return(식);]

}


▷데이터 형 : 일반적으로 함수는 그 자체가 값을 갖게 되며 이 값은 이 함수를 호 출(calling)한 프로그램에 되돌려 주게 되는데 이 때 되돌려 주는 값 (return값)의 데이터형을 기술한다.

만일 호출한 함수로 되돌려지는 값이 int형이면 생략할 수 있다.

▷가인수 : 호출 프로그램으로부터 함수가 데이터를 전달받을 때 사용하는 매개 변 수 이다. 즉 호출 프로그램으로부터 전달받아 처리할 데이터 값을 기 억시킬 변수를 말한다. 가인수는 반드시 변수를 사용하여야 하고 그 함수의 시작을 나타내는 {기호 앞에 선언하거나 또는 함수명 뒤의 ( )내 에 기술해야 한다. 가인수가 여러개일 때에는 콤마(,)로 구분한다.

[보기] 함수의 정의

int abs(x)

int x;

{

if (x>=0)

return (x);

else

return (-x);

}

⼔데이터형 : int

⼔함수명 : abs

⼔가인수 : x

⼔가인수 선언문 : int x;

⼔함수 본체+- {

| if (x>=0)

| return(x);

| else

| return(-x);

+- }

⽠ 가인수는 함수를 정의할 때 함수명 뒤의 ( )속에 기술하여도 관계없다.

위의 예에서

int abs(x)

int x;

대신에 아래와 같이 기술하여도 관계없다.

int abs(int x)

5. 함수의 호출

함수를 호출할 때에는 다음과 같은 형식으로 호출한다.

<일반형식>

함수명 (실인수1, 실인수2 );

즉, 호출할 함수명 ( ) 뒤에 ;기호를 붙이면 된다. 그 예는 다음과 같다.

[보기] 함수를 호출하는 문장의 예

abs(x);

6. 인수가 없는 함수

대부분의 함수는 호출하는 함수로부터 데이터를 전달받아 처리한 후 그 처리 결과를 호출한 함수로 되돌려 보내 진다. 그러나 경우에 따라서는 함수 사이에 데이터를 전달하지 않고 다음과 같이 단순히 사용자 정의 함수를 호출할 수도 있다.

『실습 6-01』예제 프로그램

/*----------------------------------------------------------------------------------------------

* c6-01.c : 사용자 함수의 호출

*---------------------------------------------------------------------------------------------*/

func_1( )

{

printf("3 + 5 = %2d\n", 3+5);

}

func_2( )

{

printf("3 - 5 = %2d\n", 3-5);

}

main( )

{

func_1( );

func_2( );

}

☞ 실행 결과

c>c6-01

3 + 5 = 8

3 - 5 = -2

⽠ 위 프로그램은 다음과 같은 절차로 실행된다.

main ( ) +----------→ func_1( )

{ 호출 | {

func_1( ); --+ 복귀 printf("3 + 5 = %2d\n", 3+5

←--------------- }

func_2( );-------------→ func_2( )

←--+ 호출 {

} | printf("3 - 5 = %2d\n", 3-5);

+---------------- }

복귀

위 프로그램에서 함수명과 함수 호출을 위한 문장은 다음과 같다

1. 함수명 : func_1( )과 func_2( )

2. 함수 호출을 위한 문장 : func_1( );과 func_2( );

7. 인수를 갖는 함수

인수(매개 변수 : parameter)란 호출하는 함수로부터 호출되는 함수에 데이터를 전달하기 위한 것으로 함수를 호출하는 쪽에서 본 매개 변수를 실인수라고 하고, 호출되는 함수쪽에서 본 매개 변수를 가인수라 한다.

1) 실인수(actual parameter :actual argument)

함수를 호출하려면 호출할 함수명 뒤에 ;기호를 붙이면 된다. 예를 들어 예제<c6-02.c>에서 함수 sum( )을 호출하기 위해서 다음과 같이 기술하였다.

sum(i);

위 문장에서 ( )속의 i가 실인수이다. 즉 함수가 호출될 때 함수로 넘겨지는 값을 실인수 또는 파라미터(parameter)라고도 한다. 실인수가 여러개일 경우에는 콤마(,)로 구분하여 나열하며, 이 값들은 호출되는 함수의 가인수에 순서대로 전달된다.

실인수는 상수, 변수, 수식 등이 사용될 수 있으나 실제로 함수로 전달되는 것은 상수, 변수, 수식 자체가 아니라 그들이 계산된 결과값이다.

2) 가인수 (formal parameter : formal argument)

함수를 호출할 경우 호출된 함수에서는 호출한 함수로부터 처리할 데이터인 실인수를 받아들일 변수가 필요하게 되는데 이 변수를 가인수라고 한다. 가인수는 데이터(실인수)를 받아 들이는 함수 내의 일시적인 기억 장소이기 때문에 반드시 변수만을 사용해야 한다.

인수가 여러 개일때에는 콤마(,)로 구분하여 나열한다.

예제<c6-01.c>에서처럼 함수에 전달할 인수가 없는 경우에는 함수 호출시에 실인수를 지정하지 않으면 되며 인수를 받아들이는 함수 부분에서도 가인수 리스트를 생략하면 된다.

실인수와 실인수 값을 받아들일 가인수의 데이터형은 반드시 일치해야 한다.

『실습 6-02』하나의 인수를 갖는 함수의 예

/*----------------------------------------------------------------------------------------------

* c6-02.c : 하나의 인수를 갖는 함수

*---------------------------------------------------------------------------------------------*/

sum(n)

int n; /*인수는 반드시 이 위치에 선언한다. */

{

int i, s=0;

for (i=1; i<=n; i++)

s=s+i;

printf("sum(%d) = %d\n",n,s);

}

main ( )

{

int i;

for (i=10; i<=50; i+=10)

sum(i);

}

☞ 실행 결과

c>c6-02

sum(10) = 55

sum(20) = 210

sum(30) = 465

sum(40) = 820

sum(50) = 1275

㽬 실인수와 가인수와의 관계

main ( ) +-- sum( int n)

{ 전달 | 가인수(n)

int i; | {

for (i=10; i<=50; i+=10) | int i, s=0;

sum(i); | for (i=1; i<=n; i++)

} | | s=s+i;

+------------------+ printf("sum(%d) = %d\n",n,s);

실인수(i) }


『실습 6-03』두개의 인수를 갖는 함수의 예

/*----------------------------------------------------------------------------------------------

* c6-03.c : 두개의 인수를 갖는 함수

*---------------------------------------------------------------------------------------------*/

sum(int m, int n)

{

int i , s=0;

for ( i=m; i<=n; i++)

s=s+i;

printf("sum(%d,%d) = %d\n",m,n,s);

}

main( )

{

int i, j;

printf("i, j = ? ");

scanf("%d,%d", &i, &j);

sum(i,j);

}

☞ 실행 결과 ☞ 실행 결과

c>c6-03 c>c6-03

i, j = ? 1, 10 i, j = ? 10, 20

sum(1,10) = 55 sum(10,20) = 165


《연습 1》키보드로 임의의 수를 입력하여 그 절대값을 출력하는 프로그램을 작성하여라.

단, 절대값을 구하는 루틴을 함수로 작성한다.


《연습 2》두개의 정수를 키보드로 입력하여 두 수의 최대 공약수를 구하여 출력하는 프로 그램을 작성하여라. 단, 최대 공약수를 구하는 루틴을 함수로 작성한다.

《연습 3》실행 결과와 같이 그림을 출력하는 프로그램을 작성하여라. 단 main( )함수가 다음과 같을때 space( )함수와 str( )함수를 완성 하도록 한다.

main( ) ☞ 실행 결과

{ n = ? 5

int n, i; *

***

printf("n = ? "); *****

scanf("%d", &n); *******

*********

for (i=1; i<=n; i++)

{

space(n-i);

star(2*i-1);

printf("\n");

}

}




《연습 4》아래의 실행 결과와 같이 정수 n의 값을 입력받아 n의 0승부터 5승까지의 값을 출력하는 프로그램을 작성하여라.

☞ 실행 결과

n = ? 3

3 ^ 0 = 1

3 ^ 1 = 3

3 ^ 2 = 9

3 ^ 3 = 27

3 ^ 4 = 81

3 ^ 5 = 243





8. 함수의 값과 데이터의 형

C언어에서는 호출할 프로그램(함수)으로 인수를 전달할 때에 실인수를 실제의 값으로서 가인수에 전달한다. 그러나 이와는 반대로 가인수의 값을 실인수로 되돌릴 수 없도록 설계되었기 때문에 함수로부터 호출한 함수로 처리한 값을 되돌려 보내기 위해서는 return문을 사용한다. 그리고 이때 되돌려 보내지는 값을 리턴(return)값이라고 하며 이값은 곧 함수의 값이 된다. 함수의 값을 호출한 프로그램으로 되돌려 보낼때 사용하는 return문의 일반 형식은 다음과 같다.

<일반형식>

return (연산식);


return문은 연산식의 결과값을 함수의 값으로 호출한 함수로 되돌려 보낼 때 사용하며 되돌려 보내지는 값의 데이터형은 함수 정의시에 선언된 데이터의 형이다.

return문이 사용되는 경우

①현재 수행되고 있는 함수를 탈출할 때 (제어를 호출한 함수로 이동시키고자 할 때)

②함수를 호출했던 곳으로 함수의 값을 되돌릴 때.

함수의 실행을 중지하고 호출한 곳으로 제어가 이동되는 경우

①함수의 끝까지 실행을 마치고 함수의 끝을 의미하는 }기호를 만날때.

②return문을 만날때.

C언어에서 함수 사이에 데이터를 주고 받는 방법으로 다음과 같은 3가지 방법을 사용하고 있다.

⽤call by value : 실인수의 실제값을 가인수에 전달하는 방식

⽤call by reference : 변수의 주소를 가인수에 전달하는 방식.

⽤외부 변수에 의한 전달 : 외부 변수는 모든 함수에서 참조할 수 있으므로 외부 변수를 이용하여 인수 전달없이 함수 사이에 데이터를 전달하는 방식.

여기에서는 call by value에 대해서만 설명하기로 한다. call by reference에 대해서는 포인터(pointer)를 설명할 때 구체적으로 알아 보기로 한다. 그리고 외부 벼누에 의한 전달방법은 제Ⅶ장의 기억 장소의 종류에서 설명하기로 한다.


『실습 6-04』예제프로그램

/*----------------------------------------------------------------------------------------------

* c6-04.c : 절대값을 구하는 함수

*---------------------------------------------------------------------------------------------*/

int abs(int x)

{

if ( x<0 )

x= -x;

return(x);

}

main ( )

{

int x, result;

printf("x = ? ");

scanf("%d", &x);

result = abs(x);

printf("ABS(%d) = %d\n", x, result);

}

☞ 실행 결과 ☞ 실행 결과 ☞ 실행 결과

c>c6-04 c>c6-04 c>c6-04

x = ? -14 x = ? 14 x = ? 0

ABS(-14) = 14 ABS(14) = 14 ABS(0) = 0

위 프로그램에서 "result = abs(x); "에 의해 함수 abs( )가 호출되면 실인수 x의 값이 abs( )의 가인수에 전달된다. 함수 abs( )는 전달된 값을 이용하여 함수를 처리한 후 그 결과를 함수의 값으로 되돌린다(return한다).

함수 abs( )의 실행이 끝나면 제어가 main( )함수로 옮겨진 후 함수 abs( )의 값이 변수 result에 기억된다.

함수내에서 return문을 만나면 함수의 실행을 종료하고 호출한 함수로 제어가 이동된 다. 따라서 위 함수 abs ( )를 다음과 같이 작성할 수 있다.

int abs(int x) int abs(int x)

{ {

if ( x<0 ) return ( (x<0) ? -x : x);

return (x); }

else

return (-x);

}

『실습 6-05』예제프로그램

/*----------------------------------------------------------------------------------------------

* c6-05.c : 거듭제곱 구하는 함수

*---------------------------------------------------------------------------------------------*/

int power(int x, int n)

{

int i, p=1;

for (i=1; i<=n; ++i)

p = p * x;

return (p);

}

main( )

{

int x, n, result;

printf("x,n= ? ");

scanf("%d, %d", &x, &n);

result = power(x, n);

printf("%d ^ %d = %d\n", x, n, result);

}

☞ 실행 결과 ☞ 실행 결과

c>c6-05 c>c6-05

x,n= ? 3,2 x,n= ? 5,3

3 ^ 2 = 9 5 ^ 3 = 125

『실습 6-06』예제프로그램

/*----------------------------------------------------------------------------------------------

* c6-06.c : 최대공약수 구하는 함수

*---------------------------------------------------------------------------------------------*/

int gcd(int u, int v)

{

int temp;

while ( v != 0 ) {

temp = u % v;

u = v;

v = temp;

}

return(u);

}

main( )

{

int a, b, result;

printf("a, b = ? ");

scanf("%d, %d", &a, &b);

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

}

☞ 실행 결과 ☞ 실행 결과

c>c6-06 c>c6-06

a,b= ? 12,64 a,b= ? 240,128

GCD(12, 64) = 4 GCD(240, 128) = 16

《연습 6》실행 결과와 같이 키보드로 n의 값을 입력하여 1부터 n까지의 정수의 합을 구 하여 출력하는 프로그램을 작성하여라.

☞ 실행 결과

n = ? 10

sum = 55

《연습 7》정수 n을 입력하여 1 + (1+2) + (1+2+3) +......+(1+2+3+ +n)의 계산 결과를 출력하는 프로그램을 작성하여라.

《연습 8》키보드로 3개의 정수형 데이터를 입력하여 최소값을 구하여 출력하는 프로그램 을 작성하여라.

《연습 9》키보드로 10개의 정수형 데이터를 입력하여 최대값과 최소값을 구하여 출력하 는 프로그램을 작성하여라.

《연습 10》n과 r의 값을 입력하여 다음과 같은 2항 계수의 값을 구하여 출력하는 프로그 램을 작성하여라.

rm C = n over r = n! over { r!(n-r)! }


☞ 실행 결과 ☞ 실행 결과

n,r = ? 3,2 n,r = ? 10,3

3 C 2 = 3 10 C 3 = 120


《연습 11》키보드로 년, 월, 일을 입력하여 그 날의 요일을 구하여 출력하는 프로그램을 작성하여라.

※참고: 서기 1년 1월 1일은 월요일이다. 그리고 년이 400으로 나누어지면 윤년, 400으로 나누어 지지 않고 100으로만 나누어 지면 평년, 100으로 나누어 지지 않고 4로 나누어 지면 윤년이다.



9. 반복적인 함수의 호출

아래의 예에서와 같이 호출된 함수가 다른 함수를 다시 호출하는 것도 가능하다.

『실습 6-07』예제프로그램

/*----------------------------------------------------------------------------------------------

* c6-07.c : 함수를 반복적으로 호출하는 예

*---------------------------------------------------------------------------------------------*/

float abs (float x) /* 절대값을 계산하는 함수 */

{

return ( (x<0) ? -x : x);

}

float sqr(x) /* 평방근을 계산하는 함수 */

float x;

{

float epsilon = .000001;

float guess = 1.0 ;

while ( abs ( guess * guess - x ) >= epsilon)

guess = ( x / guess + guess ) / 2.0;

return(guess);

}

main( )

{

float x, result;

printf("x = ? " );

scanf("%f", &x);

result = sqr(x);

printf("SQR(%.1f) = %f\n", x, result);

}

☞ 실행 결과 ☞ 실행 결과

c>c6-07 c>c6-07

x = ? 2 x = 169

SQR(2.0) = 1.414214 SQR(169.0) = 13.000000



10. 함수의 순환 (recursion)

함수는 다른 함수를 호출하여 이용할 수 있을 뿐만 아니라 자기 자신의 함수를 다시 불러 사용할 수 있는데 함수의 이러한 성질을 함수의 순환 또는 되부름이라고 한다.

프로그램 작성시 함수의 순환을 이용하면 보다 효율적인 프로그램을 작성 할 수 있다.

『실습 6-08』예제프로그램

/*----------------------------------------------------------------------------------------------

* c6-08.c : 함수의 순환을 이용한 숫자 출력

*---------------------------------------------------------------------------------------------*/

int p(int n)

{

if (n>0) {

p(n-1);

printf("%3d",n);

}

}

main( )

{

p(10);

}

☞ 실행 결과

c>c6-08

1 2 3 4 5 6 7 8 9 10


《연습 12》실행 결과와 같이 10부터 1까지의 숫자를 출력하는 프로그램을 순환을 이용하 여 작성하여라.

☞ 실행 결과

10 9 8 7 6 5 4 3 2 1


『실습 6-09』예제프로그램

/*----------------------------------------------------------------------------------------------

* c6-09.c : 함수의 순환을 이용한 factorial의 계산

*---------------------------------------------------------------------------------------------*/

long factorial (int f)

{

if (f<=1)

return(1);

else

return( f * factorial ( f - 1 ) );

}

main( )

{

int x;

long result;

printf("x = ? ");

scanf("%d", &x);

result = factorial(x);

printf("%d ! = %ld\n", x, result);

}

☞ 실행 결과

c>c6-09

x = ? 6

6 ! = 720

▷해설 : 위 프로그램의 실행 과정을 개념적으로 표현하면 다음과 같다.

factorial(6) = 6 * factorial(5)

= 6 * 5 * factorial(4)

= 6 * 5 * 4 * factorial(3)

= 6 * 5 * 4 * 3 * factorial(2)

= 6 * 5 * 4 * 3 * 2 * factorial(1)

= 6 * 5 * 4 * 3 * 2 * 1

= 720

『실습 6-10』예제프로그램

/*----------------------------------------------------------------------------------------------

* c6-10.c : 함수의 순환을 이용한 최소 공배수 계산

*---------------------------------------------------------------------------------------------*/

int gcd (int u, int v)

{

return ( v ? gcd(v, u%v) : u);

}

main ( )

{

int a, b, result;

printf("a,b= ? ");

scanf("%d, %d", &a, &b);

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

}

☞ 실행 결과 ☞ 실행 결과

c>c6-10 c>c6-10

a,b= ? 12,64 a,b= ? 240,128

GCD(12, 64) = 4 GCD(240, 128) = 16

《연습 13》위 프로그램에서 함수 gcd( )의 실행 과정을 개념적으로 설명하여라.

《연습 14》아래의 실행 결과와 같이 1부터 10의 배수들까지의 합을 출력하는 프로그램을 순환을 이용하여 작성하여라.

☞ 실행 결과

1부터 10까지의 합 = 55

1부터 20까지의 합 = 210

1부터 30까지의 합 = 465

1부터 40까지의 합 = 820

1부터 50까지의 합 = 1275

1부터 60까지의 합 = 1830

1부터 70까지의 합 = 2485

1부터 80까지의 합 = 3240

1부터 90까지의 합 = 4095

1부터 100까지의 합 = 5050

《연습 15》아래의 실행 결과와 같이 n의 값을 입력받아 n의 0승부터 5승까지의 값을 출 력하는 프로그램을 순환을 이용하여 작성하여라.

☞ 실행 결과

n = ? 3

3 ^ 0 = 1

3 ^ 1 = 3

3 ^ 2 = 9

3 ^ 3 = 27

3 ^ 4 = 81

3 ^ 5 = 243


『실습 6-10』예제프로그램

/*----------------------------------------------------------------------------------------------

* c6-10.c : main( )함수의 호출

*---------------------------------------------------------------------------------------------*/

main( )

{

static int i=0;

i++;

printf("%3d", i);

if (i != 10)

main( )

}

☞ 실행 결과

c>c6-10

1 2 3 4 5 6 7 8 9 10





11. 리턴값이 없는 함수 (void함수)

ANSI표준의 C언어에서는 값을 반환하지 않는 함수를 "void형 함수"라고 한다. K&R정의에서는 찾아볼 수 없다. ANSI에서도 종래에는 값을 반환하지 않는 함수를 int형과 혼용하여 왔는데 최근에 엄격한 형선언을 하고자 하는 추세에 따라 void형 함수를 추가하였다.

『실습 6-11』예제프로그램

/*----------------------------------------------------------------------------------------------

* c6-11.c : void함수

*---------------------------------------------------------------------------------------------*/

void space(int blank)

{

int counter;

for ( counter=0; counter<=blank; counter++)

printf(" ");

}

void main( )

{

int counter;

for ( counter=0; counter<8; counter++ ) {

space(counter);

printf("ABCDEFGHIJK\n");

}

}

☞ 실행 결과

c>c6-11

ABCDEFGHIJK

ABCDEFGHIJK

ABCDEFGHIJK

ABCDEFGHIJK

ABCDEFGHIJK

ABCDEFGHIJK

ABCDEFGHIJK

ABCDEFGHIJK

12. 함수와 배열

상수나 변수 또는 수식 등의 값이 호출할 함수에 인수로 넘겨질 수 있듯이 배열 원소의 값이나 배열 전체를 함수에 넘길 수 있다. 여기에서는 배열의 원소와 배열 전체를 함수에 인수로 넘겨서 처리하는 방법에 대하여 알아보기로 한다.

1) 배열 원소를 인수로 사용할 경우

하나의 배열 원소의 값을 호출할 함수에 실인수로 넘기려면 상수나 변수 등을 함수의 실인수로 사용하듯이 배열의 원소를 함수의 실인수로 사용하면 된다.

『실습 6-12』배열 원소를 실인수로 사용하는 예

/*----------------------------------------------------------------------------------------------

* c6-12.c : 3의 배수인 배열 원소의 개수를 구하는 프로그램

*---------------------------------------------------------------------------------------------*/

int sub(int x)

{

return ( ( x%3==0) ? 1 : 0 ) );

}

main( )

{

static int a[ ]={

128, 254, 123, 676, 235,

129, 756, 543, 239, 125

};

int i, sum=0;

for ( i=0; i<=9; i++)

sum += sub( a[i] );

printf("3의 배수의 갯수 = %d\n", sum);

}

☞ 실행 결과

c>c6-12

3의 배수의 개수 = 4

2) 1차원 배열 전체를 인수로 사용할 경우

배열 전체의 내용을 호출될 함수로 전달할 때에는 배열의 이름만을 호출하는 함수의 실인수로 사용하면 된다. 아래의 예에서 쉽게 이해할 수 있을 것이다.

『실습 6-13』배열 원소를 실인수로 사용하는 예

/*----------------------------------------------------------------------------------------------

* c6-12.c : 문자열의 길이를 구하는 프로그램

*---------------------------------------------------------------------------------------------*/

int strlen(x)

char x [ ];

{

int i=0;

while ( x[i] != '/0' )

i++;

return (i);

}

main( )

{

static char str[ ] = "Hong Gil Dong";

printf("\"%s\" = %d 문자 \n", str, strlen(str));

}

☞ 실행 결과

c>c6-13

"Hong Gil Dong" = 13문자

main( )함수의 printf( )함수내에 사용된 str의 의미는 다음과 같다.

printf("\"Hong Gil Dong\", = %d 문자\n", strlen(str));

배열 str의 첫번째 원소인 str[0]의 번지를↲

의미

《연습 16》실행 결과와 같이 키보드로 대문자들로 구성된 단어를 입력하면 소문자로 바 꾸어 출력하는 프로그램을 작성하여라.

☞ 실행 결과

uppercese = ? KOREA

lowercase = korea

『실습 6-14』1차원 배열을 실인수로 사용하는 예

/*----------------------------------------------------------------------------------------------

* c6-14.c : 문자열을 거꾸로 출력하는 프로그램

*---------------------------------------------------------------------------------------------*/

reverse(x)

char x[ ];

{

int n;

for (n=5; n>=0; n--)

printf("%c", x[n]);

}

main( )

{

static char str[ ]="ABCDEF"

reverse(str);

}

☞ 실행 결과

c>c6-14

FEDCBA

『실습 6-15』1차원 배열을 실인수로 사용하는 예

/*----------------------------------------------------------------------------------------------

* c6-15.c : alphabet show

*---------------------------------------------------------------------------------------------*/

sub(x)

char x[ ];

{

printf("%s\n",x);

}

main( )

{

static char str[ ]="ABCDEFGHI";

int n;

for (n=8 ; n>=0; n--)

sub(&str[n]);

}

☞ 실행 결과

c>c6-15

I

HI

GHI

FGHI

EFGHI

DEFGHI

CDEFGHI

BCDEFGHI

ABCDEFGHI

『실습 6-16』1차원 배열을 실인수로 사용하는 예

/*----------------------------------------------------------------------------------------------

* c6-16.c : 분류(sort)프로그램

*---------------------------------------------------------------------------------------------*/

sort(s, n)

int n, sl ];

{

int i, j, k, min;

for (i=0; i<n-1; i++) {

k=i

min=s[k];

for (j=j+1 ; j<n ; j++)

if ( s[j]<min ) {

k=j;

min = s[k];

}

s[k]=s[i];

s[i]=min;

}

}

main( )

{

int i, n=10;

static int a[ ] = {

21,53,46,93,12,34,24,23,75,11

};

sort(a,n);

for ( i=0; i<9; i++)

printf("%3d", a[i]);

}

☞ 실행 결과

c>c6-16

11 12 21 23 24 34 46 53 75

『실습 6-17』2차원 배열을 1차원 배열로 처리하는 예

/*----------------------------------------------------------------------------------------------

* c6-17.c : 2차원 배열을 1차원 배열로 처리하는 예

*---------------------------------------------------------------------------------------------*/

int tot(jum, n)

int jum[ ], n;

{

int index, sum=0;

for ( index = 0 ; index<n; index++)

sum += jum [index];

return (sum);

}

main( )

{

static int jum[5][4]={

{100, 78, 96, 100},

{ 98, 98, 32, 92},

{ 85, 57, 86, 59},

{ 76, 78, 77, 79},

{ 67, 90, 88, 85}

};

int line, col, jum_sum;

float jum_ave;

printf("============================\n");

printf(" 국어 영어 수학 전산 총점 평균 \n");

printf("============================\n");

for ( line=0; line<5; line++)

for (col=0; col<4; col++)

print("%5d", jum[line][col]);

jum_sum = tot(jum[line], 4);

jum_ave = jum_sum / 4.;

printf("%6d%6.1f\n", jum_sum, jum_ave);

}

printf("=============================\n");

}

☞ 실행 결과

c>c6-17

============================

국어 영어 수학 전산 총점 평균

============================

100 78 96 100 374 93.5

98 98 32 92 381 95.3

85 57 86 59 287 71.8

76 78 77 79 310 77.5

67 90 88 85 330 82.5

============================




《연습 17》실행 결과와 같이 <실습6-17>에서 사용한 데이터를 사용하여 아래와 같이 총 점, 평균 및 석차를 계산하여 출력하는 프로그램을 작상하여라.

☞ 실행 결과

===============================

국어 영어 수학 전산 총점 평균 석차

===============================

100 78 96 100 374 93.5 2

98 98 32 92 381 95.3 1

85 57 86 59 287 71.8 5

76 78 77 79 310 77.5 4

67 90 88 85 330 82.5 3

===============================






3) 2차원 배열 전체를 인수로 사용할 경우

배열 전체의 내용을 호출될 함수로 전달할 때에는 배열의 이름만을 호출하는 함수의 실인수로 사용하면 된다. 즉 1차원 배열을 함수에 전달하는 방식과 근본적으로 같다.

『실습 6-18』2차원 배열을 1차원 배열로 처리하는 예

/*----------------------------------------------------------------------------------------------

* c6-18.c : 2차원 배열을 함수로 전달하는 예

*---------------------------------------------------------------------------------------------*/

int list(data)

int data[ ][4];

{

int i, j;

for ( i = 0 ; i<5; i++) {

for (j=0; j<4; j++)

printf("%5d", data[i][j]);

printf("\n");

}

}

main( )

{

static int jum[5][4]={

{100, 78, 96, 100},

{ 98, 98, 32, 92},

{ 85, 57, 86, 59},

{ 76, 78, 77, 79},

{ 67, 90, 88, 85}

};

list(jum);

}

☞ 실행 결과

100 78 96 10

98 98 32 92

85 57 86 59

76 78 77 79

67 90 88 85




Ⅶ. 기억 장소의 종류

1. 기억 장소의 종류 (storage class)

컴퓨터는 데이터를 기억시키는 기억 장소의 크기가 제한을 받기 때문에 되도록이면 기억 장소를 효율적으로 이용하기 위하여 문자형, 정수형, 실수형 등으로 데이터의 형을 구분하여 사용한다는 사실은 이미 알고 있는 사실이다.

그리고 기억 장소의 종류에 따라 처리 속도가 다르기 때문에 프로그램의 효율성을 높이기 위하여 필요에 따라 기억장소를 구분하여 사용한다.

예를 들면 어떤 처리를 위하여 한번 쓰고 버려도 되는 변수들은 스택(stack)이라는 임시 저장 장소에 기억시켰다가 필요할 때 불러 사용하거나 고속의 연산 처리를 위하여 CPU내의 레지스터(register)를 사용하는 것 등을 그 예로 들수 있다.

이런 이유로 C언어에서는 기억 장소의 종류(storage class)를 다음의 4가지 종류로 분류하여 사용한다.

+--------- auto (자동 변수)

+----------------+ +--------- static (정적 변수)

|기억장소의 종류 +-----+--------- extern (외부 변수)

+----------------+ +--------- register (레지스터 변수)

위의 각 변수들은 아래와 같은 기억 장소들의 영역을 사용한다.

Ↄ 스택이라는 메모리상의 일시적 영역 auto

기억영역 ⇒ 보통의 메모리상의 기억 영역 static, extern

ↁ CPU내의 레지스터 영역 register

2. auto 변수 (자동 변수)

1) auto변수의 개념

auto변수란 어떤 함수의 내부나 또는 그 함수 내의 복문 안에서 선언되는 변수로서 그 변수가 선언된 함수 또는 복문 내에서만 사용할 수 있다. 이런 이유로 auto 변수를 지역 변수(local variable)라고도 한다.

따라서 auto 변수는 같은 이름의 변수를 다른 함수 내에서 또는 그 함수의 다른 복문내에서 사용해도 서로 상관없이 독립적으로 취급된다.

auto 변수는 메모리의 스택(메모리 중에서 데이터를 일시적으로 기억시키는 영역으로서 나중에 입력된 데이터를 먼저 꺼내기 위해 사용되는 영역)에 할당하는 변수로서 auto 변수가 선언되어 있는 함수가 실행됨과 동시에 생성되며 함수의 실행이 종료됨과 동시에 자동적으로 소멸된다.

auto 변수는 함수가 시작되어야 생성되기 때문에 컴파일(compile)시에 초기화 되지 않는다. 따라서 auto 변수를 선언할 때 초기치를 지정하지 않으면 부정치(garbage:쓰레기값)를 갖게 되므로 반드시 초기치를 부여항 후에 사용하여야 한다.

2) auto변수의 선언

auto 변수는 다음과 같은 형식으로 선언한다.

<일반형식>

auto 데이터형 변수1, 변수2


C언어에서 사용되는 대부분의 변수는 auto변수이기 때문에 auto라고 기술하지 않아도 auto 변수로 인정된다. 예를 들면 아래의 두 선언문은 같은 의미를 갖는다.

『 실습 7-01 』 예제 프로그램

/*------------------------------------------------------------------------------------------------

* c7-01.c : auto 변수의 사용 예

*------------------------------------------------------------------------------------------------*/

main( )

{

int s=10; /* auto 변수 s를 첫번째 선언 */

{

int s=20; /* 블럭내에 auto 변수 s를 두번째 선언 */

{

int s=30; /* 블럭내에 auto 변수 s를 세번째 선언 */

printf("s(3) = %d\n", s);

}

printf("s(2) = %d\n", s);

}

printf("s(1) = %d\n", s);

}

☞실행 결과

c>07-01

s(3) = 30

s(2) = 20

s(1) = 10

⼓ 해설

위 실행 결과에서 알 수 있듯이 자동 변수는 함수내의 블럭(복문)내에서 선언될 경우 에는 그 블럭 내에서만 통용됨을 알 수 있다.

『 실습 7-02 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c7-02.c : auto 변수의 사용 예

*------------------------------------------------------------------------------------------------*/

sub( )

{

int i, sum=0;

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

sum += i;

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

}

main( )

{

int sum=0;

sub( );

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

}

☞실행 결과

c>07-02

sum = 55 sub( )함수의 실행 결과

sum = 0 main( )함수의 실행 결과

⼓ 해설

함수 sub( )와 main( )에서 사용된 auto변수 sum은 각 함수 내에서만 유효하다.

《연습 1》아래의 프로그램은 1부터 100까지의 합을 계산하여 출력하는 프로그램이다. 예 상하는 결과가 출력되지 않을 것이다. 그 이유를 설명하고 잘못된 부분을 수정 하여 프로그램을 완성하여라.

main( )

{

int i, sum;

for ( i=1; i<=100; i++ )

sum = sum +i;

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

}

《연습 2》아래 프로그램은 1부터 10까지의 숫자를 출력하기 위하여 작성한 프로그램인데 원하는 결과가 출력되지 않았다. 그 이유를 설명하고 잘못된 부분을 수정하여 프로그램을 완성하여라.

sub( )

{

i++;

printf("%4d", i);

}

main( )

{

int i=0;

while (i<=10)

sub( );

}



3. static 변수 ( 정적 변수 )

1) static 변수의 개념

스텍을 사용하는 auto 변수는 그 수명이 영구적이지 못하고 함수나 블럭의 실행이 종료됨과 동시에 자동적으로 소멸된다. 따라서 auto 변수는 여러 블럭으로 구성된 프로그램이나 여러 함수(모듈)들로 구성된 프로그램에서 공통적으로 사용할 변수로는 적합하지 못하다. 이러한 경우에 사용하는 변수가 static 변수이다.

static 변수는 정적 영역의 메모리에 할당하기 때문에 프로그램의 시작에서 실행이 종결될 때까지 메모리 속에 유지된다. 따라서 프로그램이 실행되는 도중에는 변수의 값이 그대로 유지되기 때문에 다른 블럭이나 다른 모듈에서도 사용이 가능하다.

auto변수를 선언할 때 초기치를 부여하지 않으면 부정치(쓰레기값)를 갖게 되나 static변수를 선언할 때 초기치를 부여하지 않으면 초기값은 0이 된다.

2) static 변수의 선언

static 변수는 다음과 같은 형식으로 선언한다.

<일반형식>

static 데이터형 변수1, 변수2

[보기] static 변수의 선언 예

static int number;

static 변수는 함수의 내부에 선언하는 경우와 함수의 외부에 선언하는 경우에 따라 그 역할이 달라지게 되는데 이 두 경우에 개하여 알아보자.

3) 함수의 내부에 static 변수를 선언할 경우

함수 내부에 static변수를 선언하면 그 함수에서만 사용할 수 있는 지역변수가 된다. auto 변수와의 차이점은 스텍을 변수의 영역으로 사용하는 것이 아니라 메모리를 변수의 영역으로 사용하기 때문에 static 변수는 프로그램의 시작부터 프로그램의 실행이 종료될 때까지 변수의 값이 보존된다.

『 실습 7-03 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c7-03.c : statis 변수의 사용 예(1)

*------------------------------------------------------------------------------------------------*/

main( )

{

static int sum=0;

{

sum = sum +10;

{

sum = sum + 10;

printf("sum(3) = %d\n", sum);

}

sum = sum +10;

printf("sum(2) = %d\n", sum);

}

sum = sum + 10 ;

printf("sum(1) = %d\n", sum);

}

☞실행 결과

c>07-03

sum(3) = 20

sum(2) = 30

sum(1) = 40

『 실습 7-04 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c7-04.c : statis 변수의 사용 예(2)

*------------------------------------------------------------------------------------------------*/

main( )

{

static int counter, sum; /* counter과 sum의 초기치는 0이됨 */

auto int, mul;

while (counter<=10) {

sum += counter; /* 블럭내에서 static변수 sum과 counter사용 */

counter++;

}

printf("sum(1~10) = %d\n", sum);

mul = 10 * sum;

printf("10 * sum = %d\n", mul);

}

☞실행 결과

c>07-04

sum(1~10) = 55

10 *sum = 550




『 실습 7-05 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c7-05.c : auto변수와 statis 변수의 비교

*------------------------------------------------------------------------------------------------*/

main( )

{

auto int i=1;

static int k=1;

printf(" i = %3d k = %3d\n", i, k);

i++, k++;

}

main( )

{

int i;

printf("auto변수 static변수\n");

printf("-------------------------------------\n");

for ( i=1; i<=5; i++ )

sum( );

}

☞실행 결과

c>07-05

auto 변수 static 변수

-------------------------------------------

i = 1 k = 1

i = 1 k = 2

i = 1 k = 3

i = 1 k = 4

i = 1 k = 5

3) 함수의 외부에 static 변수를 선언할 경우

함수 외부에서 static 변수를 선언하면 그 프로그램(여러개의 함수로 구성된 프로그램) 내의 어느 곳에서든지 사용이 가능한 변수가 된다.

함수 내부에 static 변수를 선언할 때와 마찬가지로 메모리 내에 변수가 확보되기 때문에 그 변수의 값은 프로그램이 종료될 때까지 보존된다.

『 실습 7-06 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c7-06.c : 함수 외부의 statis 변수 선언 예

*------------------------------------------------------------------------------------------------*/

static int, number;

add( )

{

number++;

return( number );

}

main( )

{

int i, sum=0;

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

sum += add( );

printf("sum = %d", sum);

}

☞실행 결과

c>07-06

sum = 55

『 실습 7-07 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c7-07.c : 함수 외부의 statis 변수 선언 예

*------------------------------------------------------------------------------------------------*/

static int, n, sum;

add( x)

int x;

{

while ( n<x) {

n++;

sum += n;

}

}

main( )

{

int i;

for ( i=10; i<=100; i+=10) {

add(i);

printf("sum(1~%3d) = %4d\n", i, sum);

}

}

☞실행 결과

c>07-07

sum( 1~10 ) = 55

sum( 1~20 ) = 210

sum( 1~30 ) = 465

sum( 1~40 ) = 820

sum( 1~50 ) = 1275

sum( 1~60 ) = 1830

sum( 1~70 ) = 2485

sum( 1~80 ) = 3240

sum( 1~90 ) = 4095

sum( 1~100 ) = 5050

함수의 외부에서 static 변수를 선언한 후 넓은 영역에 걸쳐서 참조하는 것은 되도록 삼가하는 것이 좋다. 되도록이면 하나 하나의 기능을 수행하는 변수들을 사용하는 것 이 좋으며 함수들 간의 통신은 인수와 함수의 리턴값에 의하여 수행되도록 하는 것이 바람직하다.

『 실습 7-08 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c7-08.c : statis 변수의 사용예

*------------------------------------------------------------------------------------------------*/

static int a=100;

static int b=200;

static int sol;

plus( )

{

sol = a + b;

}

minus( )

{

sol = a - b;

}

main( )

{

plus( );

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

minus( );

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

}

☞실행 결과

c>07-08

100 + 200 = 300

100 - 200 = -100


『 실습 7-09 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c7-09.c : statis 배열의 사용예

*------------------------------------------------------------------------------------------------*/

static char str[6];

function( )

{

str[0]='K', str[1]='o', str[2]='r';

str[3]='e', str[4]='a', str[5]='n';

}

main( )

{

int k;

function( );

for ( k=0; k<6; k++ )

printf("str[%d] = %c\n", k, str[k]);

}

☞실행 결과

c>07-09

str[0] = K

str[1] = o

str[2] = r

str[3] = e

str[4] = a

str[5] = n


《연습 3》다음 프로그램은 키보드로 입력한 정수의 제곱을 n회 수행하기 위한 프로그램 이다. 잘못된 곳을 찾아 올바르게 수정하여라.

int n;

int square(int x)

{

n = x * x;

return n;

}

main( )

{

int i, x;

printf("횟수 = ? ");

scanf("%d", &n);

for ( i=0; i<n; i++ ) {

print("x = ? ");

scanf("%d", &x);

printf("%d ^ 2 = %d\n", x, square(x));

}

}



4. register 변수 (레지스터 변수)

1) register 변수의 개념

일반적으로 컴퓨토의 CPU내에는 연산 처리의 고속화를 위한 장치로 레지스터가 준비되어 있다. 레지스터 변수란 연산 처리의 고속화를 위하여 변수 영역으로 레지스터를 사용하는 변수를 말한다.

CPU에 따라서 레지스터의 개수가 서로 다르므로 사용할 수 있는 레지스터 변수는 컴퓨터에 따라 다를수 있으나 일반적으로 3개까지의 레지스터 변수를 사용할 수 있다. 따라서 3개 이상의 레지스터 변수를 선언한 경우에는 최초의 3개는 레지스터 변수로 사용되나 그 나머지의 레지스터 변수들은 auto변수로 처리된다.

레지스터 변수는 모든 기억 장소의 종류를 사용할 수 있는 것이 아니라 auto 변수와 함수의 가인수(formal parameter)에 대해서만 선언할 수 있다.

2) register 변수의 선언

register 변수는 다음과 같은 형식으로 선언한다.

<일반형식>

register 데이터형 변수1, 변수2

[보기] register 변수의 선언 예

register int number;

register char str;

『 실습 7-10 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c7-10.c : register 변수의 사용예

*------------------------------------------------------------------------------------------------*/

main( )

{

register int n, sum=0;

for ( n=1 ; n<=100; n++ )

sum += n;

printf("합 = %d\n", sum);

}

☞실행 결과

c>07-10

합 = 5050

register 변수의 번지는 구할 수 없기 때문에 register 변수에 번지 연산자 &는 사용할 수 없다.

『 실습 7-11 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c7-11.c : register 변수의 사용예

*------------------------------------------------------------------------------------------------*/

double power( x, n )

register int x, n;

{

register int i;

double p=1;

for ( i=1; i<=n; i++ )

p = p * x;

return(p);

}

main( )

{

int x, n;

printf("x, n = ? ");

scanf("%d, %d", &x, &n);

printf("%d ^ %d = %f\n", x, n, power(x, n));

}

☞실행 결과

c>07-11

x, n = ? 10,5

10 ^ 5 = 100000.000000







Ⅷ. 포 인 터

1. 포인터의 개념

C언어에서 가장 대표적인 특징을 들라면 포인터(pointer)를 들 수 있다. 포인터는 다른 언어에서는 찾아보기 어려운 개념으로서 메모리 관련 조작을 간결하면서도 효율적으로 제어할 수 있도록 지원하는 기능이다.

포인터는 C의 가장 강력한 특징으로서 잘 사용하면 프로그램의 효율을 향상 시킬 수 있는 반면에 잘못 사용하면 시스템을 다운 시키거나 발견하기 힘든 버그(bug:오류)를 야기 시킬 수 있으므로 사용에 특별히 유의해야 한다.

포인터를 한 마디로 표현하면 메모리의 번지(address)를 기호화한 것이라고 정의할 수 있다. 즉 포인터는 메모리의 번지라고 정의할 수 있으며 번지를 관리하기 위한 목적으로 사용된다. 다시 말해서 포인터란 실제로 존재하는 메모리에 기억되어 있는 값을 의미하는 것이 아니라 메모리의 번지를 의미한다.

※ 번지란 메모리의 특정 위치를 숫자(주로 16진수)로 표현하는 것으로 변수를 구별하기 위하여 사용되는 레이블(label)이라고 생각할 수 있다.

2. 포인터의 연산

포인터 변수란 포인터의 값 즉 메모리의 번지를 저장하는 변수를 의미한다.

포인터 변수는 포인터 연산자 * (asterisk)를 사용하여 선언한다. 그예를 들면 다음과 같다.

[보기] 포인터 변수의 선언 예

int *pointer; /* int형 포인터 변수 pointer를 선언 */

char *ch; /* char형 포안터 변수 ch를 선언 */

위 예에서 *pointer나 *ch는 포인터 변수가 아니다. 포인터 변수는 pointer와 ch이다. 그리고 포인터 변수 pointer의 형이 int형 데이터라는 의미가 아니고 pointer라는 변수를 통해서 참조할 수 있는 번지에 기억되어 있는 데이터의 형이 int형이라는 의미이다. 만일 pointer = 1230; 이라는 문장이 실행되면 *pointer는 메모리의 1230번지에 기억되어 있는 데이터를 의미한다. 다시 말해서 int *pointer; 와 같이 선언하면 pointer는 메모리 중의 특정 위치를 가리키는 포인터 변수로 동작하고 *pointer는 그곳에 수록되어 있는 데이터를 의미한다.


3. 포인터 연산자

C언어에서는 포인터 연산을 위하여 다음과 같은 2종류의 연산자를 준비하고 있다.

1) &연산자 ( 번지 연산자 )

제Ⅱ장에서 scanf( )함수로 데이터를 입력하려면 무조건 변수명 앞에 &기호를 붙인다는 것을 설명한 바 있는데 이것이 바로 번지 연산자이다.

& 연산자는 변수가 할당되어 있는 메모리의 번지를 알아낼 때 사용하며 반드시 변수명 앞에 표시한다.

『 실습 8-01 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c8-01.c : 번지 연산자 사용 예(1)

*------------------------------------------------------------------------------------------------*/

main( )

{

int a;

printf("a = ? ");

scanf("%u", &a);

printf("변수 a의 번지 = %d", &a);

printf("변수 a의 내용 = %d", a);

}

☞실행 결과

c>08-01

변수 a의 번지 = 4256

변수 a의 내용 = 123

위 프로그램에서 사용된 scanf( )함수

scanf("%u", &a);

는 변수 a로 사용된 메모리의 번지에 키보드로 입력한 데이터를 기억시키라는 의미이다.

위 프로그램의 실행 결과는 키보드로 입력한 정수형 데이터 123이 변수 a로 사용된 메모리의 4256번지에 기억되었음을 알 수 있다. 위 프로그램을 실행시키면 변수 a의 번지값은 컴퓨터에 따라서 또는 실행시킬 때마다 다르게 나타날 수 있다. 그 이유는 제Ⅶ장의 기억 장소의 종류를 학습한 후에는 충분히 이해할 수 있을 것이다.

『 실습 8-02 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c8-02.c : 번지 연산자 사용 예(2)

*------------------------------------------------------------------------------------------------*/

main( )

{

int a=10, b=20, c;

c = a + b;

printf("변수 번지 내용\n");

printf(" a %5d %4d\n", &a, a);

printf(" b %5d %4d\n", &b, b);

printf(" c %5d %4d\n", &c, c);

}

☞실행 결과

c>08-02

변수 번지 내용

a 4000 10

b 3998 20

c 3996 30


《연습 8-01》다음 프로그램의 실행 여부를 확인하라. 만일 수행되지 않는다면 그 이유를 밝혀라.

main( )

{

int a=10, b=20, c;

&c = a + b;

printf("&c = %d\n", &c);

}


2) * 연산자 (간접 지정 연산자)

* 연산자는 포인터가 지정하는 메모리 번지의 내용을 끌어낼때 사용하는 연산자이다. &연산자와 *연산자의 기능을 알아보기 위하여 다음의 예제 프로그램을 살펴보기로 하자.

『 실습 8-03 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c8-03.c : 번지 연산자와 포인터 변수

*------------------------------------------------------------------------------------------------*/

main( )

{

int n;

int *p; /* 해설①참고 */

p = &n; /* 해설②참고 */

*p = 123; /* 해설③참고 */

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

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

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

printf("*p = %d\n, *p);

}

☞실행 결과

c>08-03

&n = 3950

p = 3950

n = 123

*p = 123

⼓ 해설

①포인터 변수 p를 선언한다.

②변수 n의 번지값을 포인터 변수 p에 기억시킨다.

③정수형 수치 123을 포인터 변수 p에 기억되어 있는 번지에 기억시킨다.

따라서 123은 변수 n에 기억된 값이 된다.




이해를 돕기 위하여 위 프로그램을 행 단위로 보다 구체적으로 설명하묜 다음과 같다.

① int n

int형 변수 n을 선언 : 변수 n의 영역이 메모리의 3950번지와 3951번지라고 가정하면 다음과 같이 생각 할 수 있다.

번 지

메모리



3949


3950


변수 n의 영역

(2Byte)

3951


3952



3953



※ n의 영역이 2바이트인 이유는 int형의 데이터가 2葡이트로 표현되기 때문에 메모리에 저장될 때에도 2바이트를 차지하기 때문이다.

② int *p;

포인터 뱐수 p를 선언 : p는 변수 n의 번지를 기억 시키려고 사용하였다.

③ p = &n;

변수 n의 번지값(&n)을 포인터 변수 p에 기억시킨다.


번 지

메모리




포인터 변수 p


3949



3950




변수 n의 영역 (2Byte)


3950






3951



3952





3953



※ p = &n;에 의하여 변수 n의 선두 번지값인 3950을 포인터 변수 p에 저장된다.

④ *p = 123 ;

포인터 변수 p에 기억되어 있는 번지부터 2바이트 크기의 메모리에 정수형 상수 123을 기억시킨다. 즉 포인터 변수 p가 가리키는 번지인 3950번지부터 3951번지까지의 2바이트 영역에 123을 기억시킨다. 메모리에 123이 기억된 모양을 그림으로 나타내면 다음과 같다.

번 지

메모리




3949



3950

01111011


변수 n의 영역 (2Byte)

3951

00000000

3952




3953




※위의 그림과 같이 데이터가 기억되는 이유는 10진수 123을 2진수로 표현하면 0000000001111011이기 때문이다.

⑤ printf("&n = %d\n, &n);

변수 n의 시작 번지값(3950)을 출력한다.

⑥ printf("p = %d\n, p);

포인터 변수 p의 값(3950)을 출력한다.

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

변수 n의 값을 출력한다.

⑧ printf("*p = %d\n, *p);

포인터 변수 p의 값(3950)에 해당하는 메모리 번지에 기억되어 있는 값(123)을 출력한 다.

※ 여기서 알아 둘 사항은 변수 n의 값과 *p의 값이 동일하다는 사실이다.





『 실습 8-04 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c8-04.c : 일반 변수와 포인터 변수와의 관계

*------------------------------------------------------------------------------------------------*/

/* int형 변수 a, b에 10, 20, 30을 기억시킨 후 각 변수의 번지값과

* 그 번지에 기억된 값을 출력하는 프로그램 */

main( )

{

int a, b, c;

int *pa, *pb, *pc;

a=10, b=20, c=30;

pa=&a, pb=&b, pc=&c;

printf("a의 번지 = %d a의 내용 = %d\n", &a, a);

printf("b의 번지 = %d b의 내용 = %d\n", &b, b);

printf("c의 번지 = %d c의 내용 = %d\n", &c, c);

printf("\n");

printf("pa = %d *pa = %d\n", pa, *pa);

printf("pb = %d *pb = %d\n", pb, *pb);

printf("pc = %d *pc = %d\n", pc, *pc);

}

☞실행 결과

c>08-04

a의 번지 = 4012 a의 내용 = 10

b의 번지 = 4010 b의 내용 = 20

c의 번지 = 4008 c의 내용 = 30

pa = 4012 *pa = 10

pb = 4010 *pb = 20

pc = 4008 *pc = 30




『 실습 8-05 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c8-05.c : 포인터 변수를 이용한 덧셈

*------------------------------------------------------------------------------------------------*/

main ( )

{

int a, b;

int *pa, *pb;

a=10;

pa=&a;

b=*pa + 10;

pb = &b;

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

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

printf("*pa = %d\n", *pa);

printf("*pb = %d\n", *pb);

}

☞실행 결과

c>08-05

a = 10

b = 20

*pa = 10

*pb = 20

일반 변수와 포인터 변수의 비교


일반적인 변수

포인터 변수

선언 형식

int sum;

sum을 int형으로 선언

int *sum;

*sum(sum번지 내용)을 int형으로 선언

값의 대입

sum = 123;

변수 sum에 123을 대입

*sum = 123;

sum번지의 내용으로 123을 대입

번지 참조

&sum

변수 sum이 수록된 번지

sum;

sum자체가 번지

번지 연산

불가능

sum++;

포인터(번지)를 1만큼 증가

번지 조작

불가능

sum =123

포인터 sum에 123을 대입


4. 포인터와 문자열

문자열은 배열로 처리된다는 사실을 이미 설명한 바 있다. 문자열을 배열로 처리할 경우에는 문자열의 길이가 얼마인지 파익하여 배열의 크기를 반영해 주어야 하는데 포인터 변수를 이용하여 문자열을 처리할 경우에는 문자열의 길이를 고려할 필요가 없다. 다음의 예제 프로그램을 분석해 보면 그 이유를 쉽게 알 수 있을 것이다.

『 실습 8-06 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c8-06.c : 포인터 변수를 이용한 문자열 처리

*------------------------------------------------------------------------------------------------*/

main ( )

{

int i=0;

char *string;

string = "Seoul Korea"; /*포인터 변수 string에는 "Seoul Korea"가 */

/*기억될 첫번째 번지값이 기억된다. */

/*즉 첫문자 S가 기억될 번지값이 포인터 */

/*변수 string에 기억된다. */

while ( * (string+i) != '\0') {

printf("*(string+%2d) --> %c\n", i, *(string + i );

/* string+i 번지의 내용 출력 */

i++; /* 1만큼의 증가는 포인터의 데이터형의 크기만큼 증가 */

}

}

☞실행 결과

c>08-06

*(string + 0) --> S

*(string + 1) --> e

*(string + 2) --> o

*(string + 3) --> u

*(string + 4) --> l

*(string + 5) -->

*(string + 6) --> K

*(string + 7) --> o

*(string + 8) --> r

*(string + 9) --> e

*(string +10) --> a


위 예제에서 문자열 "Seoul Korea"가 기억되어 있는 상태를 그림으로 나타내면 다음과 같다.



메모리









string


S



*string






e



*(string + 1)







o



*(string + 2)







u



*(string + 3)







l



*(string + 4)










*(string + 5)







K



*(string + 6)







o



*(string + 7)







r



*(string + 8)







e



*(string + 9)







a



*(string +10)







\0



*(string +11)


















《연습 8-03》실습 c8-06.c의 프로그램을 변경하여 실행 결과처럼 Seoul Korea라는 문자열 을 거꾸로 출력하는 프로그램을 완성하여라.

☞실행 결과

aeroK luoeS


《연습 8-04》아래의 main( )함수는 실행 결과와 같이 문자열의 길이를 구하기 위한 것이 다. 문자열을 구하기 위한 함수 len( )을 완성하여라.

☞실행 결과

Hong Gil Dong = 13문자

main ( )

{

static char *name = "Hong Gil Dong";

printf("%s = %d 문자 \n", name, len(name));

}

『 실습 8-07 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c8-07.c : 포인터를 이용한 문자열의 복사

*------------------------------------------------------------------------------------------------*/

copy_string(form, to)

char *form, *to;

{

while ( *form != '\0' ) {

*to = *form;

form++;

to++;

}

*to = '\0';

}

main( )

{

static char string_1 [ ] = "C programming !!";

static char string_2 [20];

printf("string_1==> %s\n", string_1);

copy_string(string_1, string_2); /* 해설①참고 */

printf("string_2==> %s\n", string_2);

}

☞실행 결과

c>08-07

string_1==> C programming !!

string_2==> C programming !!

⼓ 해설

①string_1은 string_1[0]의 번지를, string_2는 string_2[0]의 번지를 실인수의 값으로 함수 copy_string( )의 가인수로 전달한다.

5. 포인터와 배열

1)포인터와 1차원 배열

C언어에서 배열 이름은 그 배열의 선두 번지를 의미하는 일종의 포인터 상수이다. 즉 C컴파일러는 첨자없는 배열명을 배열의 포인터로 취급한다. 이런 의미에서 배열명을 상수라고도 한다.

아래의 두문장을 살펴 보기로 하자.

char *str ="Seoul Korea";

static char string[ ] = "Seoul Korea";

위 두문장에서 str과 string은 모두 문자열 "Seoul Korea"가 기억되어 있는 메모리의 시작번지를 가리킨다. 포인터와 배열이 메모리의 번지를 이용한다는 관점에서 볼 때 배열 변수 대신에 포인터 변수를 사용할 수 있고, 반대로 포인터 변수 대신에 배열 변수를 사용할 수 있다.

『 실습 8-08 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c8-08.c : 배열과 포인터의 관계

*------------------------------------------------------------------------------------------------*/

main( )

{

char *pointer;

static char array[ ] = "Array";

int idx;

pointer = array; /* array는 배열 원소 array[0]의 번지를 의미 */

for ( idx=0; idx<5; idx++ ) {

printf("*(pointer + %d) --> %c ", idx, *(pointer + idx));

printf("pointer[%d] --> %c ", idx, pointer[idx]);

printf("array[%d] --> %c\n", idx, array[idx]);

}

}

☞실행 결과

c>08-08

*(pointer+0) --> A pointer[0] --> A array[0] --> A

*(pointer+1) --> r pointer[1] --> r array[1] --> r

*(pointer+2) --> r pointer[2] --> r array[2] --> r

*(pointer+3) --> a pointer[3] --> a array[3] --> a

*(pointer+4) --> y pointer[4] --> y array[4] --> y

아래의 3 문장은 실행 결과에서 알 수 있듯이 표현 방법만 틀릴 뿐이지 근본적으로 동일한 문장이다.

printf("*(pointer + %d) --> %c ", idx, *(pointer + idx));

printf("pointer[%d] --> %c ", idx, pointer[idx]);

printf("array[%d] --> %c\n", idx, array[idx]);

엄밀하게 말해서 아래의 3 표현은 완전히 동일하다고 말할 수 있다.

*(pointer + idx)

pointer[idx]

array[idx]

따라서 『 실습 8-08 』에서 문자열 "Array"가 기억되어 있는 상태를 그림으로 나타내면 다음과 같다.


메모리




pointer[0]

S

array[0]

pointer[1]

e

array[1]

pointer[2]

o

array[2]

pointer[3]

u

array[3]

pointer[4]

l

array[4]

pointer[5]

\0

array[5]








*(pointer + 5)





『 실습 8-09 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c8-09.c : 배열과 포인터의 관계 확인

*------------------------------------------------------------------------------------------------*/

main( )

{

char *pointer = "Pointer";

static char array[ ] = "Array";

int idx;

for ( idx=0; idx<8; idx++ )

printf("pointer[%d] ---> %c\n", idx, pointer[idx]);

for ( idx=0; idx<6; idx++ )

printf("*(array+%d) ---> %c\n", idx, *(array+idx));

}

☞실행 결과

c>08-09

pointer[0] ---> P

pointer[1] ---> o

pointer[2] ---> i

pointer[3] ---> n

pointer[4] ---> t

pointer[5] ---> e

pointer[6] ---> r

pointer[7] --->

*(array+0) --> A

*(array+1) --> r

*(array+2) --> r

*(array+3) --> a

*(array+4) --> y

*(array+5) -->


배열이란 단지 포인터의 변형된 형태라고 말할 수 있다. 즉 배열명은 배열의 맨 첫번째 원소에 대한 포인터라고 말할 수 있다. 따라서 위 프로그램의 경우 다음과 같은 등식이 성립될 수 있다.

pointer[0] == *(pointer+0) *(array+0) ==array[0]

pointer[1] == *(pointer+1) *(array+1) ==array[1]

pointer[2] == *(pointer+2) *(array+2) ==array[2]

pointer[3] == *(pointer+3) *(array+3) ==array[3]

pointer[4] == *(pointer+4) *(array+4) ==array[4]

pointer[5] == *(pointer+5) *(array+5) ==array[5]

pointer[6] == *(pointer+6)

pointer[7] == *(pointer+7)

『 실습 8-10 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c8-10.c : 배열 원소의 참조

*------------------------------------------------------------------------------------------------*/

main( )

{

int num[5]={

25, 87, 43, 56, 98

};

int i, *ptr;

ptr = num ;

for ( i=0; i<=4; i++ ) {

printf("*(ptr+%d) = %d", i, *(ptr+i));

printf(" ptr+%d = %d\n", i ptr+i);

}

}

☞실행 결과

c>08-10

*(ptr+0) = 25 ptr+0 = 3452

*(ptr+1) = 87 ptr+1 = 3454

*(ptr+2) = 43 ptr+2 = 3456

*(ptr+3) = 56 ptr+3 = 3458

*(ptr+4) = 98 ptr+4 = 3460



해설

위 프로그램은 배열의 각 원소를 구분하거나 그 원소의 값을 참조하는데 포인터를 사용할 수 있음을 나타낸 것이다. 여기서 이해할 수 있는 것은 포인터와 배열은 본 질적으로 같은 것을 표현을 다르게 하였을 뿐이라는 사실이다.


번지

메모리






prt+0 ==

3452

25


&num[0]


3453



prt+1 ==

3454

87


&num[1]


3455



prt+2 ==

3456

43


&num[2]


3457



prt+3 ==

3458

56


&num[3]


3459



prt+4 ==

3460

98


&num[4]


3461









*(ptr+4)









『 실습 8-11 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c8-11.c : 포인터와 배열(1)

*------------------------------------------------------------------------------------------------*/

main( )

{

static int n[5]={ 2, 4, 6, 8, 10

12, 14, 16, 18, 20 };

int sum=0;

int *pt;

for ( pt=n; pt<n+10; pt++ )

sum += *pt;

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

}

☞실행 결과

c>08-11

sum = 110


『 실습 8-12 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c8-12.c : 포인터와 배열(2)

*------------------------------------------------------------------------------------------------*/

int array_sum(array, n)

int array[ ];

int n;

{

int sum=0, *pointer;

for ( pointer=array; pointer<array+n; pointer++ )

sum += *pointer;

return(sum);

}

main( )

{

static int number[10] = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20};

printf("배열 array의 합 = %d\n", array_sum(number, 10));

}

☞실행 결과

c>08-12

배열 array의 합 = 110

2) 포인터와 2차원 배열

『 실습 08-13 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c08-13.c : 포인터와 2차원 배열

*------------------------------------------------------------------------------------------------*/

main( )

{

static int a[4][3]= { { 1, 2, 3},

{ 4, 5, 6},

{ 7, 8, 9},

{10, 11, 12} };

int k, *pt;

pt = a[3] /* 포인터 변수 pt 에 a[3][0]의 번지를 기억 */

for ( k=0; k<3; k++ )

printf("a[3][%d] = %d\n", k *(pt+k));

}

☞실행 결과

c>08-13

a[3][0] = 4

a[3][1] = 8

a[3][2] = 12

위 에에서 사용한 2차원 배열 a[4][3]의 메모리 상태를 그림으로 나타내면 다음과 같다.






메모리







pt=a[0]


a[0][0]

1








a[0][1]

2


a[0]의 영역






a[0][2]

3







pt=a[1]


a[1][0]

4








a[1][1]

5


a[1]의 영역






a[1][2]

6







pt=a[2]


a[2][0]

7








a[2][1]

8


a[2]의 영역






a[2][2]

9







pt=a[3]


a[3][0]

10








a[3][1]

11


a[3]의 영역






a[3][2]

12
















『 실습 08-14 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c08-14.c : 2차원 배열을 1차원 배열로 취급

*------------------------------------------------------------------------------------------------*/

main( )

{

static int a[ ][3]= { { 1, 2, 3},

{ 2, 4, 6},

{ 3, 6, 9},

{ 4, 8, 12} };

int k, *pt;

pt = a[0] /* 포인터 변수 pt 에 a[0][0]의 번지를 기억 */

for ( k=0; k<12; k++ ) {

printf("%3d", *(pt+k));

if ( (k+1) %3 ==0 )

printf("\n");

}

}

☞실행 결과

c>08-14

1 2 3

2 4 6

3 6 9

4 8 12


《연습 8-05》실습 8-14프로그램을 수정하여 아래의 실행 결과처럼 출력되도록 수정하여 라.

☞실행 결과

12 8 4

9 6 3

6 4 2

3 2 1

『 실습 08-15 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c08-15.c : 2차원 배열의 초기화

*------------------------------------------------------------------------------------------------*/

int_0 (temp, m, n, data)

int *temp, m, n, data;

{

int i;

for (i=0; i<m*n; i++ )

*temp++ = data;

}

main( )

{

int matrix[10][10], i, j;

int_0(matrix, 10, 10, 1);

for ( i=0; i<10; i++ ) {

for (j=0; j<10; j++ )

printf("%4d", matrix[i][j];

printf("\n");

}

}

☞실행 결과

c>08-15

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1 1 1

참고

*temp++ = data; 는 다음의 두문장을 하나의 문장으로 표현한 것이다.

*temp=data;

temp++;

6. 포인터 함수

1) 함수간의 데이터 전달을 위한 포인터의 사용

『 실습 08-16 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c08-16.c : 함수간의 데이터 전달을 위한 포인터의 사용

*------------------------------------------------------------------------------------------------*/

swap(px, py)

int *px, *py;

{

int temp;

temp = *px;

*px = *py;

*py = temp;

}

main( )

{

int a, b;

printf("a, b = ? ");

scanf("%d,%d, &a, &b);

swap (&a, &b);

printf("\n교환후 a = %d, b = %d", a, b);

}

☞실행 결과

c>08-16

a, b = 10,20

교환후 a = 10, b = 10

해설

main( )함수에서 함수 호출문

swap(&a, &b);

는 x와 y의 값대신에 x와 y의 번지를 함수로 전송한다. 따라서 함수 swap(px,py)에 서 px, py는 번지를 값으로 갖게 되므로 포인터로 선언되어야 한다.

『 실습 08-17 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c08-17.c : 함수간의 데이터 전달을 위한 포인터의 사용

*------------------------------------------------------------------------------------------------*/

multi(x, y, z)

int x, y, z;

{

*z = x * y;

}

main( )

{

int a, b, c;

printf("a, b = ? ");

scanf("%d, %d", &a, &b);

multi(a, b, &c);

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

}

☞실행 결과

c>08-17

a, b = 10,20

10 * 20 = 200




《연습 8-05》3개의 수를 키보드로 입력하여 대, 중, 소 순으로 출력하는 프로그램을 작성 하라. 단 아래의 함수 swap( )을 사용하여라.

swap(px, py)

int *px, *py;

{

int temp;

temp = *px;

*px = *py;

*py = temp;

}

『 실습 08-18 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c08-18.c : 함수간의 데이터 전달을 위한 포인터의 사용

*------------------------------------------------------------------------------------------------*/

address(alpha)

char *alpha;

{

printf("%s\n", alpha);

}

main( )

{

static char str[ ]="ABCDEFGHIJKLMNOP";

int n;

for ( n=0; n<=15; n++ )

address(&str[n]);

}

☞실행 결과

c>08-18

ABCDEFGHIJKLMNOP

BCDEFGHIJKLMNOP

CDEFGHIJKLMNOP

DEFGHIJKLMNOP

EFGHIJKLMNOP

FGHIJKLMNOP

GHIJKLMNOP

HIJKLMNOP

IJKLMNOP

JKLMNOP

KLMNOP

LMNOP

MNOP

NOP

OP

P

『 실습 08-19 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c08-19.c : 함수간의 데이터 전달을 위한 포인터의 사용

*------------------------------------------------------------------------------------------------*/

strlen (start)

char *start;

{

int i, len=0;

for ( i=0; ; i++)

if ( *(start+i) == '\0' ) {

len = i;

break;

}

else

len += 1;

return len;

}

main( )

{

char *string;

int length;

string = "I am Korean.";

printf("string = \"%s\"\n", string);

length = strlen(string);

printf("string length = %d\n", length);

}

☞실행 결과

c>08-19

string = "I am Korean."

string length = 12



『 실습 08-20 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c08-20.c : 함수간의 데이터 전달을 위한 포인터의 사용

*------------------------------------------------------------------------------------------------*/

left(bstr, astr, an)

char *bstr, *astr;

int an;

{

int i;

for ( i=0; i<an ; i++ )

*(bstr+i) = *(astr+i);

*(bstr+an) = '\0';

}

main( )

{

static char a[ ] = "Programming";

char b[255];

int n;

printf("a[ ] = %s\n", a);

printf("n = ? ");

scanf("%d", &n);

left(b, a, n);

printf("b[ ] = %s\n", b);

}

☞실행 결과

c>08-19

a[ ] = Programming

a = ? 7

b[ ] = program



《연습 8-06》아래의 실행 결과와 같이 키보드로 문자열 a와 정수 n을 입력하면 문자열 a 의 오른쪽부터 a개의 문자들로 구성된 문자열 b를 출력하도록 프로그램을 작성하여라.

☞실행 결과

a = ? Programming

n = ? 6

b = amming

《연습 8-07》아래의 실행 결과와 같이 키보드로 문자열 a와 정수 i 및 j를 입력하면 문자 열 a의 i번째 문자부터 j개의 문자들로 구성된 문자열 b를 출력하는 프로그 램을 작성하여라.

☞실행 결과

a = ? Programming

i, j = ? 4,4

b = gram

《연습 8-08》아래의 실행 결과와 같이 키보드로 하나의 문자 x와 하나의 숫다 n을 입력 하면 문자 x를 n개 연속하여 출력하는 프로그램을 작성하여라.

☞실행 결과 ☞실행 결과

char = ? p char = ? #

int n = ? 10 int n = ? 6

string = pppppppppp string = ######












Ⅸ. 구 조 체

1. 구조체의 개념

구조체(structure형 데이터 구조)란 복수개의 데이터로 구성된 집합체를 하나의 단위로 처리하고자 할 때 사용되는 데이터 구조를 말한다.

일반적으로 여러개의 데이터 항목으로 구성된 집합체를 레코드(record)라고 하며, 레코드와 같이 여러 항목으로 구성된 데이터 구조를 C언어에서는 구조체(structure)라고 한다. 그리고 레코드를 구성하는 하나하나의 항목을 레코드 필드(record field)라고 하며 C언어에서는 이것을 구조체 구성원(structure members)이라고 한다.

구조체를 사용함으로써 얻을 수 있는 가장 큰 이점은 서로 관련있는 데이터들을 하나의 단위로 취급 할 수 있다는 점이다. 즉 구조체 단위로 데이터를 주고 받을 수 있다는 점이다.

2. 구조체의 정의와 선언

1) 구조체의 예

아래의 그림은 여러 항목으로 구성된 구조체의 한 예를 나타낸 것이다.

성 적 카 드

번호

성 명

점수

등위

1201

홍길동

90

8



2) 구조체의 정의

구조체를 정의할 때에는 예약어인 struct를 사용하여 다음과 같은 형식으로 정의한다.

struct 구조체 택 {

구성원1 선언;

구성원2 선언;

구성원n 선언;

};

구조체 택(structure tag)이란 구조체를 대표하는 이름으로 레코드명이라고 생각할 수 있다. 위와 같이 구조체가 선언된 후에 구조체를 사용할 때에는 구조체 택에 의하여 참조된다.

3) 구조체 정의의 예

위에서 구조체의 예로 나타낸 성적카드를 구조체로 정의하면 다음과 같다.

struct sungjuk {

int bunho;

char irum[7];

int jumsu;

int sunwi; };

위와 같이 구조체를 정의하면 struct sungjuk이라는 구조체형 데이터를 사용 할 수 있는 준비 작업이 된 것이라고 할 수 있다.

| 구조체의 정의를 함수의 외부에서 하게되면 고조체 정의 이후에 기술된 어떤 함수에서 도 사용이 가능하나 함수 내부에서 정의하면 그 함수 내에서만 사용할 수 있다.

| 구조체를 정의할 飁 auto, static등의 기억 장소 종류는 기술하지 않는다.

4) 구조체 변수의 선언

구조체를 정의하고 난 후 구조체를 실제로 사용하려면 구조체를 선언해 주어야 하는데 그 형식은 다음과 같다.

struct 구조체 택 변수1, 변수2,


위와 같은 형식으로 구조체를 선언하면 변수1 변수2, 등은 구조체 택과 같은 데이터 구조를 갖는 변수로 선언된다.

struct sungjuk { /*구조체 정의 */

int bunho;

char irum[7];

int jumsu;

int sunwi; };

struct sungjuk list_1, list_2; /*구조체 선언 */


위와 같이 구조체가 선언되면 list_1과 list_2는 sungjuk과 같은 구조를 갖는 구조체 변수로 사용할 수 있다.

| 구조체 선언의 다른 예

구조체 변수는 다음과 같이 구조체 정의와 선언을 결합하여 한 단계로 표현 할 수 도 있다.

struct sungjuk { /*구조체 정의 */

int bunho;

char irum[7];

int jumsu;

int sunwi;

} list_1, list_2; /*구조체 선언 */



3. 구조체 변수의 참조

『 실습 09-01 』구조체를 사용하는 간단한 예제 프로그램

/*------------------------------------------------------------------------------------------------

* c09-01.c : 구조체 변수의 활용

*------------------------------------------------------------------------------------------------*/

main( )

{

struct sungjuk {

int bunho;

char *irum;

int jumsu;

int sunwi;

};

struct sungjuk list;

list.bunho = 1201;

list.irum = "홍길동";

list.jumsu = 90;

list.sunwi = 8;

printf("번호 성 명 점수 순위\n");

printf("%4d%8s,%6d%6d", list.bunho, list.irum, list.jumsu, list.sunwi);

}

☞실행 결과

c>09-01

번호 성 명 점수 순위

1201 홍길동 90 8

프로그램 <c09-01.c>에서와 같이 구조체의 구성원을 참조하려면 피어리드(.)를 사용하여야 한다. 예를 들면

list.bunho =1201;

에서 list.bunho는 구조체 list의 구성원인 bunho를 의미한다. 즉 .bunho는 구조체 list의 각 구성원을 판별하기 위한 첨자의 역할을 수행한다.

그리고 list.bunho와 같은 구조체의 구성원은 독립된 하나의 변수로 사용할 수 있다.

『 실습 09-02 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c09-02.c : 구조체 변수의 활용

*------------------------------------------------------------------------------------------------*/

main( )

{

struct book {

char title[20];

char author[20];

char press[20];

int value;

} list;

printf("책 명 = ? ");

scanf("%s", list.title); /* 배열은 일종의 포인터이므로 &기호를 사용안함 */

printf("저 자 = ? ");

scanf("%s", list.author);

printf("출판사 = ? ");

scanf("%s", list.press);

printf("정 가 = ? ");

scanf("%d", &list.value);

printf("\n=============================\n");

printf(" 책 명 : %s\n:, list.title);

printf(" 자 자 : %s\n:, list.author);

printf(" 출 판 사 : %s\n:, list.press);

printf(" 정 가 : %d원\n:, &list.value);

printf("\n=============================\n");

}

☞실행 결과

c>09-02

책 명 = ? MicroSoft-C-Basic

저 자 = ? Naba.barkakati

출판사 = ? Sams

정 가 = ? 18000

==============================

책 명 : MicroSoft-C-Basic

저 자 : Naba.barkakati

출 판 사 : Sams:

정 가 : 18000원

==============================




4. 구조체의 초기화

1) 구조체 변수의 초기화

구조체 변수를 초기화 하는 것은 일차원 배열을 초기화 하는 것과 매우 유사하다. 단지 다른 점이 있다면 각 초기치가 대응하는 구조체 구성원(member)의 데이터형과 일치해야 한다는 것과 구조체 구성원이 배열일 경우 배열 크기를 생략할 수 없다는 점이다.

구조체 변수를 초기화 하려면 구조체 변수가 static 변수이거나 extern변수 이어야 한다. 구조체 변수가 static 변수인지 extern 변수인지는 구조체 변수가 정의된 위치에 의해서 결정되는 것이 아니라 구조체 변수가 선언된 위치에 따라서 구별된다.


『 실습 09-03 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c09-03.c : 구조체 변수의 활용

*------------------------------------------------------------------------------------------------*/

static date {

int year;

int month;

int day;

};

main( )

{

static struct date today = { 1991, 9, 31};

printf("오늘은 %d년 %d월 %d일 입니다.\n",

today.year, today.month, today.day);

}

☞실행 결과

c>09-03

오늘은 1991년 9월 31일 입니다.

『 실습 09-04 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c09-04.c : 구조체 변수의 초기화

*------------------------------------------------------------------------------------------------*/

struct book {

char title[30];

char author[20];

char press[20];

int value;

} ;

main( )

{

static struct book dos = {

"Dos Power user's guide", /* dos.title */

"KRIS SAMSA", /* dos.author */

"McGraw-Hill", /* dos.press */

8000 /* dos.value */

}, /* 각 변수는 콤마(,)로 구분한다. */

msc = {

"MicroSoft-C-Basic", /* msc.title */

"Naba.barkakati", /* msc.author */

"Sams", /* msc.press */

18000 /* msc.value */

};

printf("\n================================\n");

printf(" 책 명 : %s\n:, dos.title);

printf(" 자 자 : %s\n:, dos.author);

printf(" 출 판 사 : %s\n:, dos.press);

printf(" 정 가 : %d\\\n:, &dos.value);

printf("\n=============================\n");

printf("\n================================\n");

printf(" 책 명 : %s\n:, msc.title);

printf(" 자 자 : %s\n:, msc.author);

printf(" 출 판 사 : %s\n:, msc.press);

printf(" 정 가 : %d\\\n:, &msc.value);

printf("\n=============================\n");

}

『 실습 09-05 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c09-05.c : 구조체 배열의 활용

*------------------------------------------------------------------------------------------------*/

struct sungjuk {

int number;

int name[20];

char sex;

int age;

int score;

int rank;

};

main( )

{

int i;

static struct sungjuk list[ ] = {

{ 1101, "홍길동", "남", 25, 88, 13},

{ 1204, "김남순", "여", 21, 87, 14},

{ 1306, "김알지", "남", 25, 90, 8},

{ 1412, "장보고", "남", 28, 89, 10},

};

printf("\n----------------------------------------------------");

printf("\n 번호 성 명 성별 나이 점수 순위 ");

printf("\n----------------------------------------------------");

for ( i=0; i<=3; i++ )

printf("\n%4d %6s %2s %2d %2d %2d",

list[i].number, list[i].name, list[i].sex,

list[i].age, list[i].score, list[i].rank);

printf("\n----------------------------------------------------");

}

☞실행 결과

c>09-05

-----------------------------------------------------

번호 성 명 성별 나이 점수 순위

-----------------------------------------------------

1101 홍길동 남 25 88 13

1204 김남순 여 21 87 14

1306 김알지 남 25 90 8

1412 장보고 남 28 89 10

-----------------------------------------------------

『 실습 09-06 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c09-06.c : 구조체 포인터 변수의 활용

*------------------------------------------------------------------------------------------------*/

struct sungjuk {

int number;

int *name;

char *sex;

int age;

int score;

int rank;

};

main( )

{

int i;

static struct sungjuk *pointer;

static struct sungjuk list[ ] = {

{ 1101, "홍길동", "남", 25, 88, 13},

{ 1204, "김남순", "여", 21, 87, 14},

{ 1306, "김알지", "남", 25, 90, 8},

{ 1412, "장보고", "남", 28, 89, 10},

};

printf("\n----------------------------------------------------");

printf("\n 번호 성 명 성별 나이 점수 순위 ");

printf("\n----------------------------------------------------");

pointer = list;

for ( i=0; i<=3; i++, pointer++ )

printf("\n%4d %6s %2s %2d %2d %2d",

pointer-->number, pointer-->name, pointer-->sex,

pointer-->age, pointer-->score, pointer-->rank);

printf("\n----------------------------------------------------");

}

☞실행 결과

c>09-06

-----------------------------------------------------

번호 성 명 성별 나이 점수 순위

-----------------------------------------------------

1101 홍길동 남 25 88 13

1204 김남순 여 21 87 14

1306 김알지 남 25 90 8

1412 장보고 남 28 89 10

-----------------------------------------------------

5. 공 용 체 (Union)

공용체는 하나의 데이터를 여러 개의 변수가 공용할 수 있게 해주는 데이터 형이다. 공용체의 정의 방법과 선언 방법은 구조체와 동일하다. 단, 구조체는 모든 자료가 별개의 기억장소를 배정받지만 공용체의 경우에는 가장 긴 것의 자료 형에 맞추어 메모리를 할당받는다. 공용체의 멤버로는 주로 구조체를 사용하며, 공용체의 정의 형식은 다음과 같다.

union 공용체 택 { 멤버1; 멤버2; ...; };

<예제4> 공용체의 사용 보기

<리스트4> | <리스트4>의 공용체는 아래와 같

union abc { | 은 형태로 기억장소를 배정한다

char a; |

int b; | | |

long c; | +------+---- +----+

}; | | 78 +-- a | |

main() | +------+ | b |

{ | | 56 | | |

union abc val; | +------+-----+ | c

val.c = (long)0x12345678; | | 34 | |

printf("c = %08lx\n", val.c); | +------+ |

printf("b = %08x\n", val.b); | | 12 | |

printf("a = %08x\n",val.a); | +------+ ---+

} | | |

위의 그림과 같이 상위 바이트와 하위 바이트가 바뀌어 저장되는 것을 역워드 형식이라고 하는데 80x계의 CPU에서는 역워드 형식으로 자료가 저장된다. <리스트4>내의 프로그램에서는 각각의 바이트를 독립적으로 억세스할 수 없지만 공용체의 멤버로 구조체를 사용하면 각각의 바이트를 개별적으로 억세스할 수 있다.

<예제5> 공용체의 사용 보기 (II)

<리스트5>

struct str { | <리스트5>의 공용체는 아래와

char c1; | 같은 형태로 기억장소를 배정

char c2; | 한다.

char c3; |

char c4; | | |

}; | +------+---+ -----+ --+

union abc { | | 78 | c1| - a | |

struct str chr; | +------+ | |b |

char a; | | 56 | c2| | |

int b; | +------+ | -----+ |c

long c; | | 34 | c3|구조체 |

}; | +------+ | chr |

main() | | 12 | c4| |

{ | +------+ --+ ---------+

union abc val; | | |

val.c = (long)0x12345678; |

printf("a = %8lx\n", val.a); |

printf("b = %8x\n", val.b); | <리스트5>에서 c3를 가리킬 경

printf("c = %8x\n", val.c); |우에는 val.chr.c3로 기술해야

printf("c1 = %8x\n",val.chr.c1); |한다. 이것은 '공용체 val에 속

printf("c2 = %8x\n",val.chr.c2); |해있는 구조체 chr의 멤버 c3'라

printf("c3 = %8x\n",val.chr.c3); |는 의미이다. 구조체의 요소를

printf("c4 = %8x\n",val.chr.c4); |공용체로 선언해 두면 자료를 전

} |체적으로 통합하여 다룰수 있고

개별적으로도 다룰 수 있다.

구조체나 공용체를 함수의 인수로 사용할 때는 구조체나 공용체의 주소를건내주어야 하며, 받는 측에서는 그것을 포인터로 받아온다. 예를 들어 test()라는 함수에 <리스트5>에서 정의한 공용체 val을 전달하려면 다음과 같이 하면 된다.

호출측 : test(&val);

...

피호출측 : void test(union val *abc)

{ ....

test( )함수에서는 공용체 val을 abc라는 이름으로 사용한다. 구조체와 공용체의 활용은 초보자에게는 다소 어려운 개념이므로 보다 깊은 내용은 생략하겠다.

구조체나 공용체의 개념을 왜 익혀야 하는지 의문을 가지는 사람이 있을지 모르나, C로 그래픽 처리를 하기 위해서 그래픽 관련 내장 함수들을 쓴다거나, 어셈블리 루틴을 추가하려는 경우에는 구조체와 공용체의 개념을 알고 있는 것이 훨씬 유리하다. 왜냐하면 그래픽 처리를 위한 함수들은 대부분 구조체 형채로 제공되며, 어셈블리와 관계되는 항목들은 여지없이 공용체로 지원되기 때문이다. 만약 구조체와 공용체를 전혀 모른다면 컴파일러에서 지원하는 각종 라이브러리 루틴을 제대로 활용할 수가 없다.

<예제6> 어셈블리 루틴의 이용(공용체의 사용 보기(III))

여러분들의 대부분은 어셈블리를 모를 것이므로 이 항목을 가볍게 읽고넘어가자.

어셈블리에서는 화면소거를 BIOS인터럽트 10H의 6번이나 7번을 이용하여처리하는데, 이 때의 레지스터는 다음과 같은 용도로 사용된다.

AL: 화면을 스크롤할 줄의 수 (0이면 화면을 지운다)

CH: 가상 윈도우의 좌측상단 X좌표 (row)

CL: 가상 윈도우의 좌측상단 Y좌표 (column)

DH: 가상 윈도우의 우측하단 X좌표 (row)

DL: 가상 윈도우의 우측하단 Y좌표 (column)

BH: 가상 윈도우의 배경색 코드

AH: 기능 번호(6:위로 스크롤, 7:아래로 스크롤)

화면전체를 소거할 경우에는 윈도우 좌표를 (0,0), (79,24)로 지정하고 AL에 0을 주면 된다.

도스 인터럽트를 사용할 경우에는 프로그램 첫머리에 #include <dos.h>를삽입해야 하는데 dos.h에는 레지스터에 관한 사항이 구조체와 공용체로 정의되어 있어 그것을 우리가 프로그램에서 사용하기 위함이다.

<dos.h에 삽입되어 있는 레지스터에 관한 선언>

struct WORDREGS {

unsigned int ax,bx,cx,dx,si,di,cflag,flags;

};

struct BYTEREGS {

unsigned char al,ah,bl,bh,cl,ch,dl,dh;

};

union REGS {

struct WORDREGS x;

struct BYTEREGS h;

};

ax레지스터는 al,ah로 구성되어 있다.(bx,cx,dx도 마찬가지이다)

공용체 REGS가 선언이 되어 있는데, 우리가 ax를 지정하기 위해서는 x.ax,ah나 al을 지정하기 위해서는 h.ah, h.al로 기술해야 한다.

<리스트6>

void clrscreen()

{

union REGS r; /* 공용체 REGS를 r변수에 할당 */

r.h.al = 0; /*스크롤할 줄의 수*/

r.h.ch = 0; /*좌측 코너 row */

r.h.cl = 0; /*좌측 코너 col */

r.h.dh = 24; /*우측 코너 row */

r.h.dl = 79; /*우측 코너 col */

r.h.bh = 0; /*컬러 코드*/

r.h.ah = 6; /*기능 번호*/

int86(0x10,&r,&r); /*BIOS인터럽트 10H 호출*/

} /*int86()함수는 BIOS인터럽트를 호출하는*/

/* 내장함수이다 */

이해는 잘 안가지만, 뭔가 고급 기능 구현에 구조체와 공용체가 큰 비중을 차지하고 있다고 느껴지지 않는가?















Ⅹ. 선 행 처 리 기

1.선행 처리기의 개념

선행 처리기(preprocessor)란 그 단어에서 알 수 있듯이 원시 프로그램이 컴파일되기 전에 원시 프로그램에 대해 일련의 작업을 행하는 것으로, 예를 들면 프로그램 상에 기술된 기호화된 약식 표현을 모두 원래의 표현대로 바꾸어주는 역할을 하거나 다른 프로그램 내에 포함시키는 등의 역할을 한다.

일반적인 C컴파일러(compiler)는 원시 프로그램 전체를 선행 처리기로 일단 처리한 후 계속해서 컴파일(compile)하고 마지막으로 링크(link)함으로써 실행 가능한 프로그램(.EXE화일)을 생성한다.

2. 실행 가능한 프로그램의 생성 과정

일반적인 C컴파일러에 의해서 원시 프로그램이 실행 가능한 프로그램으로 만들어지는 과정을 그림으로 나타내면 다음과 같다.




원시 프로그램
















선행 처리기










중개 프로그램
















컴파일러







라이브러리


목적 프로그램














링커


















실행 프로그램











컴파일러의 입장에서 보면 선행 처리기에 의해서 처리된 중개 프로그램은 원시 프로그램의 일종으로 취급한다. 즉 선행 처리기는 목적 프로그램(기계어 프로그램)을 생성하는 것이 아니다. 선행 처리기가 하는 작업은 원시 프로그램을 컴파일하기 좋도록 가공하는 작업이라 할 수 있다. 다시 말해서 선행 처리기는 원시 프로그램 내의 모든 선행 처리기 지시어를 컴파일 할 수 있는 C문장으로 바꾸어 주는 작업을 수행한다.

선행 처리기의 대표적인 지시어는 #define과 #include문이다.

3. #define문에 의한 단순 대체

1) #define문이란

#define문은 선행 처리기 지시어 중에서 가장 많이 사용되는 것 중의 하나로서 매크로를 정의할 때 사용한다. 즉 단순한 상수에서부터 매우 복잡한 형태의 문장들을 간단한 이름으로 정의하기 위해서 사용한다.

2) #define문에 의한 단순 대체

#define문에 의하여 단순 대체시킬 때의 일반적인 형식은 다음과 같다.

<일반형식>

#define 매크로명 대체 문자열 (또는 식)


[보기] #define문의 사용 예

#define PI 3.141592

↓ 매크로 ↁ치환 문자열

선행 처리기 지시어

위의 #define문은 매크로 PI의 값으로 치환 문자열 3.141592를 사용하도록 정의한 것이다. 즉 선행처리기에 의하여 #define으로 정의되어 있는 매크로명을 원시 프로그램(source program)에서 탐색하여 모두 대체 문자열로 대체시킨다.

매크로명과 대체 문자열 사이는 한개 이상의 공백 문자로 반드시 분리하여야 한다. 그리고 매크로명은 일반 변수처럼 소문자를 사용하여도 관계없으나 일반 변수와 구별하기 위하여 대문자를 사용하는 것이 관례처럼 되어 있다.



4. 선행 처리기의 동작 절차

원시 프로그램이 실행 가능한 프로그램으로 만들어지기까지의 과정을 선행처리기를 중심으로 하여 나타내면 다음과 같다.




원시 프로그램

#define PI 3.141592

main( )

{

printf("원주율 = %d\n", PI);

}



















선행 처리기























선행 처리기에

의해 변경된

중개 프로그램

main( )

{

printf("원주율 = %d\n", 3.141592);

} ↓

PI가 치환된 값




















컴파일러

























링 커

























실행 프로그램

(.EXE프로그램)










『 실습 10-01 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c10-01.c

*------------------------------------------------------------------------------------------------*/

#define PI 3.141592

#define R 10

main( )

{

float area, length;

area = PI * R * R;

length = 2 * PI * R;

printf("원의 면적 = %f\n", area);

printf("원의 둘레 = %f\n", length);

}

☞실행 결과

c>10-01

원의 면적 = 314.159200

원의 둘레 = 62.831841

《연습 1》위 프로그램이 선행 처리기에 의해 처리된 중개 프로그램은 ?

% 만일 반지름이 30인 원의 면적과 원의 둘레를 구하려면 위 프로그램을 어떻게 변경 하여야 할까 ?

프로그램의 본문은 그대로 두고 #define문만을 다음과 같이 수정하면 된다.

#define R 30

위의 선행 처리기의 지시어인 #define문을 사용하면 프로그램 내의 모든 관계되는 데 이터를 수정할 필요없이 해당되는 #define문만 수정하면 되므로 프로그램의 수정을 손쉽게 할 수 있다.

『 실습 10-02 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c10-02.c

*------------------------------------------------------------------------------------------------*/

#define LINE printf("====================\n");

#define TEXT printf(" 축하합니다!!! \n");

main( )

{

LINE

TEXT

LINE

}

☞실행 결과

c>10-02

=====================

축하합니다!!!

=====================

《연습 2》위 프로그램이 선행 처리기에 의해 처리된 중개 프로그램은 ?

『 실습 10-03 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c10-03.c

*------------------------------------------------------------------------------------------------*/

#define BANBOK for( i=1; i<=10; i++ )

#define PRINT_I printf("%3d", i);

main( )

{

int i;

BANBOK

PRINT_I

}

☞실행 결과

c>10-03

1 2 3 4 5 6 7 8 9 10

《연습 3》위 프로그램이 선행 처리기에 의해 처리된 중개 프로그램은 ?

5. 인수를 갖는 매크로 정의

#define문을 사용하여 인수를 포함하는 매크로를 정의할 수 있는데 그 일반 형식은 다음과 같다.

<일반형식>

#define 매크로명(가인수, 가인수 ) 식(또는 대체 문자열)


[보기] #define문의 사용 예

#define SQR (x) x*x

↓ ↁ가인수ↁ식(가인수를 포함한 매크로 본체)

매크로 명

『 실습 10-04 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c10-04.c

*------------------------------------------------------------------------------------------------*/

#define SQR(x) x*x

#define PRINT(X) printf("%d ^ 2 = %d\n", x, SQR(x));

main( )

{

int x=2, y;

y=SQR(x+3);

PRINT(X)

PRINT(3)

PRINT(y)

}

☞실행 결과

c>10-04

2 ^ 2 = 4

3 ^ 2 = 9

11 ^ 2 = 121

위 프로그램에서 사용된 아래 문장들은

y=SQR(x+3);

PRINT(X)

PRINT(3)

PRINT(y)

은 선행 처리기에 의하여 다음과 같이 대체된다.

printf("%d ^ 2 = %d\n", x, x*x);

printf("%d ^ 2 = %d\n", 3, 3*3);

printf("%d ^ 2 = %d\n", y, y*y);



《연습 4》위 프로그램의 어느 부분을 수정하여야 실행 결과가 다음과 같이 출력 되겠는 가?

☞실행 결과

c>10-04

2 ^ 2 = 4

3 ^ 2 = 9

5 ^ 2 = 25

『 실습 10-05 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c10-05.c

*------------------------------------------------------------------------------------------------*/

#define leap_year(year) ( year %4 == 0 && year % 100 != 0 \

|| year % 400 == 0 )

main( )

{

int y;

printf("연도 = ? ");

scanf("%d", &y);

if ( leap_year (y) )

printf("%d년은 윤년이다.\n", y);

else

printf("%d년은 평년이다.\n", y);

}

☞실행 결과 ☞실행 결과 ☞실행 결과

c>10-05 c>10-05 c>10-05

연도 = ? 1991 연도 = ? 2000 연도 = ? 2100

1991년은 평년이다. 2000년은 윤년이다. 2100년은 평년이다.

% 아래의 문장에서 사용된 \는 행을 계속하기 위하여 사용되었다.

#define leap_year(year) ( year %4 == 0 && year % 100 != 0 \

|| year % 400 == 0 ) 행 계속문자

《연습 5》위 프로그램이 선행 처리기에 의해 처리된 중개 프로그램은 ?

『 실습 10-06 』예제 프로그램

/*------------------------------------------------------------------------------------------------

* c10-06.c

*------------------------------------------------------------------------------------------------*/

#define ABS(x) ((x<0) ? (-x) : (x) )

main( )

{

int n, result;

printf("n = ? ");

scanf("%d", &n);

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

}

☞실행 결과 ☞실행 결과 ☞실행 결과

c>10-05 c>10-05 c>10-05

x = ? -14 x = ? 14 x = ? 0

ABS(-14) = 14 ABS(14) = 14 ABS(0) = 0

위 프로그램은 메모리 효율성 문제와 속도 문제 등을 고려하여 함수를 사용하지 않고 매크로로 정의한 예이다.


6. #include문

1) #include문의 기능

#include문은 컴파일러에게 다른 지정된 원시 화일을 메인 원시 프로그램에 포함 시키도록 지시할 때 사용한다.

예를 들면 각종 매크로 정의문만을 따로 모아 하나의 화일로 정의해 놓고 이 매크로가 필요한 프로그램에서 #include문을 사용하여 읽어 들이도록 하면 프로그램의 크기를 줄일수 있을 뿐만아니라 관리하기도 편리해진다.

따라서 매우 복잡한 데이터 구조나 여러 프로그램에서 공통으로 사용되는 데이터들도 한 파일로 따로 구성해 놓고 필요한 프로그램에서 #include문을 사용해서 원시 프로그램 내에 포함시키면 편리할 것이다.

2) #include문의 일반형식

#include문의 일반 형식은 다음과 같다.

<일반형식>

#include <화일이름>

또는

#include "화일이름"

[보기] #define문의 사용 예

① #include <stdio.h>

② #include "b:sample.c"

①은 시스템 디렉토리에 준비되어 있는 stdio.h 화일을 작성 중인 프로그램에 포함 시키라는 지시이다.

②는 사용자가 작성한 b:드라이브 중에서 sample.c화일을 작성중인 프로그램에 포함 시키라는 지시이다.

% 일반적으로 #include 문 기술시에 < >는 시스템이 미리 준비해 놓은 포함 화일을 읽어 들일때 사용하고, " "는 사용자 자신이 작성한 포함 화일을 읽어 들일때 사 용한다.

% #include문 다음에 기술하는 화일 이름에는 path지정을 포함 시킬수 있다. MS-DOS 에서 path 지정시에 \를 사용하듯이 #include문에서도 \를 사용한다.

[보기] path지정 예

#include "b:\work\sample.c"


% #include문 다음에 사용되는 화일의 확장자는 어떠한 영문자를 사용해도 관계없으나 일반적으로 다음과 같은 두가지의 문자가 많이 사용된다.

.h header 화일로 사용될 경우

.c 사용자가 C언어로 작성한 화일을 사용할 경우

% header 화일이란 포함시킬 화일에 #define문이나 #include문 또는 외부 변수 혹은 함수의 선언 등을 포함한 화일을 말한다. 이 화일의 내용은 C언어의 문법에 맞는 것이라면 어떠한 것이든 관계없이 사용할 수 있다.

『 실습 10-07 』다음과 같은 화일을 작성하여 sample.h라는 이름으로 저장하자.

/*------------------------------------------------------------------------------------------------

* c10-07.c

*------------------------------------------------------------------------------------------------*/

#define ADD add= a+b;

#define SUB sub= a-b;

#define MUL mul= a*b;

#define DIV div= a/b;


『 실습 10-08 』다음 프로그램을 작성하여 컴파일한 후 실행하여 보자

/*------------------------------------------------------------------------------------------------

* c10-08.c

*------------------------------------------------------------------------------------------------*/

#include "sample.h"

main( )

{

int a=20, b=10;

int add, sub, mul, div;

ADD

SUB

MUL

DIV

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

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

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

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

}

☞실행 결과

c>10-08

10 + 20 = 30

10 - 20 = 10

10 * 20 = 200

10 / 20 = 2

7. 그 외의 선행 처리기 (#if, #ifdef, #ifndef, #else, #endif)

이것들은 조건적인 컴파일을 가능하게 해 주는데, 대형 프로그램에서 주로 사용된다.

#ifdef MAVIS

#include "horse.h"

#define STABLES 5

#else

#include "cow.h"

#define STABLES 15

#endif /* if 블럭이 끝남을 알리는 기능을 한다. */

#ifdef지정어는 그 다음에 오는 명칭(MAVIS)이 선행처리기로 정의되었으면, 그 지점에서 다음에 오는 #else나 #endif이전까지에 있는 명령들을 처리하게 한다.즉, #ifdef은 다음의 명칭이 정의되었으면 참의 판단을 하고#ifndef은 다음의 명칭이 정의가 안 되었으면 참의 판단을 내린다.

#if SYS == "IBM" /* #if는 if문과 기능이 비슷하다 */

#include "ibm.h"

#endif

이러한 조건 컴파일의 용도는 프로그램의 호환성을 높이기 위한 것이다. 화일 처음에 있는 몇 개의 중요한 정의만 바꾸면 다른 시스템을 위한 다른화일이 포함되고 다른 값들이 설정된다.

8. typedef

typedef문은 프로그래머 자신만의 수형명을 만들어 준다. #define과 기능이 비슷하지만 아래와 같은 차이점이 있다.

1) #define와는 달리, 단지 데이터 수형에만 기호적인 명칭을 사용할 수 가 있다.

2) typedef는 선행처리기에 의해처리되는것이아니라 컴파일러에 의해 처리되는 내장명령어이다.

<리스트10>

typedef float REAL; /* float수형명을 REAL으로 사용할 수 있다 */

typedef char *STRING;

main()

{

REAL a = 12.3243;

STRING name = "We are the world!";

...

위에서 STRING name;은 char *name;과 같다.

또한 구조체에 대해서도 사용할 수가 있다.

typedef struct COMPLEX {

float real;

float imag;

};

main()

{

COMPLEX son;

...

<typedef를 사용하는 이유 3가지>

(1) 자주 사용되는 수형에 대해서 인식하기 쉬운 명칭을 제공하기 위함이다.

(2) 복잡한 수형명을 간단하게 하기 위해서이다.

(3) 프로그램의 이식을 용이하게 하기 위해서이다.

(2)의 경우의 예를 들면, typedef char *FRPTC () [5];는 FRPTC가 char 5개로 구성된 배열을 가리키는 포인터를 반환하는 함수의 수형임을 나타낸다. ( FRPTC flump;는 char *flump()[5];와 같다. ) 포인터의 깊은 곳으로 들어가면 아주 복잡하고 헷갈리는 선언들이 많이있다. 이 글의 성격과는 맞지 않으므로 자세한 설명은 피하겠다.

(3)의 경우의 예를 들면, 프로그램이 16비트 숫자를 사용할 필요가 있을때, 어떤 시스템 (OS에 따라)에서는 short가 어떤 시스템에서는 int가 16비트이다. 그 때 프로그램의 첫머리에 typedef int TWOBYTE;로 선언해 두고 int를 short로만 바꾸어 주면 프로 그램 이식을 간편히 할 수가 있다.

9. 명령행 인자(Command-line arguments)

아래 한글 사용시 도스에서 hwp c:\data\letter.hwp와 같이 명령을 내리면 프로그램을 시작과 동시에 letter.hwp화일이 뜨는 것을 알고 있을 것이다. 이러한 것을 어떻게 구현할까? 명령행이란 프로그램을 실행시키기 위해 명령어를 입력해 놓은 행을 말한다.

우리가 보통 프로그램을 작성할 때 main( )이라고만 기술하였는데, main( )함수도 인자가 존재한다. 아래 예제를보자.

<예제8> 명령행 인자를 사용한 프로그램 - I

<리스트11> 화일명을 copystr.c라고 하자.

#include <stdio.h>

main(argc, argv)

int argc;

char *argv[];

{

int c;

for (c = 1;c < argc;c++)

printf("%s",argv[c]);

printf("\n");

}

위 프로그램을 컴파일 시킨 후, 명령행에서 copystr My name is robocap.이라고 입력하면, My name is robocap.이라고 출력한 후 프로그램을 종료한다.

main( )함수는 두 가지 인수를 가진다. 첫번 째 인자(argc)는 명령어에 따르는 문자열의 갯수를 나타낸다. argc는 argument count의 약자로써, 다른인자명도 사용할 수 있으나 관례적으로 argc를 사용한다. 문자열의 구분은공백으로 하는데, 위의 예제는 5개의 문자열을 가진다.

두번째 인자(argv : argument value)는 문자열 포인터 배열이다. 명령행의 각 문자열은 그 자신에 대한 포인터로 배열에 저장된다. 위의 경우,

argv[0]은 프로그램명 copystr을 가리킨다.

argv[1] = "My" argv[4] = "robocap."을 각각 가리킨다.

argv[2] = "name"

argv[3] = "is"

<예제9> <#1편>의 <예제2>를 명령행 인자를 사용하는 융통성 있는 프로그

램으로 바꿔 보자.

<리스트12> 프로그램명이 son.c라면,

#include <stdio.h>

main(int argc,char *argv[])

{

FILE *in;

int ch;

if (argc==1) printf("Usage: son filename.ext\n");

else {

if ((in=fopen(argv[1],"r")) != NULL) {

while ((ch=getc(in)) != EOF)

putc(ch,stdout);

fclose(in);

}

else printf("file not found..\n");

}

}

. 화일 조작 / 기타의 것들


1. 입출력의 종류

화일을 대상으로 하는 작업의 종류는 쓰기, 추가, 읽기의 3가지로 나눌수 있다.

⼑ 쓰기 - 화일을 새로 만드는 것인데, 이미 같은 화일이 존재하면 기존의자료는 모두 지 워진다.

⼑ 추가 - 화일 뒷부분에 새로운 자료를 추가하기 위해 사용되는데, 선택한 화일이 발견되 지 않으면 그 자체로 새로운 화일이 형성된다.

⼑ 읽기 - 이미 만들어진 화일에서 자료를 읽어들이는 것으로서, 해당 화일이 존재하지 않 으면 에러를 발생시킨다.

이 세가지 이외에도 '읽기/쓰기 겸용', '읽기/추가 겸용'의 형태를 지원한다.

2. 입출력의 절차

화일을 대상으로 작업하는 경우에는 반드시 다음의 절차를 거쳐야 한다.

(1) 화일 open - 입출력 대상이 되는 화일명과 mode를 지정하는 절차

(화일 입출력을 위한 버퍼를 할당하게 된다)

(2) 입출력 수행

(3) 화일 close - 입출력 과정을 끝낸 다음에는 반드시 이 과정을 실행시켜 (1)에서 할당 된 버퍼를 해제해야 한다. 화일을 닫지 않은채 프로그램의 실행을 종료 시키면 화일이 깨지는 경우가 있으므로 주의 하여야 한다.

3. 화일 처리에 관한 함수

1) 화일의 개방

⼑선언문 FILE *fp : 화일 구조체 포인터 변수를 선언한다. 이 함수는 변수의 선언 부분 (보통 선언부의 맨 끝)에서 정의한다.(fp는 임의 변수임) ===> <stdio.h>에 화일에 관한 자료들을 저장할 공간이 구조체 'FILE'로 선언되어 있다.

⼑fp = fopen("화일명","mode") : 화일을 오픈하고 화일 포인터를 초기화한다. 화일 포인터 는 자료가 화일 내의 어느 부분에 위치해 있는지를 기억 하는 변수로서 자료를 읽거나 쓸 때마다 자료의 크기만큼 뒤로 이동한다. 화일오픈에 실패하면 이 함수의 값은 null pointer가 된다. mode는 아래의 모드가 있다.

<화일포인터 위치>

"r" : 화일을 읽기 전용으로 연다(read) 화일 처음

"w" : 화일을 새로이 생성하고 쓰기 전용으로 연다(write) 화일 처음

"a" : 화일을 추가 전용으로 연다(append) 화일 끝

"r+" : 화일을 갱신용으로 연다(읽기,쓰기 모두 가능) 화일 처음

"w+" : 화일을 새로이 생성하고 갱신용으로 연다 화일 처음

"a+" : 화일이 없는 경우 새로이 생성하고 갱신용으로 화일 끝

연다

모드지정문자 뒤에 t나 b를 붙여 텍스트화일과 이진화일임을 지정할 수 있다. 텍스트 화일은 ASCII코드를 이용하여 문자로써 저장된 화일을 말 하고, 이진 화일은 기계어코드를 저장할 때 사용되는 화일 형식이다.

⼑freopen("화일명","mode",fp) : fp가 가리키는 화일을 닫고 새로운 모드로 다시 연다. 이

함수는 이미 오픈된 함수의 모드를 바꾸는 경우에 이용한 다.

2) 화일의 종결

⼑fclose(fp) : fp로 지정한 화일을 닫는 함수이다. fclose()함수는 성공적인 패쇄이면 0을,

그렇지 못하면 -1을 반환한다.


3) 화일 입출력 함수

⼑fputs("문자열/변수",fp) : 문자열을 화일 포인터가 가리키는 위치에 수록한다. 문자열을 수록한 다음에는 화일 포인터 fp가 문자열의 길이만큼 뒤로 이 동한다.

⼑fputc(fp,'문자') : 문자 1개를 화일에 출력한다.

⼑fprintf(fp,"서식제어문자열",변수,..) : 변수의 내용을 서식제어 문자열의 포맷에 맞추어

화일에 출력한다. 출력 매체가 화일이라는 것만

다를 뿐 printf()함수와 용법이 같다.

⼑fgets(변수,길이,fp) : 화일 포인터가 가리키는 위치에서 지정된 (길이-1)만큼자료를 읽어

변수에 할당한다. 변수의 마지막에는 '\0'이 추가되는데 화일의 자 료 내부에 '\n'이 있거나 화일이 끝날경우에는 그 시점까지만 읽어 들인다. 화일에서 지정된 길이만큼 읽어들일 때는 수록된 문자열 의 길이보다 1문자 더 크게 지정해야 한다.

⼑fgetc(fp) : 화일에서 한 문자를 읽어 들인다. (내장함수이다)

⼑getc(fp) : 화일에서 한 문자를 읽어 들인다. (매크로함수이다)

⼑fscanf(fp,"서식제어 문자열",변수,..) : 화일에서 서식제어 문자열의 포맷대로 자료를 읽어

들여 변수에 할당한다. 입력매체가 화일이라는 것 만 다를 뿐 scanf()함수와 동일하다.

⼑fread(변수,길이,갯수,fp) : 화일 포인터의 현재 위치에서 지정된 길이만큼 지정된 갯수를 읽어들인다. 화일 끝이 검출되면 그 시점에서 읽어들이는 것 을 멈춘다. 함수의 값은 정상 수행인 경우에는 읽어들인 갯 수가 되며, 화일의 끝을 검출했을 경우에는 0이된다.

⼑fflush(fp) : 버퍼 내의 자료를 비운다. 디스크에 수록할 자료가 있으면 디스크에 수록할

자료가 있으면 디스크에 수록한 후 버퍼를 비운다. 보통은 자료의 수록을 확 실히 하기 위하여 사용된다. fclose()함수가 수행되면 자동으로 fflush()함수가 수행된다.

⼑feof(fp) : 화일의 끝인지를판정한다. 화일의 끝이아니면 0이외의 값이 되고, 끝이면 0이 된다.

⼑ftell(fp) : 화일 포인터의 위치를 구한다.

⼑fseek(fp,상대위치,모드) : 화일 포인터의 위치를 변경한다. 상대 위치는 수치 다음에 'L' 을 붙이고, 수식인경우에는 붙이지 않는다. 모드는 아래 세 가지 중 하나가 된다.

0: 화일의 시작부터 상대 위치를 계산한다.

1: 현재의 화일 포인터부터 상대 위치를 계산한다.

2: 화일의 끝부분부터 상대 위치를 계산한다.

<예제1> fseek( )의 사용 예

fseek(fp,5L,0); : fp를 화일의 시작위치에서 5바이트번째로 이동

fseek(fp,2L,1); : fp를 현재의 위치에서 2바이트 이동

fseek(fp,-1L,2); : fp를 화일의 끝에서 1바이트 전의 위치로 이동

이 때 함수의 수행이 성공적이면 변경된 화일 포인터 위치가, 실패하면 -1이 구해진다.

4. 화일 처리에 관한 예제들

<예제2> 텍스트 화일을 읽어 화면에 출력하는 프로그램 작성

<리스트1> 한 글자씩 읽어 한 글자씩 출력하는 프로그램

( fopen( )함수안의 화일명은 현재 디렉토리내에 있어야 한다 )

#include <stdio.h>

main( )

{

FILE *in; /* 화일에 대한 포인터를 선언 */

int ch;

if ((in=fopen("c:hello.c","r")) != NULL) {

/* in에 null pointer가 되돌려 지지 않는다면 */

/* 즉, 화일이 성공적으로 개방이 되면 */

while ((ch=getc(in)) != EOF) /* 화일에서 한 문자를 읽어 */

/* ch변수에 저장한다. 그리 */

/* 고 화일끝(EOF)이 아니면,*/

putc(ch,stdout); /* 표준 출력(화면)에 ch 출력 */

fclose(in);

}

else printf("file not found..\n");

}

<리스트2> 한 라인씩 읽어 한 라인씩 출력하는 프로그램

#include <stdio.h>

#define MAX 80

main( )

{

FILE *fpt;

char str[MAX];

fpt = fopen("c:hello.c","r");

while (fgets(str,MAX,fpt) != NULL)

puts(str);

}

<예제3> 다음 자료를 키보드에서 입력하여 화일로 작성하는 프로그램을

작성하여라.

---------------------------------------

이 름 주 소 전화번호

---------------------------------------

홍 길동 서울시 중구 신당동 432-3453

이 순신 경남 진해시 89-3455

김 유신 전북 부안군 34-1123

x <- (자료의 끝 표시)

<리스트3> 1:#include <stdio.h>

2:main( )

3:{

4: char name[8],addr[21],tel[9];

5: int n = 0;

6: FILE *fp;

7: fp = fopen("SAMPLE.DAT","a");

8: do {

9: printf("%2d. ",++n);

10: printf("성명 : "); gets(name);

11: if (name[0] == 'X' || name[0] == 'x') break;

12: printf(" 주소 : "); gets(addr);

13: printf(" 전화 : "); gets(tel);

14: fputs(name,fp); fputc('\n',fp);

15: fputs(addr,fp); fputc('\n',fp);

16: fputs(tel,fp); fputc('\n',fp);

17: } while (1);

18: fclose(fp);

19:}

#화일에 자료가 수록되는 형태: (화일내에서 '\n은 2바이트로 취급된다)

+-------------------------------------------------------

|홍 길동\n서울시 중구 신당동\n432-3453\n이 순신\n...

+-------------------------------------------------------

위 프로그램의 14행 - 16행에서 보면, fputs()함수에서는 문자를 화일에 수록 할때 각 문자열의 끝에 아무런 표시도 해주지 않으므로 자료를 구분하기 위해서 fputc()를 이용해 자료구분 문자의 하나인 '\n'문자를 추가하였다.

<예제4> 위에서 구축한 화일을 읽어 화면에 출력하는 프로그램 작성

<리스트4>

#include <stdio.h>

main()

{

char name[8],addr[21],tel[9];

int n=0;

FILE *fp;

fp = fopen("SAMPLE.DAT","r");

printf("--------------------------------------------\n");

printf("번호 이 름 주 소 전화번호\n");

printf("--------------------------------------------\n");

do {

fgets(name,25,fp);

if (feof(fp)) break; /* 화일 끝이 검출되면 중지 */

fgets(addr,25,fp);

fgets(tel,25,fp);

printf("%2d %-11s%-19s%8s\n",++n,name,addr,tel);

} while (1);

printf("--------------------------------------------\n");

fclose(fp);

}

위 프로그램을 실행시키면 데이터 화일내의 '\n' 때문에 출력결과가 이상하게 나온다. 위의 12, 14, 15행을 아래와 같이 각각 변경시키자.

fgets(name,25,fp); name[strlen(name)-1]='\0';

fgets(addr,25,fp); addr[strlen(addr)-1]='\0';

fgets(tel,25,fp); tel[strlen(tel)-1]='\0';

5. 순차화일과 랜덤화일

화일은 자료의 편성방법에따라 순차화일(Sequential file)과 랜덤화일(Random file)로 구분된다. 순차화일은 모든 자료가 발생한 순서대로 저장되고, 편성된 화일은 순차적으로 읽혀진다. 또한 화일 내의 특정한 데이터를갱신할 때에는 일단 화일을 모두 읽어들여 필요한 부분을 수정하고, 다시 처음부터 차례대로 디스크에 수록하는 화일 형태이다. 이러한 화일은 자료의 갯수가 적은 경우나 문서 화일, 자료의 변동이 거의 없는 고정형 자료인 경우에 유리하다.

랜덤화일은 자료를 일정한 크기(레코드)에 맞추어 저장한 다음, 레코드 단위로 입출력하는 형태의 화일이다. 이 것은 화일내의 특정 자료를 수정하는 경우 원하는 레코드만 읽어들여 수정한 다음 다시 그 자리에 기록하는 것이다.( 좀 더 개선된 경우는 인덱스 화일이라는 색인 화일을 만들어 데이터를 검색하기 편하도록 한 것이 있다 )

C에서 랜덤 화일의 처리를 위한 함수로는 fprintf(),fseek(),fread(),ftell() 등이 있다.

<예제5> <리스트3>의 프로그램을 랜덤화일 형식으로 작성하라.

<리스트5> #include <stdio.h>

main()

{

char name[8],addr[21],tel[9];

int n = 0;

FILE *fp;

fp = fopen("SAMPLE1.DAT","a+");

do {

printf("%2d. 성명:",++n); gets(name);

if (name[0]=='X' || name[0]=='x') break;

printf(" 주소:"); gets(addr);

printf(" 전화:"); gets(tel);

fprintf(fp,"%-11s%-19s%-8s\n",name,addr,tel);

} while (1);

fclose(fp);

}

#화일에 자료가 수록되는 형태: (1레코드당 40byte : \n은 2Byte로 처리)

+------------------------------------------------------------

|홍 길동 서울시 중구 신당동 432-3453\n이 순신 .. ..

+------------------------------------------------------------

fprintf( )함수는 따로 변수에 대한 '구분을 해주지않고' 서식제어 문자열대로 화일에 써 주는 함수임을 명심하라.

<예제6> 랜덤 화일을 화면에 출력하는 프로그램

정수 n을 입력하여 n번째 레코드를 읽어서 화면에 표시하라.

<리스트6> #include <stdio.h>

main( )

{

char name[12],addr[20],tel[9]; /* 배열크기를 */

int n; /* \0이 추가될 공간까지 적절히 확보함 */

FILE *fp;

fp = fopen("SAMPLE1.DAT","a+");

do {

printf("번호입력:");

scanf("%d",&n);

if (n<1) break;

fseek(fp,40*(n-1),0);

fgets(name,12,fp);

fgets(addr,20,fp);

fgets(tel,9,fp);

printf("성명:%s\n주소:%s\n전화번호:%s\n",

name,addr,tel);

} while (1);

fclose(fp);

}

C에서는 현재 레코드를 읽어들일 경우 현재의 화일 포인터 위치를 읽으며, 화일 포인터는 읽어들인 자료의 크기에 맞추어 자동으로 증가된다. 그러나 다른 위치에 있는 레코드를 읽어들일 경우에는 프로그래머가 직접 화일포인터를 이동시켜야 한다. fseek( )함수로 읽어들일 화일 포인터의 위치를지정할 때는 '(읽을 레코드 번호-1)*레코드당 바이트수'로 지정하여야 한다.

위 프로그램에서 fgets( )함수의 길이를 쓸 때는 반드시 읽어 들일려는 문자보다 1 많게 설정하여야 한다. 자세한 사항은 위에 기술한 화일 입출력 함수 부분을 확인하기 바란다.

fscanf( )함수를 이용하여 화일을 읽어들일 경우에는 fscanf( )의 특성상 자료내에 포함된 공백을 그 자료의 끝으로 판단하여 예기치 않은 결과가 발생할 수도 있으니 주의해야 한다.



back_1.JPG (13408 bytes)home_1.JPG (11522 bytes)   

BACKRUSH  대화방입장  유닉스명령  다음  자료실  Ascii Table   Exploit   원격접속  달력,시간   프로세스   오이까기  
지하철노선   Whois   RFC문서   SUN FAQ   SUN FAQ1   C메뉴얼   PHP메뉴얼   너구리   아스키월드 아이피서치