C언어강좌

제 0 장   C 언어의 특성

1. C 언어의 역사

C 언어의 발전과정은 아래의 표와 같다.

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

|  년  도  |      개     발        |       내             용         |

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

|  1960년  | 국제 위원회           | ALGOL 60                        |

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

|  1963년  | 케임브리지, 런던대학  | Combined Prgramming Language    |

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

|  1967년  | 케임브리지,마틴 리챠드| Basic Combined Prog. Language   |

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

|  1970년  | 벨 연구소,켄 톰슨     | B 언어                          |

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

|  1972년  | 벨 연구소,데니스 리치 | C 언어                          |

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

C 언어가 파생된 ALGOL 60  언어에서 PASCAL 언어도 파생되었기 때문에

PASCAL 언어도 C 언어와 비슷한 점을 많이 가지고 있다. 1970년대  초에

UNIX 시스템을 만들기 위해 개발된 C 언어는 20여년이 지난 지금에  와서야

많은 사람들이 애용함으로 그 전성기를 맞고 있다.

2. C 언어의 장점

C 언어는 워낙 많은 사람들이 선호하는  좋은 언어라는 점에서 그 장점

이 많겠으나 이를 요약하여 몇가지로 간추려보면 다음과 같다.

(1) 이식성이 높다.

C 언어는 다양한  연산자, 데이타형, 함수 등을 가지고  있으며 특

정 시스템에서도 수행되도록 작성된 프로그램도 수정  없이 혹은 약간의 수정

을 거쳐 다른 시스템에서도 수행할 수 있는 언어이다.

(2) 융통성이 많다.

컴파일러가 에디터로 작성한 원시 프로그램을  기계어로 번역할 때

형식을 따지지  않으며, 어셈블리어와 연관되어  시스템의 미세한  제어를 할

수 있고, 융통성이  많은 UNIX 운영체제가 C 언어로 만들어진  것만 보아도 C

언어의 융통성을 짐작할 수 있다. 모듈러 프로그램이 가능하기 때문에

프로그램 경력이 쌓여지면  이미 작성한 프로그램 중 많은 부분을  다시 사용

할 수 있기 때문에 편리하기도 하다.

(3) 강력하다.

C 언어는 고급언어이면서도 비트  조작이 가능하고, 미세한 시스템

의 제어를 할 수 있는 언어이며, 다양한  연산자와 데이타 형, 그리고 터보 C

2.0의 경우만 보더라도 450개가 넘는 함수를  보유하고 있다. 뿐만 아니라 시

스템 제어를 통해 함수를 스스로 만들어 사용할 수 있다.

제 1 장   C 프로그램의 개요

1. TURBO C 의 운영

먼저 TURBO C  를 인스톨하고 TC를 실행하면 에디터와   컴파일과 링크

를 할 수 있는 통합환경이 나온다.  TURBO C의 HOT KEY는 다음 표와 같다.

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

|   키    |                 기               능                      |

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

|   F1    | 도움말                                                   |

|   F2    | 저장                                                     |

|   F3    | 불러오기                                                 |

|   F5    | Zoom 기능 (테두리를 없애고 생기게 하는 토글키)           |

|   F6    | 에디터와 에러멧세지 간 작업 이동                         |

|   F7    | 전에 발생한 에러 표시                                    |

|   F8    | 그 다음 에러 표시                                        |

|   F9    | make 기능                                                |

|   F10   | 메뉴 호출                                                |

| ALT+F1  | 바로 전 도움말 화면 호출                                 |

| ALT+F3  | 불러오기 pick 방식                                       |

| ALT+F5  | MAIN 스크린과 사용자 스크린 토글                         |

| ALT+F6  | 실행 화면의 내용 변경                                    |

| ALT+F7  | 바로 이전 에러 표시                                      |

| ALT+F8  | 다음 에러 표시                                           |

| ALT+F9  | 링크는 수행하지 않고 컴파일만 하도록 함                  |

| CTRL+F1 | 현재 커서위치의 명령어에 관한 C언어 사전                 |

| CTRL+F2 | 실행중인 프로그램을 첫상태로 만듦                        |

| CTRL+F3 | Call stack을 만듦                                        |

| CTRL+F4 | 해당 연산시기의 결과를 수행                              |

| CTRL+F7 | 기술되는 연산식을 추가                                   |

| CTRL+F8 | BREAK POINT ON/OFF 토글                                  |

| CTRL+F9 | 프로그램 실행                                            |

|SHIFT+F10| TURBO C 의 version 스크린 표시                           |

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

2. C 프로그램의 구성

간단한 C 프로그램을 통해 C 프로그램의 기본적인 특성을 살펴보자.

#include <stdio.h>  --------------------------------------(1)

main() ---------------------------------------------------(2)

{ --------------------------------------------------------(3)

int age, day; ----------------------------------------(4)

age = 25; --------------------------------------------(5)

day = age * 365; -------------------------------------(6)

/* 나이에 1년의 날수인 365를 곱한다. */ ------(7)

printf("내 나이는 %d살이고 살아온 날수는 %d일이다."

, age, day); -----------------------(8)

} --------------------------------------------------------(9)

(1) #include <stdio.h>

include란 포함한다는  뜻이다. 즉 stdio.h 라는  화일을 컴파일하기

전에 그 자리에 포함시켜 놓고 컴파일을  하게 된다. 이런 의미에서 #include

는  선행처리기  (preprocessor)  라고  한다.  stdio.h라는  화일은standard

input output header file로서 표준입출력장치에   관한  명령어나 함수를 정

의해 놓은 화일을  말한다. 다른 언어에서는 프로그램에서 사용하지  않은 명

령어라도 모두 포함되어 있지만 C 언어는 필요없는  명령을  포함시켜 프로그

램의 길이를  길게 하고 실행속도를  떨어뜨리는 일을 피하도록  설계되어 있

다.

(2) main()

C 프로그램은  반드시 하나의 main()이라는  함수명이 존재해야   한

다. 만일 이  이름 이외의 함수명이 존재하면 그것은 부  (sub) 프로그램으로

간주된다. main 이라는 이름 뒤에 괄호가 있는 것은 main 이 함수명임을 나

타내는 것이다. 함수란  여러가지 일을  한번에 모아서 하는  일을 뜻하며 일

종의 명령집합이라 할  수 있다.  함수는 여러개의 명령으로   모아져 있지만

또한 좀 더 큰 단위의 하나의 명령이라고도 할 수 있다.

(3) {

왼쪽 중괄호 { 는 함수의 본체의 시작임을 뜻한다.

(4) int age, day;

나이값(age)과 날수값(day)을  저장할 변수를 선언하는 것이다.   변

수는 미리 지정해 주어야만 사용할 수 있다.    int 는 age 와 day 변수가 정

수형임을 나타낸다.

(5) age = 25;

(6) day = age * 365;

치환문으로서 age 에 1을, day 에  age*365 라는 계산식을 각각 치환

하는 문장이다.

(7) /* 나이에 ................. */

주석문은 원시 프로그램을 독해하기 쉽도록  달아주는 것으로 주석문

의 표시가 있으면 컴파일러가 컴파일할 때 이  문장은 읽어들이지 않는다. 주

석문을 시작하는 기호는 /* 이고, 주석문의 끝을 나타내는 기호는 */ 이다.

(8) printf("내 나이는 %d살이고 살아온 날수는 %d일이다.",age, day);

다른 언어의 print 라는 명령과 비슷하기  때문에 짐작할 수 있을 것

이다. 이 문장은  %d 라는 곳에 age값과 day값을 치환한  후 표준입출력 장치

에 출력시켜 주는  것이다. printf() 역시 함수이므로 이  문장은 함수호출문

이라 한다.

(9) }

프로그램의, 좀 더  구체적으로 말하면 main() 함수 본체의  끝을 나

타내는 표시이다.

제 2 장   데이타형

데이타형에는  int,   unsigned int,   short,    unsigned short,  long,

unsigned long,  char,  unsigned char,  float,  double 등이 있다.

1. 데이타형의 크기

각 데이타형의 표시가능한 숫자의 범위는 다음과 같다.

(1) int (PC 기종에서)

0    1                                                15

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

|부호|                                                 |

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

최대값  0111111111111111  (215 - 1, 32767)

최소값  1000000000000000  (-215,   -32768)

(2) unsigned int (PC 기종에서)

0                                                     15

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

|                                                      |

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

최대값  1111111111111111  (216 - 1, 65535)

최소값  0000000000000000  (0,           0)

(3) short

0    1                                                15

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

|부호|                                                 |

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

최대값  0111111111111111  (215 - 1, 32767)

최소값  1000000000000000  (-215,   -32768)

(4) unsigned short

0                                                     15

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

|                                                       |

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

최대값  1111111111111111  (216 - 1, 65535)

최소값  0000000000000000  (0,           0)

(5) long

0    1                                                31

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

|부호|                                                 |

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

최대값 01111111111111111111111111111111 (231 - 1, 2147483647)

최소값 10000000000000000000000000000000 (-231,   -2147483648)

(6) unsigned long

0                                                     31

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

|                                                      |

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

최대값 11111111111111111111111111111111 (231 - 1, 4294967295)

최소값 00000000000000000000000000000000 (0,                0)

(7) char

0    1                                                 7

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

|부호|                                                 |

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

최대값  01111111  (27 - 1, 127)

최소값  10000000  (-27,   -128)

(8) unsigned char

0                                                      7

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

|                                                      |

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

최대값  11111111  (27 - 1, 255)

최소값  00000000  (0,        0)

(9) float

0          6  7  8                                    31

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

|  지수부  |부 호|       가         수        부       |

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

(10) double

0          6  7  8                                    63

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

|  지수부  |부 호|       가         수        부       |

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

정   수   형 : int, unsigned int, short, unsigned short,

long, unsigned long, char (문자형)

부동소숫점형 : float, double

부동소숫점형에서의 지수의 범위는 IBM PC에서

-307 부터 308 까지이다.

2. 데이타형보다 큰 수

main()

{

char ch = 127, ch1, ch2;

ch1 = ch + 1;

ch2 = ch + 2;

printf("ch = %d, ch1 = %d, ch2 = ch2",ch,ch1,ch2);

}

데이타형보다 큰  수를 표기하면 어떻게  되는지 알아볼 수  있는 예이

다. char 이라는 데이타형이 표시할 수 있는 수의 최대 크기는 127이다. ch

는 최대수로 초기화되었다. ch1  과 ch2 는 여기에 1과 2를 더해서   그 결과

를 알아보자는 것이다. 그 결과는 다음과 같다.

ch = 127, ch1 = -128, ch = -127

즉 최대값에서 더 증가를 하면 시작하는  값에서부터 다시 시작하게 된

다. char 의 표시범위는 -128 부터 127  이므로 시작하는 수인  -128 부터 시

작하는 것을 볼 수 있다.

예제)  일을 한 시간과 시간당 임금을 입력받아 총액을 계산하고

또한 그 중에서 세금을 공제한 임금을 계산하는 프로그램

을 작성하라. (세율은 총액의 0.15)

<해>

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

|                                                              |

| /* realpay.c */                                              |

|                                                              |

|  #include <stdio.h>                                          |

|                                                              |

|  main()                                                      |

|  {                                                           |

|      float hour, pay_per_hour, total, pay;                   |

|                                                              |

|      printf("일을 한 시간을 입력하시요 : ");                 |

|      scanf("%f", &hour);                                     |

|      printf("시간당 임금을 입력하시요 : ");                  |

|      scanf("%f", &pay_per_hour);                             |

|                                                              |

|      total = hour * pay_per_hour;                            |

|      pay = total - total * 0.15;                             |

|                                                              |

|      printf("%5.1f시간 일하고 시간당 임금 %7.1f원을 받으\    |

|  면 \n", hour, pay_per_hour);                                |

|      printf("총액은 %10.2f원이고, 세금을 빼면 실제로 받는 \  |

|  임금은 %10.2f원이다. \n", total, pay);                      |

|      getch();                                                |

|  }                                                           |

|                                                              |

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

제 3 장   변수와 상수

1. 변수

C 언어를 공부하는 사람이 변수가  무엇인지 모르지는 않겠지만 간단히

설명하면 변수란 기호번지를 뜻하는 것으로 숫자나  문자가 담길 그릇을 말한

다고 할 수  있겠다. 따라서 변수는 프로그램이 실행되는 동안  어떤 값을 지

니게 되고 그 값이 변할 수도 있는 것이다.

(1) 변수 명칭의 원칙

변수는 영문자의 대문자와 소문자,  밑줄기호 및 숫자로 이루어

질수 있으나 첫글자로 숫자를 사용할 수는 없다.

변수명칭의  알파벳이 같더라도  대문자와 소문자로 서로  다른

한 문자라도 있으면 다른 기억장소를 의미한다.

변수명칭의 길이에는 제한이 없다.

변수는 처리 전에 반드시 미리 선언되어야 한다.

변수의 명칭은  원시 프로그램 판독의 편이를  위하여 의미있는

이름을 선택하는 것이 좋다.

변수 선언시에도 옆에 커멘트를 달아주는 것이 좋다.

예약어(KEY WORD)는 변수명칭으로 사용할 수 없다.

(2) 변수 선언의 장점

변수를 한 자리에 모아둠으로 프로그램 이해에 좋다.

변수를  미리 계획하게  함으로 계획성있는 프로그램을  작성할

수 있다.

필요한  만큼만 미리 선언을  하게 됨으로 기억장소를  줄일 수

있고, 따라서 프로그램의 길이가 짧아지고, 실행속도가 빨라진다.

변수명칭의 철자가 틀림으로 발생하는  RUN TIME ERROR 를 막을

수 있다. 즉 프로그램 수정이 용이하다.

2. 상수

상수란 프로그램 내에서 변하지 않는 값,  즉 문자나 숫자로 된 데이타

를 말한다. 상수는  데이타형에 따라 정수, 부동소숫점수, 문자  등으로 구분

할 수 있다.

(1) 문자상수

특별히 문자상수에 대해서 알아보자. C  언어에서 문자는 단일 인용

부호(')로 나타낸다. 예를  들면 아래와  같다. 문자상수에서  인용부호를 뺀

다면 컴파일러는 이를  변수로 취급할 것이다. 문자변수 또는  문자상수는 하

나의 문자만을 값으로 가질  수 있다.  문자 역시 ASCII  코드에 의한 숫자로

표시될 수 있다. C 언어는 기본적으로 문자가  없고 문자도 숫자인 것으로 생

각하는 것이 좋다.

(2) 특수기호에 의한 문자 표시방법 (ESC 문자열)

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

|  문자 |   의 미           |   아스키 코드값   |

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

|  '\n' |  newline          |      13 + 10      |

|  '\t' |  tab              |         9         |

|  '\b' |  backspace        |         8         |

|  '\r' |  carriage return  |        13         |

|  '\f' |  form feed        |        12         |

|  '\\' |  backslash        |        92         |

|  '\'' |  single quote     |        39         |

|  '\"' |  double quote     |        34         |

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

(3) 진수에 따른 상수 표시방법

long 형 데이타는 뒤에 L 자를 붙인다. ("%ld")

8진수 데이타는 앞에 0(zero) 을 붙인다. ("%o")

16진수 데이타는 앞에 0X(zero 엑스) 를 붙인다. ("%X", "%x")

(%X 와 %x 의 차이는 A-F의 문자를 대문자 혹은 소문자로

출력한다.)

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

| 데이타형   |   10진수   |   8 진수   |   16진수  |

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

|    char    |    \32     |    \040    |    \0x20  |

|    int     |     32     |    040     |    0x20   |

|    long    |     32L    |    040L    |    0x20L  |

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

(4) 변환문자의 기능

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

|변환문자|          출     력        내     용             |

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

|   %d   | 인수를 10진수로 변환하여 출력한다.              |

|        | %ld 는 long형 10진수를 표기할 때 사용한다.      |

|   %o   | 인수를  8진수로 변환하여 출력한다.              |

|   %x   | 인수를 16진수로 변환하여 출력한다.              |

|        | %X 는 a-f의 문자를 대문자로 출력한다.           |

|   %u   | 인수를 부호없는 10진수로 변환하여 출력한다.     |

|        | 메모리 주소를 표기할 때도 사용한다.             |

|   %c   | 인수를 한 문자로 출력한다.                      |

|   %s   | 문자열을 출력한다.                              |

|   %f   | float 나 double 형 10진수로 변환하여 출력한다.  |

|        | 길이가 없으면 소숫점 이하 6자리까지 출력한다.   |

|   %e   | 지수형으로 출력한다.                            |

|   %%   | '%' 문자를 출력한다.                            |

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

(5) 한글문자코드

한글코드에는 여러가지가 있으나  그 중 대표되는 것은   KSSM 조합

형과  KS-5601 완성형  (국가 행정망 표준 코드) 으로 크게  구분된다.  KSSM

조합형은 KS-5601 완성형에 비해 많은 문자  코드를 가지고 있고, KS-5601 완

성형은 국제 규약에 맞는다는 장점들을 서로 가지고 있다.

0     31       127          255(0xFF)

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

31 --+--+---------+-------------+--

|  |   (1)   |     (3)     |

|  |         |             |

127 +--+---------+-------------+

|  |         |             |

|  |   (2)   |     (4)     |

|  |         |             |

255 +--+---------+-------------+ 0xFF

아스키코드의 4상한

한글 코드는 2바이트로 한 문자코드를  생성하게 되는데 KS-5601 완

성형은 완성된  코드값을 가지고 있고  조합형은 아래 그림과  같은 방식으로

코드를 생성하게 되어  있다. 영문 아스키 코드가 이미 127까지의  값을 가지

고 있으므로 한글코드는 최소한 2바이트 중  1바이트는 127이 넘는 값을 가져

야 한다. 이를 위의 그림 4상한을 가지고  생각해보면 (1) 부분이 영문자 아스

키 코드가 있는  부분이고 이 중에서도 31까지는 통신용 제어문자로  되어 있

다. 그러므로 (2),(3),(4) 부분 중 한 부분을  영어를 사용하는 국가에서 선택하

도록 국제규약이 되어  있는데 KS-5601 완성형은 ㉣ 부분을,   KSSM 조합형은

(3) 과 (4) 부분을 사용하고 있다.

KSSM 조합형 코드 형성 방법

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

|0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|

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

비트  0    : 부호 (1이면 한글)   비트  1-5  : 초성코드

비트  6-10 : 중성코드            비트 11-15 : 종성코드

예제)  문자열, 정수, long형 정수, 부동소숫점수 등을 길이를

지정하여 출력하여 보라.

<해>

/* outtype.c */

#include <stdio.h>

main()

{

int small     = 2345;

long big      = 12345678;

float point   = 100.25;

char name[20] = "JUNG ANG COMPUTER";

printf("         1         2         3");

printf("123456789012345678901234567890");

printf("%20d \n", small);

printf("%-20d \n", small);

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

printf("ld \n", big);

printf("%f \n", point);

printf("%20.3f \n", point);

printf("%-20.4s \n", name);

printf("%20s \n", name);

}

제 4 장   연산자

C 언어에는 다른  언어에서 볼 수 없었던 많은 연산자를  가지고 있다. 연

산자를 많이 가지고  있다는 것이 어쩌면 공부하는 이들에게 더욱  골치 아픈

요소가 될 수 있을  수 있으나 그만큼 막강한 기능을 발휘할  수 있다는 좋은

장점을 제공한다.

1. 연산자의 종류와 우선순위

다음 페이지에 있는  표와 같은 연산자들이 있고 우선 순위가   정해져

있다. 각 장의  내용에 따르는 연산자를 이해해야 하므로 이  장에서  연산자

들을 다 다룰 수는 없으나 우선순위 문제로 도표화 한 것이다.

2. 기본 연산자

= (치환연산자)  : 치환연산자로서 우변의 변수, 상수  및 계산식이

좌변 변수에 대입된다. 좌변에는 절대로 상수가 올 수가 없다.

+ (덧셈연산자) : 이 연산자를 중심으로  좌우에 있는 두 수를 더하

는 데 사용된다.

- (뺄셈연산자) : 이 연산자의 좌측에  있는 수에서 우측에 있는 수

를 빼는 데 사용된다.

* (곱셈연산자) : 이 연산자를 중심으로  좌우에 있는 두 수를 곱하

는 데 사용된다.

/ (나눗셈연산자) : 이 연산자의 좌측에  있는 수를 우측에 있는 수

로 나누는 데 사용된다.

- (부호연산자) : 계산식이 아닌 상수  앞에 단독으로 이 기호가 붙

으면 뺄셈 연산자가  아니라 부호연산자로서 그 값의 부호를 바꾸는  데 사용

된다. 예컨대 양수를 음수로, 음수를 양수로 변환시킨다.

C 언어의 연산자 중에 제곱을  나타내는 연산자는 존재하지 않는다.

이것은 함수로 만들어 사용하는 수 밖에 없다.

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

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

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

| 일  차  식 | 프라이머리  | ( )  [ ]  ->  .        | 우측 |

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

|            |             | !  ~  ++  --  -  *  &  |      |

| 단항연산자 | 단      항  +------------------------+ 좌측 | ^

|            |             | (데이타형)  sizeof     |      | |

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

|            | 승      제  | *  /  %                | 우측 | |

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

|            | 가      감  | +  -                   | 우측 | |

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

|            | 쉬  프  트  | <<  >>                 | 우측 | |우

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

|            | 비      교  | <  <=  >  >=           | 우측 | |

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

|            | 동등(등가)  | ==  !=                 | 우측 | |

| 이항연산자 +-------------+------------------------+------+ |선

|            | 비트   AND  | &                      | 우측 | |

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

|            | 비트   XOR  | ^                      | 우측 | |

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

|            | 비트   O R  | |                      | 우측 | |순

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

|            | 논리   AND  | &&                     | 우측 | |

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

|            | 논리   O R  | ||                     | 우측 | |

+------------+-------------+------------------------+------+ |위

| 삼항연산자 | 조      건  | ? :                    | 좌측 | |

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

| 치환(대입) |             | =  +=  -=  *=  /=  %=  |      | |

|            | 치      환  +------------------------+ 좌측 | |

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

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

| 순서연산자 | 콤      마  | ,                      | 우측 | v

+------------+-------------+------------------------+------+낮다

<--------------------- 같은 우선순위 ------------------>

3. 편리한 연산자

% (나머지 연산자)  : 이 연산자의 좌측 수를 우측  수로 나눈 나머

지 값을 계산하는데  사용된다. (예, 화폐단위별 계산,  주민등록번호 마지막

자리수 계산, 시분초 계산 등)

++ (증가 연산자) : 증가시킬  변수의 앞이나 뒤에 붙임으로 피연산

자를 1 증가시킨다. 앞에 붙는 것을  전위형(PREFIX), 뒤에 붙는 것을 후위형

(POSTFIX) 이라고 하는데 붙는 위치에 따라서  계산식의 순서가 틀려진다. 앞

에 붙는  경우 관련된 식을 먼저  계산하기 전에 자신의 값부터  증가를 시키

며, 뒤에 붙는 경우 관련된 식을 먼저  계산한 후 자신의 값을 증가시키게 된

다.

-- (감소 연산자) : 증가시킬  변수의 앞이나 뒤에 붙임으로 피연산

자를 1 감소시킨다. 전위형과 후위형에 따른 역할은 증가연산자와 같다.

, (콤마  연산자) : 순차연산자라고 부르는데 콤마(,)로  분리된 식

을 왼쪽부터 평가하여 오른쪽 식의 결과값이 되도록 한다.

c = (a = 3, a + 5);

위의 식을 계산하면 a 값은 3 그대로  있지만 c 값은 콤마 앞뒤식을

계산한 후 8 값을 갖게 된다.

(int), (unsigned int), (short), (unsigned short), (long),

(unsigned long), (char), (unsigned char), (float), (double)

(캐스트 연산자) :  데이타형이 서로 다른 변수값을  치환하게 되는

경우 정확성을 기하기 위하여 캐스트 연산자를 아래와 같이 사용하게 된다.

int result;

float a = 15.5, b = 25.7;

result = (int) a + (int) b;

위의 프로그램에서 a 와 b 는  float 형으로 선언되고 초기화되었으

나 (int) 라는  캐스트 연산자를 사용하였으므로 정수형 상수로  변환하여 계

산에 참여한다. 그러므로 결과값은 15 와 25 를 합한 40 을 갖게 된다.

/*  binary.c */

/*  이 프로그램은 10진 정수를 2진수로 바꾸는 프로그램이다.

C 언어 자체에서 2진수로 바꾸어주는 format 은 없으므로 이 예제를

사용하면 유용하다.  */

#include <stdio.h>

main()

{

int num, i, mod, mok;

char bin[17];

printf("INPUT DECIMAL NUMBER (0 - 32767) : ");

scanf("%d", &num);

mok = num;

for(i = 0; i < 16; i++) {

mod = mok % 2;

mok /= 2;

bin[15-i] = mod;

}

printf("Decimal = %d\n", num);

printf("Hexa    = %X\n", num);

printf("Octal   = %o\n", num);

printf("Binary  = ");

for(i = 0; i < 16; i++) {

printf("%d", bin[i]);

if((i % 4) == 3) printf(" ");

}

printf("\n");

getch();

}

/*******************************************

*   Identity card number check program.   *

*     idnumchk.c     by Samyull Hong      *

*******************************************/

#include <stdlib.h>

#include <stdio.h>

#include <mem.h>

main()

{

printf("\nJUNG ANG Bulletin Board System  (032) 763-7333 \n");

input();

}

input()

{

int ret;

char st[15],st1[10];

printf("\n주민등록번호 (예 920101-1234567)  :  ");

scanf("%s",st);

if(!strcmp(strupr(st),"Q")) exit(0);

memcpy(st1,st+7,7);

ret = idnum_check(st,st1);

if(ret) {

printf("\n주민등록번호가 틀립니다. 다시 입력하세요!!!   끝내시려면 q

요.\n");

printf("주민등록번호 끝자리는 %d 이어야 합니다.\n",ret);

input();

}

else       printf("\n맞습니다. 감사합니다 !!!\n");

getch();

}

idnum_check(char *no, char *no1)

{

int i, tot = 0, mod = 0, mon, day, num[12];

char n[] = { 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5 };

mon = (no[2]-48)*10 + (no[3]-48);

day = (no[4]-48)*10 + (no[5]-48);

if((mon > 12 || mon < 1 || day < 1 || day > 31)  ||

((mon == 2 || mon == 4 || mon == 6 || mon == 9 || mon == 11)

&& (day > 30) )  ||

(no1[0] < '1' || no1[0] > '2'))     return 0;

for(i = 0; i < 12; i++) {

if(i < 6)   num[i] = no[i]-48;

else        num[i] = no1[i-6]-48;

tot += num[i] * n[i];

}

mod = 11 - (tot % 11);

if( mod == 10 )            mod = 0;

if( mod == (no1[6]-48) )  return(0);

else                      return(mod);

}

/*  0   1   2   3   4   5   -   6   7   8   9  10  11  12

2   3   4   5   6   7       8   9   2   3   4   5

*   *   *   *   *   *       *   *   *   *   *   *

5   6   0   5   0   5   -   1   1   4   3   2   8   6  <------+

|

10 +18 + 0 +25 + 0 +35   +   8 + 9 + 8 + 9 + 8 +40   =  170    |

170 % 11 = 15 ... 5      11 - 5 = 6 ---------------------------+    */

/*  money.c  */

/*  이 예제는 일정액을 만원권, 5천원권, 천원권, 5백원권, 백원권,

5십원권, 십원권, 5원권, 1원권의 9가지 화폐단위로 갯수(장수)를 최소

화할 때의 계산방법이다.  */

#include <stdio.h>

main()

{

int money[9] = { 10000, 5000, 1000, 500, 100, 50, 10, 5, 1 };

int i, ea[9];

long mod;

printf("WHOLE MONEY : ");

scanf("%ld", &mod);

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

ea[i] = (int)(mod / money[i]);

mod  %= money[i];

}

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

printf("%5d : %3d \n", money[i], ea[i]);

getch();

}

/*  앞의 세 페이지에 걸친 두개의 예제와 함께 '%' (나머지) 연산자를 위

한 예제다.  */

4. 비트 및 쉬프트 연산자

C 언어는  고급언어이면서도 시스템에 가까이  갈 수  있는 언어이므로

비트 연산자나 쉬프트  연산자는 매우 중요한 역할을 한다.  시스템은 비트연

산을 통해 세미한 조작을 할 수 있기 때문이다.

& (비트  AND 연산자) : 산술 연산자와는 달리  비트별 조작을 하는

데 비트별로 계산할 때 두 수가 다  1이어야만 결과가 1이 되는 연산자다. 그

림으로 그리면 다음과 같다.

+--------------------------+     +----/  ----/   ---+

|  +------------+          |     |     A      B     |

|  |   A   ++++++-------+  |     +                  |= F

|  +-------++++++   B   |  |    | |                 |

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

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

| (비트 O  R 연산자) : 비트별로 계산할 때 두 수  중에 하나 이상

1이면 결과가 1이 되는 연산자다. 그림으로 그리면 다음과 같다.

+---/  ---+

+--------------------------+     +----+    A    +---+

|  ++++++++++++++          |     |    +---/  ---+   |

|  ||| A ||++++++++++++++  |     +         B        |= F

|  ++++++++++++++|| B |||  |    | |                 |

|          ++++++++++++++  |     +                  |

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

^ (비트 XOR  연산자) : 비트별로 계산할 때 두 수가  서로 다른 수

이어야 1이 되는 비트별 EXCLUSIVE (배타적)  OR 연산자다. 이 연산자는 스위

치 기능, 데이타 상호교환, 데이타 CLEAR시 주로 사용한다.

~ (1의  보수 연산자) : 상수나 변수 앞에  단독으로 붙는 단항연산

자로서 뒤의 수의 1의 보수를 취하는 연산자다.

<<, >>  (쉬프트 연산자) : 왼쪽 쉬프트와  오른쪽 쉬프트가 있는데

비트별로 밀어내는 연산자다. 예를 들면 다음과 같다.

'A' << 2  일때  'A'는 65이므로 2진수로 01000001 이다.

그러므로 2비트를 좌측으로 밀면 000001 이 되고 남은 2비트는

0 으로 채워져 결과는 00000100 이 된다. 우측으로 쉬프트시키

면 부호가 있는 데이타형일 경우 부호비트는 그대로 남아있다.

다음 예제를 통해 쉬프트 연산자의 성격을 알아보자.

int ch = 0x507F;

char ch1, ch2;

ch2 = ch;

ch1 = ch >> 8;

위의 예제는 ch 의 값중 0x50 은 ch1 에, 0x7F 는 ch2 에 넣는 과

정이다.

/* shift 연산자에 있어서의 부호비트에 대한 예제 */

#include <stdio.h>                        #include <stdio.h>

main()                                    main()

{                                         {

int a = -32768, b;                        unsigned int a=32768, b;

int i;                                    int i;

for(i = 0; i < 16; i++) {                 for(i = 0; i < 16; i++) {

b = a >> i;                               b = a >> i;

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

}                                         }

getch();                                  getch();

}                                         }

위 프로그램의 결과는 다음과 같다.

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

|                                                             |

|    -32768                                    32768         |

|    -16384                                    16384         |

|    -8192                                     8192          |

|    -4096                                     4096          |

|    -2048                                     2048          |

|    -1024                                     1024          |

|    -512                                      512           |

|    -256                                      256           |

|    -128                                      128           |

|    -64                                       64            |

|    -32                                       32            |

|    -16                                       16            |

|    -8                                        8             |

|    -4                                        4             |

|    -2                                        2             |

|    -1                                        1             |

|                                                             |

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

위 예제에 의하면  int 형에 있어서는 부호는 전혀 달라지지  않고 나머지

비트만 shift 되었음을 알  수 있다.  그러나  unsigned  int 형은 MSB (Most

Significant Bit, 최상위  비트)가 부호를 나타내는 것이  아니므로 MSB를 포

함한 모든 비트가 그대로 shift 가 이루어졌음을 알 수 있다.

최상위  비트가 MSB인데 반해  최하위 비트는 LSB  (Least Significant

Bit) 라고 한다.

5. 그 밖의 치환 연산자

= (치환 연산자) 외의 몇가지의 치환(대입)  연산자가 또 있는데 그 역

할은 다음과 같다.

+=  : 이 연산자의 좌변의  값에 우변의 변수나 상수,  계산식 결과

등을 더하여 그 값을 다시 좌변의 변수에 넣는 연산자다.

-= : 이 연산자의 좌변의 값에서  우변의 변수나 상수, 계산식 결과

등을 빼서 그 값을 다시 좌변의 변수에 넣는 연산자다.

*=  : 이 연산자의 좌변의  값에 우변의 변수나 상수,  계산식 결과

등을 곱해서 그 값을 다시 좌변의 변수에 넣는 연산자다.

/= : 이 연산자의 좌변의 값에서  우변의 변수나 상수, 계산식 결과

등으로 나누어 그 몫을 다시 좌변의 변수에 넣는 연산자다.

%= : 이 연산자의 좌변의 값에서  우변의 변수나 상수, 계산식 결과

등으로 나누어 그 나머지를 다시 좌변의 변수에 넣는 연산자다.

&=  : 이 연산자의 좌변의  값에 우변의 변수나 상수,  계산식 결과

등으로 비트 AND 연산하여 그 값을 다시 좌변의 변수에 넣는 연산자다.

|=  : 이 연산자의 좌변의  값에 우변의 변수나 상수,  계산식 결과

등으로 비트 OR 연산하여 그 값을 다시 좌변의 변수에 넣는 연산자다.

^=  : 이 연산자의 좌변의  값에 우변의 변수나 상수,  계산식 결과

등으로 비트 XOR 연산하여 그 값을 다시 좌변의 변수에 넣는 연산자다.

치환 연산자의 기능을 예제를 통해 알아보자.

int result, num1 = 10, num2 = 20;

result += num2 - num1;

위의 식중 아래줄의 식을 풀어쓰면 다음과 같다.

result = result + (num2 - num1);

6. 관계(논리) 연산자

이 세상에는 항상  참과 거짓이 존재하기 마련이다. 참과  거짓에 관해

깊이 사고하는 학문이 철학이며 이 철학 중  논리학이라는 분야가 있다. 참과

거짓을 구분짓는 것은  논리이다. 그리고 참과 거짓은 어떠한  관계성이 없이

는 이루어질 수 없다. 그러므로 참과 거짓을  위한 연산자를 관계연산자 혹은

논리연산자라  부른다. 이러한  관계연산자에는 여러가지  조건이 필요할  때

AND, OR, NOT  이라는 연산자를 통해 결합된다.  우선순위가  높은 순으로 기

술하면 아래와 같다.

! (NOT)  : 부정의 의미를 지닌 관계 연산자로서  변수 앞에 붙이면

그 값이 참(0이  아닌 숫자)일 때 거짓(0) 을 만들고  거짓(0)일 때는 무조건

1을 만든다.  관계식의 조건에 있어서는 반대의 의미를 지닌다.

&& (AND)  : 이 연산자 앞뒤의  두 가지 조건이 둘 다  만족할 때만

참인 연산자이다.

|| (OR) : 이 연산자 앞뒤의  두 가지 조건중 하나 이상이 만족하면

참인 연산자이다.

7. 등가(동등) 연산자

등가연산자는 관계 연산자의 일종이나 엄밀히  구분하면 '같으냐 ?' 혹

은 '같지 않느냐 ?' 를 따지는 연산자를  말함으로 관계연산자와 구별하여 등

가 연산자 혹은 동등 연산자라고 한다.

==  : 이 연산자의 좌변과  우변의 값이나 계산식이  같으냐를 묻는

연산자이다. = 기호  2개를 붙여 쓴다. = 기호 하나만  사용하면 치환 연산자

가 되므로 유의해야 한다.

!= : 이 연산자의 좌변과 우변의  값이나 계산식이 같지 않느냐 (다

르냐) 를 묻는 연산자이다.

8. 순서(조건) 연산자

항이 셋이 필요하다고  하여 삼항 연산자라고도 하는데  조건문을 간편

하게 사용할 수 있고 함수의 인자로도 사용할 수 있는 편리한 점이 있다.

int a = 0, b;

if(a == 0)  b = 0;

else        b = 1;

위와 같은 식을 순서 연산자를 사용하면 다음과 같이 줄일 수 있다.

b = (a == 0) ? 0 : 1 ;

즉, 조건문 뒤에  '?' 를 붙이고, 조건에 따라 좌변  변수에 치환될 참

일 때의 값을 다음에, 그리고 그 다음에는  ':'를, 그 뒤에는 거짓일 때의 치

환될 값을 쓰게 되어 있다.

이 조건 연산자는 키워드가 아니고 연산자이기  때문에 아래와 같이 함

수 안에 인자로 사용될 수도 있다는 점에서 편리하다.

printf("%d", (x > 0 ? 1 : 0));

제 5 장   제어문

1. 참이냐 ?  거짓이냐 ?

인생은 태어나면서부터 무수한 선택에 의해  살아간다. "이 상황에서는

울어야 할  것이냐, 웃어야 할 것이냐  ?" 또는 식당에 가서  "짜장면을 먹을

것이냐, 갈비탕을 먹을 것이냐 ?" 하는 등의  작은 선택으로부터 시작해서 직

업 선택이나 배우자 선택  등 크고 작은 많은 선택을 하지  않으면 인생을 살

아갈 수가 없는 것이다. {선택} 이라는 것은  모든 논리의 핵심이고 프로그램

의 핵심이기도 하다.

논리학이라는 학문이 있는  데 이것은 수학과도 관련이  있고 철학과도

관련이 있는 학문이다.  즉 수학과 철학은 먼 관계가 아니라는  점이다. 우리

는 흔히 이런 논리를 말하면서 궤변이라고 한다.

"원숭이는 펄쩍펄쩍 두 다리로 뛰어다닌다.

사람도 두 다리로 펄쩍펄쩍 뛰어다닌다.

그러므로 원숭이는 사람이다."

이 세상에 있는  진리 가운데는 이러한 궤변적인 진리가  많다. 그러다

보니 요즘 가치관을 세운다는 말은 상당히 힘들게  느껴지게 되고 그래서 "가

치관의 혼란시대"라고 쉽게  규정지어 버리고 만다. 그러나  진리(참)란 분명

이 존재한다. 다만  진리에 있어서 당파성만이 있을 뿐이다. 당파성이란   예

컨대 "배가 고프다"  라는 말은 배부른 사람에게는 진리가 아니고  배고픈 사

람에게만 진리가 된다는 말이다.

하지만 프로그램 속에서의  참이란 그리 어려운 것이  아니다. C언어는

C++언어 등과는 달리 OOPL (Object  Oriented Programming Language) 이 아니

고 POPL (Procedure Orienter Programming  Languane) 이기 때문에 간단한 비

교판단에 의해서 결정할  수 있기 때문이다. 즉 맞으면 참(1  등의 유효숫자)

이고, 틀리면 거짓(0)이다. 다음의 예를 살펴보면 간단하다.

int true, false;

true  = (15 < 30);

false = (15 > 30);

true 에는 1이 기억되고, false 에는 0이 기억된다.

그러면  !!(-3) 의 값은 얼마가 되는가 생각해 보라.

2. REDIRECTION

본래 UNIX 에서만 가능하던 것들이 있는  데 하나는 계층적 디렉토리이

고, 또 하나는 REDIRECTION 기능이다.  계층적 디렉토리는 서로간의 데이타를

보호하는 의미에서  있던 것이지만  퍼스널 컴퓨터  상에서도 기억용량이  큰

FIXED DISK를 사용하게 되면서 구분을 쉽게 하기 위해 사용되었다.

REDIRECTION 역시 UNIX에서만 사용되던  것으로 오래전부터 DOS 에서도

사용할 수 있게 되었다. REDIRECTION 이란 글자  그대로 STREAM 의 방향을 도

스상에서 임시로 돌려주는  명령이다. 도스 2.0 이상에서  기본적으로 지원하

는 디바이스 드라이버 가운데는 다음과 같은 것들이 있다.

CON

AUX

PRN

NUL

LPT1

LPT2

LPT3

COM1

COM2

COM3  ---+-- 이것은 보통 AT 급 이상에서만 지원한다.

COM4  ---+

이외의 이름이 지정되면 그것은 디바이스  드라이버가 아니라 디스크의

화일이름이 된다.  예를 들어 출력문으로  printf() 함수만  사용한 경우라면

화면으로 출력될 것이나 아래와 같이 명령을  내리면 출력될 스트림의 방향이

바뀌게 된다.

C:\> TYPE  A.TXT  >  PRN

위의 예로 보면 TYPE 이라는 명령은  도스의 내부명령으로서 문서의 내

용을 화면에 출력시키라는 것인데 리다이렉션인  '>' 표시가 있으므로 다음에

지시한 프린터로 스트림을  바꾸라는 뜻이 되므로 A.TXT 라는  문서는 프린터

에 인쇄된다. '>' 기호를 REDIRECTION 이라  한다. 화일처리를 직접하지 않는

경우 유용한 처리방법이다.

3. 시스템 입출력

많은 컴퓨터들이  INTEL사의   8088,  8086,  80286,   80386,  80386,

80486,  80586....  등의 마이크로프로세서를 사용하고 있다.  그러나 컴퓨터

는 CPU에 의해서만  움직여지는 것이 아니라 키보드, 모니터,  디스크 드라이

버, 마우스, 타이머,  스피커 등의 장치를 가지고 있다. 그러므로  이들 장치

와 CPU와  뭔가 데이타나 명령을 주고  받아야만 동작이 가능하게  되는 것이

다. 예를 들어  스피커가 소리를 내게 하려면 8255칲을 이용하게  된다. 8255

칲은 Programmable Parallel Interface Controller 라고 하는데 이 칲에 의해

스피커가 동작을 하게  된다. 이 칲과 CPU가 연결이 되어야만  동작이 가능하

게 되는데  CPU는 이런  외부 주변장치와 연결하는  PORT를 갖게  된다. 이를

I/O PORT라  하는데 스피커 제어를 위해서는  61h 포트를 이용하게 된다. 61h

포트 가운데서도 0비트와 1비트가 1로 set되면 소리를 내게 되는  것이

다. 주변장치를 동작시키는 칲으로는 다음과 같은 것들이 있다.

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

|        |   | 캐 |   |          I/O+-+   |    +--모니터

|   메   +---+ 쉬 +---+          포 +-+---+ 컨 +--키보드

|        +---+ 메 +---+          트 +-+---+    +--클럭

|        |   | 모 |   |             +-+   | 트 +--타이머

|   모   |   | 리 |   |  C   P   U    |   |    +--스피커

|        |   +----+   |               |   | 롤 +--디스크

|        |            +---------------+   |    +--마우스

|   리   |                                | 러 |

|        |                                |    |

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

<시스템에 따른 칲 번호>

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

|  장 치    |  칲   | 장 치    |  칲   |

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

|  timer    | 8253  | 모니터   | 6845  |

|  clock    | 8284  | 통신용   | 8250  |

|  디스크   | 8237  | 인터럽트 | 8259  |

|  키보드   | 8042  |          |       |

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

예제) 스피커에서 약 5초동안 소리가 나게 하는 프로그램을 두 가지

방법으로 연속해서 작성하고 그 둘을 서로 비교해 들어보시요.

<해>

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

|                                                   |

|  /* beep.c    MADE BY HONG SAMYULL */             |

|  #include <dos.h>                                 |

|                                                   |

|  main()                                           |

|  {                                                |

|      int ret, i;                                  |

|                                                   |

|      ret = inport(0x61);                          |

|      outport(0x61, ret | 3);                      |

|      sleep(5)         /* 또는 delay(5000); */     |

|      outport(0x61, ret);                          |

|      getch();                                     |

|      for(i = 0; i < 5; i++)                       |

|          putchar('\07');                          |

|      getch();                                     |

|  }                                                |

|                                                   |

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

4. if - else 문

프로그램 중에서 조건에 따라 선택하여 수행하게  해야 하는 경우 가장

쉽고 가장 많이 사용되는 제어문이다. 그 형식은 다음과 같다.

if (조건식)

statement1;

else

statement2;

위의 프로그램  중에서 만일  조건식이 만족하여 참이면  statement1을

수행하고 거짓이면  statement2를 수행하는 것이다. 예제  프로그램으로 다음

의 텍스트 암호화 프로그램을 작성한 것을 보자.

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

|      #include <stdio.h>                             |

|      main()                                         |

|      {                                              |

|           char ch;                                  |

|           while((ch = getchar()) != EOF) {          |

|              if(ch == '\n')                         |

|                  putchar(ch);                       |

|              else                                   |

|                  putchar(ch + 4);                   |

|           }                                         |

|      }                                              |

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

복합 if 문에는 어떠한 것들이 있는가 알아보자.

예제) 어린이 대공원  입장료가 아래와 같다. 연령을  입력받아 입장요

금이 얼마인가를  계산해주는 프로그램을 작성하라. 아울러  순서도도 작성해

보라.

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

|    6세 이하   영 유 아  /  무  료   |

|    7세 - 12세 국민학생  /  1000원   |

|   13세 - 18세 중·고생  /  1500원   |

|   19세 - 60세 성    인  /  2000원   |

|   61세 이상   노    인  /  무  료   |

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

<해>

#include <stdio.h>

main()

{

int age, fare;

printf("나이를 입력하시요 : ");

scanf("%d", &age);

if(age >= 7 && age <= 12)         /*  7 - 12세 */

fare = 1000;

else if(age >= 13 && age <= 18)   /* 13 - 18세 */

fare = 1500;

else if(age >= 19 && age <= 60)

fare = 2000;         /* 19 - 60세 */

else

fare = 0;

/* 6세 이하와 61세 이상 - 무료 */

printf("나이가 %d인 사람의 입장료는 %d원입니다.",

age, fare);

}

5. while 반복문

while 문은  조건식이 거짓이  될 때까지  반복하는 루프를  형성한다.

while 루프는 while 루프 안으로 들어갈  때부터 조건식을 검사한다. if 문이

나 반복문 등에서  루프에 해당하는 문장이 하나이면 중괄호가 없어도  한 문

장은 수행하지만 루프에 소속된 문장이 두  문장 이상이면 중괄호가 있어야만

옳바른 결과를 얻을 수 있다. while 루프의 형식은 다음과 같다.

한 문장의 경우                두 문장 이상의 경우

while(조건식)                 while(조건식) {

statement;                   statement1;

statement2;

}

6. do - while 반복문

while 문과 비슷하나  while 은 루프 안에 들어가기  전에 조건을 따지

는 반면, do -  while 문은 한번 루프를 수행한 후 조건을  검사하는 것이 다

르다. do - while 루프의 형식은 다음과 같다.

do {

statement1;

statement2;

} while(조건식);

즉, 조건식 속에서 값을 입력받는 경우  while 문을 사용하면 입력받는

문장이 루프에 들어오기 전과 루프 안에 두개가  존재해야 하지만 do - while

문을 사용하면 한번으로 줄어들 수 있다.

7. for 반복문

for 루프는  타언어에서와 마찬가지로 몇가지 문장을  포함하는 반복문

이다. 즉  초기화하는 과정과 조건식,  그리고 인덱스를 증가시키는  곳 등이

포함된다. for 루프의 형식은 다음과 같다.

for(초기화; 조건문; 증가 또는 감소)  statement;

일반적으로 타언어와 비슷하면서도  C 언어만의 독특한 특징이  for 루

프에 포함되어 있다. 그것은 그만큼 융통성이  있다는 말이다. 융통성이란 다

음과 같은 것들이다.

(1) 숫자 대신  문자를 사용할 수 있다. 이것은 어떻게  보면 for 루프

의 특징이라기보다 시스템에  가까운 언어로서 문자도 숫자로 처리하는  C 언

어의 특징이라고 할 수 있겠다.

for(ch = 'A'; ch <= 'Z'; ch++) printf("%c : %d \n",ch,ch);

(2) 증가 또는 감소하는 곳은 반드시  증가와 감소만 아니라 승제 등의

다른 계산방법에 의한 변경도 가능하다.

(3) 초기화, 조건문,  증가 또는 감소하는 곳에 포함된  변수는 세곳이

모두 같은 것들이 있어야 하는 것은 아니다.

a = 0;

for(b=1; a<10; a=b * 5)   printf("a = %d, b = %d \n",a,b);

(4) for 문 안의  세 곳 중 한 곳 이상을 빈 칸으로  둘 수도 있다. 조

건문이 비는  경우는 참으로 인정되어  루프 안에 빠져나가는  조건이 없으면

무한루프가 된다. for(;;) 는 while(1) 과 같다.

(5) 첫번째  수식이 반드시 초기화일  필요는 없다. 다만  루프를 돌기

전에 수행해야 할 문장이면 된다. 어떤 함수가 와도 좋다.

8. break 문

break 는 루프 내에서 루프 밖으로 while,  do - while, for 문이 자체

적으로 가지고 있는  조건문에 의하지 않고 비상탈출하고자 할  때 사용한다.

이  문을 사용하면  조건에  관계없이 루프  밖으로  완전히 빠져나간다.  이

break 문은 루프 이외에 이후에 나올 switch 문에서도 사용된다.

9. continue 문

continue 문은 break  문과는 달리 루프를 완전히  빠져나가는 것이 아

니라 루프 내의 continue 문 이하에 있는 문장들만 한번 skip 된다.

for(i = 0; i < 100; i++) {

a = 10;

b++;

if(b < 30) continue;

c = 30;

d = 50;

}

위의 예에서 b 가  30이 못되어 continue 문을 만나면 c = 30;  과 d =

50 이라는 문장을 수행하지 않고 건너뛰어 다시 for문으로  가 a = 10; 을 수

행한다.

10. goto 문

구조적인 모듈 프로그램을  작성하기 좋은 C 언어에서 goto  문을 사용

할 필요는 없다.  하지만 만일의 경우를 위하여 goto 문이  준비가 되어 있기

는 하다. goto 문  뒤에 지시한 label 로 이동하는 명령인데  해당 함수 내에

서만 가능하다. label 은 설정할 때  이름 뒤에 콜론(:)을 붙여줌으로 구분된

다.

11. switch - case 문

여러개의 if 문을 사용해야만 할 경우  원시 프로그램은 매우 지저분하

게 보일 수도  있다. 뿐만 아니라 여러개의 if 문을  사용하면 일일히 모두를

비교해 나가야 하기 때문에 시간도 많이 걸린다.  이러한 문제를 해결하는 데

는 switch 문을 사용한다. switch 문의 형식은 다음과 같다.

switch(변수나 식) {

case 식에 대입될 상수 :

statement1;

break;

case 식에 대입될 상수 :

statement2;

break;

default :

statement3;

}

case 뒤에 있는 상수가 switch 문 뒤에  있는 변수나 식에 대입되어 조

건이 맞으면  바로 해당  문장을 수행하게 되고  해당되는 case 문이  없으면

default 문에  속한 문장을 수행한다. break  문에 case 끝마다  없으면 다음

case 문으로 무조건 떨어지게 되므로 주의해야 한다.

제 6 장   함수

1. 함수의 정의

함수란 어떤 특정한 작업을 수행하는  독립적인 프로그램을 말한다. 다

른 언어로 비유하면 서브루틴, 프로시듀어 또는  함수와 유사한 기능이다. 우

리는 그동안  함수에 대해 정확히  이해하지 않았으면서도 함수를  이미 많이

사용했다. printf(), scanf(), main() 등과  같이 괄호가 뒤에 붙어있는 것들

은 모두 함수였다.  main()은 모든 프로그램에서 반드시 하나가  있어야만 프

로그램이 시작되는 곳을 알려줄 수 있다. 이런  함수들은 컴파일러를 만든 회

사가 제공하는  함수다. 하지만 함수는 제공되는  것만 사용할 수  있는 것이

아니라 사용자에 의해 만들어질 수도 있다. 예로서  화면 중앙에 문자열을 출

력하는 함수를 만들어보자.

#include <stdio.h>

#include <string.h>

main()

{

center("JUNG ANG COMPUTER ACADEMY");

}

center(char *string)

{

int len, start, i;

len = strlen(string);

start = (80 - len) / 2;

for(i = 0; i < start; i++)  putchar(' ');

puts(string);

}

center() 라는 것은 주어진 문자열을 화면  중앙에 위치하도록 하여 출

력시키는 함수다. 어떤 문자열이든 center()  라는 함수를 시키면 80바이트가

넘지 않는 범위  내에서 화면 중앙에 오도록 출력시키는 독립적인  일을 하고

있다.

2. return 문

다른 언어에서 서브루틴으로 이동한 후에  서브루틴의 문장들이 수행되

다가 return 문을 만나면 서브루틴을 호출한  다음 문장으로 돌아가듯 C 언어

에서도 함수내에서 return 문을 만나면 함수를  호출한 다음 부분으로 되돌아

가게 된다. 그러나 C 언어에서는 return 문이 값을 가지고 돌아가게 된다.

3. 함수의 호출 및 인자의 전달

함수는 그  기능이 독립적이면서도  범용적이어야 하기 때문에  인자를

가질 수 밖에  없다. 만일 위에서 보았던 예에서 center()  라는 함수가 화면

중앙에 문자열을 나타내되  단지 그 문자열 밖에 못 나타낸다면  범용적인 함

수가 될 수 없다. center() 함수를 호출할 때 "JUNG ANG COMPUTER ACADEMY"라

는 문자열을  인자로 넘기므로 범용적이 된  것이다. 인자 전달  방법을 위해

예를 들어 두 수의 곱을 계산하는 프로그램을 만들어 보자.

#include <stdio.h>

main()                                multiply(int x, int y)

{                                     {

int a, b, c;                        int z;

printf("input a, b : ");            z = x * y;

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

c = multiply(a,b)                }

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

}

multiply() 함수의 인자는 int  형인  x 와 y 이다.  main() 함수 내에

서  multiply()  라는  함수를 호출했을  때,  그리고  multiply()  함수에서

main() 으로 다시 돌아올  때 각각 어떤 식이 성립되는가 ?   다음과 같은 관

계가 성립된다.

함수로 넘어갈 때   : x = a, y = b;

함수에서 돌아갈 때 : c = z;

4. 함수의 형

변수가 데이타형을 가지듯 함수도 그 형을  갖게 되는데 이것은 전달되

는 인자의 형에 따라  선언하는 것이 아니라 return 되는 값의  형에 따라 선

언하는 것이다. 그러므로  함수의 형은 변수의 데이타형과  유사하다. 리턴되

는 값이 없는  함수는 void 형이라고 한다. 만일 함수의  형을 선언하지 않으

면 int 형으로 간주한다. 제곱값을 구하는  연산자가 C 언어에는 없으므로 흔

히 함수로 만들어 사용하는데 그것을 예로 들어보자.

main()

{

float power(float,float);

float result;

result = power(2.0, 10.0);

printf("210 = %10.2f\n",result);

}

float power(x, y)

int x, y;

{

int i, z;

for(i = 1; i <= y; i++)  z *= x;

return(z);

}

위 프로그램에서 보는  바와 같이 power() 라는 함수는  변수선언과 함

께 함수를 호출하기 이전에 인자들의 형과 함께  선언되었다. 뿐만 아니라 함

수를 정의할 때에도  함수의 형을 함수명 앞에 붙여 놓았다.  선언도 하지 않

고 정의할 때도  그 형을 기록하지 않아 int 형으로  간주되면 리턴되는 값이

달라지기 때문이다.

제 7 장   문자열과 배열

1. 문자열

문자열이란 하나 이상의  문자들이 연속적으로 나열되어 있는  것을 말

한다. 문자열에는 space, tab, new line  등의 공백문자나 ESC 문자열도 포함

될 수 있다.  문자열의 마지막에는 NULL(\0) 문자가 오게 된다.  문자열은 다

음과 같은 것이다.

"JUNG ANG COMPUTER ACADEMY"

물론 인용부호는  문자열에 포함되지 않는다. 위의  문자열이 기억장소

에 저장될 때는 다음과 같은 형식으로 저장된다.

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

|J|U|N|G| |A|N|G| |C|O|M|P|U|T|E|R| |A|C|A|D|E|M|Y|\0|

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

위의 그림에서 문자열의 마지막은 널문자(\0)가  들어가 있음을 표시하

고 있는 것이다.  널문자란 '0' 이라는 문자를 가리키는 것이  아니라 아스키

코드값 0 을 가리킨다.

2. 문자열 함수

string.h 에 정의된 라이브러리 문자열 함수  중 많이 사용되는 함수에

다음과 같은 것들이 있다.

strlen()

문자열의 길이를  계산하는 함수로서  문자열이 널(NULL)문자  바로

이전까지의 문자수, 즉 문자열의 바이트수를 리턴한다.

int len;

len = strlen("JUNG ANG");

strcmp()

두개의 문자열을  비교하여 어느 문자열이 작고(우선)  어느 문자열

(나중)이 큰지를 알려준다. 리턴되는 값은 아래와 같다.

0보다 작은 값 : 앞의 문자열이 뒤의 문자열보다 작을 때

0 인 값       : 두 문자열이 똑같을 때

0보다 큰 값   : 앞의 문자열이 뒤의 문자열보다 클때

strcpy()

뒤의 인자로 주어진 문자열을 앞의  인자로 주어진 문자열에 복사한

다. 앞에 주어진  기억장소에 기존의 문자열이 있으면 삭제되고  대신 복사된

문자열만 존재하게 된다.

char name[20];

strcpy(name,"hong kil dong");

strcat()

뒤의 인자로 주어진  문자열을 앞의 인자로 주어진 문자열  뒤에 덧

붙인다. 뒤의 문자열은  그대로 남아있고 앞의 인자로 주어진  기억장소의 문

자열만 추가되어 변한다.

char name[20] = "hong";

strcat(name, " kil dong");

strupr()

주어진 인자의 문자열  가운데 소문자(a-z)로 된 문자를  모두 대문

자(A-Z)로 바꾸어 주는 함수다. 다른 문자는 바꾸어지지 않는다.

char name[] = "hong kil dong";

printf("%s",strupr(name));

HONG KIL DONG

strlwr()

주어진 인자의 문자열  가운데 대문자(A-Z)로 된 문자를  모두 소문

자(a-z)로 바꾸어 주는 함수다. 다른 문자는 바꾸어지지 않는다.

char name[] = "HONG KIL DONG";

printf("%s",strlwr(name));

hong kil dong

3. 배열

앞 절에서 예로 들었던 것처럼 문자열은  연속되어 있는 것이므로 컴퓨

터 메모리의 연속적인  공간을 할애하여 사용해야 하는데  연속적인 기억장소

할당은 배열선언에  의해 이루어진다. 그러므로 배열이란  메모리상에 연속적

인 한 행으로 나열된 것이다. 배열은 문자의  저장만을 목적으로 있는 것만이

아니므로 배열은 데이타형을 가지게 되는데 이는  여러개의 변수를 나란히 선

언하는 것보다  편리하게 사용되는 것이기  때문에 배열의 한  요소는 하나의

변수와 동일하며 그래서 하나의 요소는 데이타형에  따라 크기가 달라지게 되

는 것이다.

char name[81];

이것은 1 바이트를 차지하는 문자형이므로  배열 전체의 크기는 81바이

트가 된다. 이  때 여기에 들어갈 수 있는 문자열의  최대 크기는 80바이트이

다. 널문자가 마지막에 있어야 하기 때문이다.

int num[20];

그러나 int  형은 2 바이트이므로  전체 크기는 20바이트가  아니라 40

바이트가 된다. 배열을  선언할 때의 배열요소의 갯수와 배열의  마지막 첨자

와는 다르다. 배열의 하나의 요소를 가리키는  첨자는 0부터 시작하므로 위의

예에서 마지막 배열의  요소는 num[19] 가 된다. 첨자란 데이타형에  따른 크

기로 시작점에서부터 떨어진  거리가 된다. 위의 배열에서 num[0]  이라는 식

으로 표현하면 기억장소를 가리키는 변수가  되지만 배열의 대표명인 num이라

고만 하면 변수가 아니라 주소를 나타내는 상수가  된다. 즉 num 이라는 배열

의 대표명은 첫번째 요소인 num[0] 의 주소인  &num[0] 과 같다. 배열의 형에

는 데이타형의 종류대로 존재한다.

4. 배열의 초기화

배열을 초기화할 때는 두가지 방법이  있다. 문자열로 초기화할 경우와

기타의 경우다.

char name[14] = "hong kil dong";

초기화된 문자열은  13개의 문자로 이루어졌으므로 널문자가  들어갈 1

바이트를 더하여 14바이트를 선언했다.

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

이런 경우는 문자형이 아니므로 하나의  기억장소가 더 필요하지 않다.

10개의 정수가 들어갈 10개의 배열만 선언하면  된다. 이 배열의 전체 크기는

2 바이트를 차지하는 int 형 20 바이트이다.

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

여기서는 배열의 크기를 선언하지 않았다.  만일 이처럼 크기를 지정하

지 않고 초기화도 하지 않았다면 문제가  발생하겠지만 지금의 경우는 크기는

선언하지 않았으나 초기화가 되었으므로 초기화된  갯수만큼의 크기가 자동으

로 설정된다.

char name[] = "hong kil dong";

이러한 경우도 배열의 크기가 선언되지  않았지만 초기화되었으므로 선

언된 만큼 설정되나 문자형이므로 널문자를  위하여 1바이트 추가되어 설정된

다. 문자열도 중괄호를  사용하여 한 문자씩 초기화할 수 있다.  단 문자열을

아래와 같이 초기화할 때는 마지막에 널문자가 추가되어야 한다.

char name[] = { 'h','o','n','g',' ','k','i','l',' ',

'd','o','n','g','\0' };

예제)  문자열을 입력하여 한 줄에 한 문자씩 아래와 같이 거꾸로

출력하도록 프로그램 하시요.

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

|   문자열을 입력하시요 : ba bo   |

|   o                             |

|   b                             |

|                                 |

|   a                             |

|   b                             |

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

<해>

#include <stdio.h>

main()

{

int i, len;

char str[81];

printf("Input Srting : ");

gets(str);

len = strlen(str);

for(i = len - 1; i >= 0; i--) {

putchar(str[i]);

printf("\n");

}

}

5. 다차원 배열

월별 가계부 프로그램을 작성한다고 가정할 때  월별 통계만 낸다면 가

계부로서 의미가 없을 것이다. 월별로 하되 항목별로  통계가 나와야 보다 제

대로 된  프로그램이라 할 수 있을  것이다. 이럴 때 1차원  배열을 가지고는

원하는 프로그램을  작성하는데 있어서  많은 혼동이  될 것이다. 이렇  때는

int home[월수][지출항목수] 로  2차원 배열을 선언하면 보다  손쉽게 프로그

램을 작성할 수 있겠다. 2차원 배열의 초기화를 해보자.

int home[12][5] = {

{ 35000, 55000, 20000, 100000, 70000 },

/*  1월의 항목별 지출액수 */

{  6000, 15000, 48000,  28000, 12000 },

/*  2월의 항목별 지출액수 */

.

.

.

{ 23000, 16000, 37000, 44000,  5000 },

/* 11월의 항목별 지출액수 */

{ 50000, 20000, 30000, 40000, 10000 }   };

/* 12월의 항목별 지출액수 */

가계부 프로그램을 작성하는데 항목이 5개밖에  없을 리는 없지만 간단

한 예를 위하여  이렇게 하였다. 2차원 배열이니만큼 중괄호는  2중으로 둘러

싸여야 하고, 1차원씩 초기화하고 나서는 콤마(,)로 구분해야 한다.

다음과 같은 방법으로도 초기화할 수 있다.

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

6. 함수에서의 배열 인자

함수 호출시 1차원 배열인자

main() {

char name[] = "HONG SAMYULL";

print(name);

}

print(char string[]) {

printf("MY NAME IS %s.\n",string);

}

print() 라는 함수로  배열명을 인자로 넘겨주었고

print() 라는 함수에서는 같은 string[] 이라는  배열로 받아 처리하고 있다.

배열인자를 받는 곳에 배열의 크기가 설정되어  있지 않아도 인자를 넘겨받으

면서 자동 초기화되어 그 크기만큼  기억장소가 설정되므로 1차원 배열에서는

상관이 없다.

함수호출시 다차원 배열 인자

main() {

char alpha[2][3] = { { 'A','B','C' }, { 'D','E','F'} };

print(alpha);

}

print(char s[][3]) {

int i, j;

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

for(j = 0; j < 3; j++)  putchar(s[i][j]);

}

2차원 배열을 인자로 넘겨줄 때 역시  배열명으로 넘겨줄 수 있으나

받을 때는 반드시 2번째 배열첨자는 길이를 정의해 주어야 한다.

제 8 장   포인터

1. 포인터란 ?

포인터란 "가리키다"(point) 라는 동사를 명사화시킨 것으

로 무엇인가를  가리키고 있다는 의미를 가지고  있다. 포인터란

자기 자신은 어떤 정보를 갖고 있지 않고 다른 어떤 부분을 가리

키고 있는 것이다.

C 언어를 배우고자 하는 모 대학 학생이 중앙정보처리학원

에 등록하기까지는 학원을 직접  찾아오는 것이 제일 빠르겠지만

반드시 그런 경우만 있는 것이  아니다. 다니는 대학에 붙어있는

현수막 광고를 보고 찾아온 경우도 있을 수 있고, {컴퓨터} 하면

"아무개"에게 물어보면 모든  정보를 가진 학생이 있다고  할 때

그 학생을 찾아가 물어볼 수도 있다.  그러면 그 학생은 대학 통

로에 걸려있는 학원광고 현수막을  가르쳐준다고 가정하자. 현수

막을 보고 전화를 걸고 학원을 찾아오게 되는 경우가 있을 수 있

다. 이처럼  학원에 등록한다는 결과는 같지만  거기까지의 경로

가 각각 다를 수 있다. 이럴  때 현수막광고가 있는 자리나 컴퓨

터에 대한 많은 정보를 가진  학생을 알고 있는 것이 중앙정보처

리학원을 알고 있는 것보다 나을 수가 있는 것이다. 만일 중앙정

보처리학원이 이사를 했다고 하자.  중앙정보처리학원만 알고 있

는 경우라면 이사간 정보에 대해  모른다. 하지만 컴퓨터에 관한

많은 것(정보처리학원이 이사간 것까지)을  아는 사람을 아는 것

이 정보를 얻어내는데 더욱 편리하고 유리할 수 있다. 이런 경우

에 중앙정보처리학원 자체는 아니지만  컴퓨터 전반에 대해서 알

고 있는 사람을 포인터라고 할 수 있다. 이처럼 포인터란 데이타

가 있는 주소를 가지고 있는 것을 말한다.

2. 포인터 변수의 선언

C 언어에서 모든 변수는 사용하기  전에 미리 선언해야 하

는데 포인터  변수의 경우도 마찬가지다. 변수의  선언의 방법은

다음과 같다.

int *num_pointer;

위의 예와 같이 일반적인  변수를 선언하듯 데이타형 뒤에

변수를 쓰는데 다만 변수명 앞에 '*'를 붙인다는 것이다. 그랬을

때 num_pointer는 포인터 변수가 된다. 즉 주소값을 기억하는 기

억장소이다. 프로그램상에서 '*'를 붙여 사용하면 가리키는 주소

에 있는 내용이, '*'를 제외하고 사용하면 주소값을 사용하게 된

다.

3. '&' 와 포인터형 캐스트 연산자

일반적인 변수를 선언했을 때  프로그램 내에서 변수를 사

용하면 변수에  들어있는 내용을 사용하게 되는  것이다. 그러나

그 내용이 들어있는 주소를 알거나  가리키기 위해서는 '&' 연산

자를 사용해야만 한다. scanf()와  같은 함수에서는 주소를 인자

로 원하기 때문에 이 연산자를  사용해야만 한다. 포인터형 캐스

트 연산자는 일반적인  변수에 대한 캐스트 연산자와  같은 방법

으로 다음과 같이 사용된다.

int i;

float *fp;

fp = (float *)&i;

4. 포인터와 배열의 차이점

포인터와 배열의 대표명은 모두 주소를 가리킨다는 점에서

같으나 차이점이 있다. 아래 예를 통해 다른 점들이 무엇인지 알

아보자.

static char array[] = "Jung-Ang";

char *point = "Computer";

(1) 포인터는 변수이나 배열은 상수이다.

(2) 포인터나 배열 모두 덧셈은 가능하다.

putchar( *(array + 1) );

putchar( *(point + 1) );

(3) 포인터만 증가나 감소 연산자를 사용할 수 있다.

putchar( *(point++) );

(4) 배열명은 좌변에 올 수 없다.

point = array;        /* 가능 */

array = point;        /* 불가능 */

5. 포인터와 일차원 배열

배열의 대표명은 배열의 첫번째  요소가 있는 주소를 가리

킨다. 배열이란 데이타형의 크기만한  기억장소가 나란히 일렬로

배열요소의 갯수만큼 할당된다. 포인터는  주소를 기억하는 변수

이고 배열명도 주소를  가리키기 때문에 같은 용도로  사용할 수

있다는 점에서 같으나 포인터는  변수이고 배열명은 주소를 가리

키는 상수라는 점에서 다르다. 즉 포인터는 증가 또는 감소가 가

능하나 배열은 증가나  감소는 가능하지 않고 다만  첨자만 사용

할 수 있을 뿐이다. 그리고 배열명은 상수이므로 좌변에는 올 수

없다.

int array[20], *point, i, tot;

point = array;

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

tot += *point++;

6. 포인터와 다차원 배열

2차원 배열을 예로 들면 선언은 int array[10][2]; 식으로

선언하게  된다.  즉  10행 2열이다.  이러한  경우  기억장소는

[0][0], [0][1],  [1][0], [1][1], [2][0],  [2][1] .... 순서의

일렬로 잡힌다.  그러므로 포인터로 대응될 때는  포인터가 증가

하는 순서 역시 위의 순서가 된다.

int array[10][2], *point;

point = array;

위의 예에서 *(point + 4) 라고 하면 array 의 5번째 요소

인 array[2][0] 를 가리키게 되는 것이다.

*(point + 0) == array[0][0]

*(point + 1) == array[0][1]

*(point + 2) == array[1][0]

*(point + 3) == array[1][1]

.

.

다차원배열일 경우 포인터를 사용하는 것이 기억장소의 낭

비를 줄일 수 있다.

7. 함수에서의 포인터 인자

포인터를 포인터로

#include <stdio.h>

main()

{

char *academy = "JUNG ANG COMPUTER";

int len;

len = str_len(academy);

printf("academy name length = %d\n", len);

}

str_len(char *s)

{

int n = 0;

while(*s++) n++;

return(n);

}

<결과>

academy name length = 17

위의 예는 문자열의 길이를 구하는 strlen() 함수와 같

은 일을 하는 str_len() 이라는  함수를 만들어 본 것이다. 여기

서 함수에 넘겨지는 인자는 main() 함수에서 문자열의 주소인 포

인터가 넘겨졌고 str_len() 함수에서도 같은 문자형 포인터로 받

았다. str_len() 함수 내에서  문자열의 주소가 증가되면서 내용

이  없을 때,  즉 null  문자가  나타날 때까지  n 을  증가시켜

main() 에 돌려준다. null  문자는 문자열의 길이에 포함되지 않

는다.

포인터 배열을 포인터 배열로

#include <stdio.h>

main()

{

char *str[] = {

"JUNG ANG COMPUTER",

"DATA PROCESS",

"ACADEMY",

"C LANGUAGE",

"ON THE JOB OF TRAINNING",

"HONG SAM YULL" };

print_jungang(str, 6);

}

print_jungang(char *s[], int n)

{

int i;

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

printf("%s \n", s[i]);

}

<결과>

JUNG ANG COMPUTER

DATA PROCESS

ACADEMY

C LANGUAGE

ON THE JOB OF TRAINNING

HONG SAM YULL

/* str_len.c */

#include <stdio.h>

main()

{

int len;

char *str[] = {

"JUNG ANG COMPUTER",

"DATA PROCESS",

"ACADEMY",

"C LANGUAGE",

"ON THE JOB OF TRAINNING",

"HONG SAM YULL" };

int i;

for(i = 0; i < 6; i++) {

len = str_len(str[i]);

printf("%s = %d \n", str[i], len);

}

getch();

}

str_len(char *s)

{

int len = 0;

while(*s++)

len++;

return(len);

}

<결과>

JUNG ANG COMPUTER = 17

DATA PROCESS = 12

ACADEMY = 7

C LANGUAGE = 10

ON THE JOB OF TRAINNING = 23

HONG SAM YULL = 13

8. 메모리 모델

.EXE(.COM) 화일 구조                        메 모 리

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

|화일헤더(.COM화일에는없음)             |Program Segment Prefix|

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

|       CODE          |                 |       CODE           |

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

|       DATA          |                 |       DATA           |

|  (초기화된 데이타)  |                 |  (초기화된 데이타)   |

+---------------------+   ----------->  +----------------------+

| (비초기화된  데이타)|      MAPPING    | (비초기화된 데이타)  |

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

|HEAP, STACK 크기 지정|                 |       HEAP           |

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

|         STACK        |

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

프로그램이 컴파일될 때는  메모리의 어느위치부터 로드가

되던 상관이  없도록 만들어진다. 로더에 의해  메모리로 프로그

램이 옮겨지면 화일헤더부분 대신 PSP  라는 영역이 생긴다. PSP

영역의 길이는 256(100h) 바이트이다. EXE 화일과 COM 화일의 차

이점은 최소  512바이트를 차지하는  화일헤더가 없다는  것이다

(COM 화일은 다음에 설명할 메모리 모델 가운데 TINY모델의 경우

에만 만들어질 수 있는데 일단 EXE  화일로 만든 다음 도스가 지

원하는 EXE2BIN 프로그램을 통해 변환할  수 있다). 컴파일할 때

디스크의 화일에는 HEAP과 STACK은 실제로 할당하지 않고 크기만

정의해 놓게 되며  메모리에 매핑이 된 후에는  메모리를 차지하

게 된다.  EXE 화일의 경우  메모리에 매핑되면 화일  헤더 대신

Program Segment Prefix (PSP) 라는  것이 생기게 된다. 이는 코

드 세그멘트와 데이타  세그멘트의 시작 주소 등을  가지고 있는

곳이다.

(1) SEGMENTATION

16비트 컴퓨터란 무엇을 말하는가 ?  이것은 한번에 처

리할 수 있는 데이타의 양, 즉 CPU REGISTER 하나당 크기나 데이

타를 운반하는 BUS 의 크기를  말한다. 그런데 데이타 버스에 의

해 메모리 주소도 지정하게 되는데  메모리 주소는 20 비트를 차

지한다. 그러므로 16비트의 데이타 버스로는  운반할 수 없기 때

문에 16비트씩 둘로 나누는 작업을 하게 되는데 이를 세그멘테이

션이라고 한다. 16비트짜리 둘을 합해 20비트를 표현하는 방법은

아래와 같다.

1111 0000 0000 0000        (16비트 - Segment)

1111 1111 1111 1111   (16비트 - Offset)

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

1111 1111 1111 1111 1111   (20비트 - 절대 주소)

위와 같이 16비트씩을 비껴서 더하면 실제 메모리의 주

소를 만들어낼 수  있다. 왜 이와 같은  방법을 사용하지 않으면

안 되는가 ?  현재 사용하는  16비트 방식의 컴퓨터 이전에 사용

하던 최대 메모리 64 KB였던 8비트 컴퓨터와의 데이타 호환을 위

해 불가피했던  것이다. 이처럼 세그멘테이션을 일으켰을  때 위

계산식 중 윗부분 16비트를 세그멘트라고 하고, 아랫부분 16비트

를 옵셋(편차)이라고 한다. 하나의 세그멘트는 64 KB 이며, 도스

가 지원하는 최대 메모리 640 KB 는 10개 (0 - A) 의 세그멘트로

나누어지게 된다. 32비트 운영체제(OS)인 OS/2 에서는 512 MB 의

메모리를 지원하고 있는  바 앞으로는 이러한 문제가  없어질 것

이다.

(2) 명령어 집합 및 데이타 크기에  따른 메모리 모델 선택

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

|  모델  |  코드 세그멘트 |        데이타 세그멘트        |

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

|  TINY  |    합해서     1     세그멘트    이내           |

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

|  SMALL | 1 세그멘트이내 |  1  세그멘트이내              |

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

| MEDIUM | 1 세그멘트이상 |  1  세그멘트이내              |

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

| COMPACT| 1 세그멘트이내 |  1  세그멘트이상              |

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

| LARGE  | 1 세그멘트이상 |  1  세그멘트이상              |

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

| HUGE   | 1 세그멘트이상 |  1 세그멘트이상(하나의 배열도)|

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

9. 기억장소의 종류

(1) 전역변수와 지역변수

변수를  구분하는  한가지 방법으로  전역변수(global

variable) 와 지역변수(local variable)  로 구분할 수 있다. 전

역변수는 프로그램  전 영역에서  사용가능한 변수로  함수 밖에

선언하며, 프로그램 머리에 선언해야  한다. 지역변수는 한 함수

내에서만 사용가능한  변수이며 전역변수와 지역변수가  같은 이

름의 것이 있을 때는 지역변수를 우선한다.

(2) 기억방식에 따른 기억장소의 종류

자동변수 (auto variable) : static 으로 선언되지

않은 지역변수(국소변수)를  말하므로 다른 함수에  영향을 미칠

수 없다. 자동변수가 기억되는 곳은   운전기사의 동전통과 같은

원리인 push-pop 방식 (LIFO) 의 stack 부분에 저장된다.

정적변수  (static) : 함수 내부와  함수 외부에서

선언하는 종류가  있으며, 데이타  세그멘트에 기억되는  것으로

함수 내에서 선언되더라도 그 값이 바뀌지 않는다.

외부변수 (extern) : 함수의 밖에서 정의되며 따로

떨어진 두개 이상의 원시화일을  컴파일하고 링크작업에 의해 합

하고자 할 때  다른 원시화일에서 선언된 변수를  그대로 사용한

다는 의미로 선언한다.

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

|   제 1 소스 컴파일 |      | 제  2 소스 컴파일 |

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

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

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

|       두 화일을 함께 링크         |

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

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

|            실       행            |

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

레지스터변수 (register)  : 자동변수와 크게 다를

바 없으나 다만 기억되는 장소가 CPU 의 레지스터라는 점이 다르

다.

10. 동적 할당

배열과 포인터 변수를 같은  목적으로 선언했을 경우 어떤

차이가 있는가 ?  배열은 실제 기억장소를 할당하는 것이므로 데

이타 세그멘트에 할당이 된다. 그러나  포인터 변수는 선언할 때

초기화시키지 않으면  주소만 기억하고 있고  실제로 기억장소를

할당하지는 않으므로  프로그램 중에서 해당  포인터를 사용하고

자 할  때 기억장소가  확보되지 않았으므로 사용할  수가 없다.

이럴 때 heap 의 영역에 기억장소를 임시로  확보해  사용하려면

malloc() 이라는 함수를 사용하게 된다.

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

|                                         |

|   char *p;                              |

|   int i;                                |

|                                         |

|   p = (char *)malloc(27);               |

|   for(i = 0; i < 26; i++)               |

|       *p++ = 'A' + i;                   |

|   *p = 0;                               |

|   free(p);                              |

|                                         |

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

위의 예에서 포인터 변수  p 를 사용하기 위해 1000바이트

할당하는 모습이다.  이를 동적  할당이라고 하는데 할당된 메모

리를 해제할 때는 free() 라는  함수에 의한다. 디스크복사 프로

그램  등 640  KB  전 영역의  메모리를  할당하여야 할  경우는

farmalloc() 과 farfree() 를 사용한다.

제 9 장  선행처리기 (PREPROCESSOR)

선행처리기 (preprocessor) 란 C 컴파일러가 원시 프로그램을

기계어로 컴파일할 때  처리하는 것이 아니라 원시  프로그램 한

줄 한 줄을 컴파일하기 이전에 미리 처리해 놓는 방법과 그 구문

을 말한다.

1. #include

include 는 "포함하다" 라는 뜻으로  이 문 뒤에 있는 화

일이 이 문이 있는 자리에 불러들여진 후 컴파일된다.

[MAIN.C] -----------------------------------

#include <stdio.h>

#include "strlen.h"

main()

{

int len;

char *str;

str = (char *)malloc(20);

scanf("%s",str);

len = str_len(str);

printf("%s length = %d\n",str,len);

}

[STRLEN.H] ---------------------------------

str_len(char *s)

{

int num = 0;

while(*s)  num++;

return(num);

}

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

2. #define

define 은 "정의하다"  라는 뜻으로 기호상수를 정의하는

데 주로  사용되며 변수와  구별하기 위해  일반적으로 대문자로

표기한다. 정의된 기호상수는 프로그램  내에서 사용되면 컴파일

될 때 미리 본래의 상수로 바꾼 뒤 컴파일하게 된다.

#define PI 3.141592

main()

{

float r, width, circle;

scanf("%f",&r);

circle = r * 2.0 * PI;

width  = r * r * PI;

printf("circle = %f, width = %d\n", circle, width);

}

위의 #define 문에서 PI  는 약어이고 3.141592 부분은 본

래의 값이다. 약어부분에는 공백이 있어서는 안된다.

#define MSG "Jung Ang Data Process Institute"

위의 경우는  문자열을 MSG 라는 약어로  정의해놓은 것이

다. 여기에서는 이중 따옴표까지 포함된다.

#define abs(x) ((x) < 0 ? -(x) : (x))

위의 경우는 인자를 가지는 define 문이다. 마치 함수처럼

이용될 수 있다. 정의할 때 주의할  점은 인자 하나 하나를 괄호

로 싸주어야 한다. 이러한 경우를 매크로라 부른다.

3. 기타 선행처리기

#include 와 #define 이외의 선행처리기에는

#ifdef

#ifndef

#else

#endif

#undef

등이 있다.

#define TURBOC

#ifdef  TURBOC

harderr(int handler);

#else

_harderr(int handler);

#endif

위의 예는 이런 의미이다.

첫째줄 :  TURBOC 라는 것을 define  해 놓았다. 무엇을

정의했는지는 정해져 있지 않지만 이러한 정의도 가능하다.

둘째줄 : 프로그램식으로 이해할 수 있다. "만일 TURBOC

가 정의되어 있으면" 이라는  뜻이다. 현재는 정의되어 있으므로

해당된다.

셋째줄 : 터보  C 에 있는 시스템 에러를  체크하는 함수

다.

넷째줄 : 만일 TURBOC  가 정의되어 있지 않으면 이하를

실행한다. MS C 로 컴파일하려면 첫째줄만 없애버리면 된다.

다섯째줄 : MS  C 에 있는 시스템 에러를  체크하는 함수

다.

여섯째줄 : #ifdef 문이 끝났다는 의미다.

※  #undef 는 define 된 것을 취소시킨다.

※   #ifndef 는  #ifdef 의 반대의  경우가 된다.  (n :

NOT 의 의미)

4. typedef

typedef 는 define 이나 같은 의미이지만 단지 데이타형에

만 적용될 수 있다는 점이다.

5. main() 함수 ARGUMENT

어떤 프로그램, 특히  도스 명령(내부명령 혹은 외부명령)

에서 보면 프로그램을  실행시킬 때 화일명이나 옵션을  뒤에 붙

여 실행하는 경우가 있다. 이러한  프로그램을 작성할 수 있도록

C 언어는 main() 함수에 실인자를 지정할 수 있다.

main(int argc, char *argv[])

argc 는  프로그램 자신의 화일명(명령)을  포함한 옵션의

갯수를 가지고 있는 인자이므로  int 형으로 되어 있다. *argv[]

는 포인터의  배열이므로 이차원  배열과 비슷한  용도로 사용된

다. 여기에는  자신의 프로그램명이  기억된 기억장소의  주소를

첫 포인터가  가리키고, 이어서  옵션들을 기억하는  기억장소의

주소를 다음 포인터들이 가리키고 있게  된다. 예를 들어 아래와

같이 명령을 내리는 프로그램이라고 하자.

C:\> COPY1.EXE  SRC.FIL  TGT.FIL

도스의 COPY 명령과 같은  프로그램 이름을 쓴다면 도스명

령이 실행될 것이므로  '1'을 뒤에 붙였으나 COPY  와 같은 일을

하는 프로그램이라고 가정하자.  이럴 때  COPY1.EXE 은 argv[0]

이 가리키는 곳에 기억되고, SRC.FIL 은 argv[1] 이 가리키는 곳

에, TGT.FIL 은 argv[2] 가  가리키는 곳에 각각 기억된다. 그러

므로 위의 예의 경우 argc 는 3 이라는 값을 가지고 있게 된다.

#include <stdio.h>

main(int argc, char *argv[])

{

if(argc != 3) {

puts("USAGE : COPY1 <source file> < target file>");

exit(1);

}

|

|

}

제 10장   구조체와 공용체

1. 구조체(struct)란 ?

C 언어 구문 가운데 또  하나 생소한 것이 구조체이다. 구

조체란 일정한 형식으로  몇가지 항목을 하나의 내용  안에 담도

록 짜맞추는 일종의 데이타형이라고 할  수 있다. 여러개의 데이

타형에 의한 기억장소를 늘어놓은  집합이다. 구조체를 선언하는

방법은 다음과 같다.

struct  tag명 {

데이타형  항목명;

데이타형  항목명;

|

|

};

위의 형식에서 tag명은 구조체를 구분하기 위한 것 뿐이고

변수명칭은 아니다. 변수 명칭은 아래와 같이 선언한다.

struct tag {

int num;

char name[20];

} card;

struct tag {

int num;

char name[20];

};

struct tag card;

위의 두가지 방식으로  구조체변수를 선언할  수 있다.

2. 구조체의 초기화

구조체는 다음과 같은 두가지 형태로 초기화할 수 있다.

struct tag {

int num;

char name[20];

} card = { 1, "hong kil dong" };

struct tag {

int num;

char name[20];

};

struct tag card = { 1, "hong kil dong" };

배열인 경우는 다음과 같다.

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

|                                                          |

|                     struct tag {                         |

|                       int  num;                          |

|                       char name[20];                     |

|                     };                                   |

|                                                          |

|   struct tag card[2] = { { 1, "hong  kil dong" },        |

|                          { 2, "noh ka ree"     }  };     |

|                                                          |

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

위의 예에서 card[] 라는  배열은 tag 라는 구조체의 형을

가진 기억장소이므로 card[0] 과 card[1] 은 각각 22바이트 크기

임을 알 수 있다. 태그명이나  변수명은 키워드나 내장함수가 아

니면 무슨 이름이든 지정할 수 있다. 이 절에서는 선언방법과 초

기화 방법만 서술되었으므로 다음  절에 넘어가서 구조체의 일부

분을 지정해서 사용하고자 할 때의 방법을 알아보자.

3. 피리어드 연산자와 화살표 연산자

구조체에 속한 하나의 요소를  사용하고자 할 때는 새로운

연산자를 사용해야 한다.

struct tag {

int num;

char name[20];

};

struct tag card;

card.num = 1;

strcpy(card.name, "hong kil dong");

위의 예에서는 피리어드('.') 연산자를 사용하여 구조체의

요소를 사용하고  있다. 그러면 만일 구조체  변수를 포인터변수

로 선언했을 때는 어떻게 해야 되겠는가 ?

struct tag {

int num;

char name[20];

};

struct tag *card;

card->num = 1;

strcpy(card->name, "hong kil dong");

구조체 포인터변수를 선언한 가운데 한 요소를 지정하려면

위의 예에서는 (*card).num 식으로 표시해야 하지만 대신 화살표

연산자를 사용하면  간단하게 표시할 수 있다.  화살표 연산자는

마이너스('-') 기호와 부등호 표시('>') 를 붙여서 표현한다.

4. 함수에서의 구조체 인자

구조체 형태의 데이타를 함수로 넘길 때 구조체를 많이 사

용하는데 다음과 같은 방식으로 전달한다.

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

|                                                            |

|    #include <stdio.h>                                      |

|                                                            |

|                     struct tag {                           |

|                        int  num;                           |

|                        char name[20];                      |

|                     };                                     |

|                                                            |

|    main()                                                  |

|    {                                                       |

|      struct tag card;                                      |

|      input_card(&card);                                    |

|      printf("num = %d,name =  %s\n", card.num,card.name);  |

|    }                                                       |

|                                                            |

|    input_card(struct tag *in)                              |

|    {                                                       |

|      scanf("%d", &(in->num));                              |

|      scanf("%s", in->name);                                |

|    }                                                       |

|                                                            |

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

위의 예에서  보듯이 input_card() 라는  함수로 card라는

구조체 변수의 주소를  넘겨주고 있다. input_card() 함수에서는

struct 구조체 포인터변수로 넘겨받아 화살표 연산자를 사용하여

카드 입력을 받고 있다.

5. 공용체(union)

공용체(유니온)란 같은 기억장소에  다른 데이타형을 저장

하여 공용으로 사용할 수 있도록  하는 매체이다. 마치 중앙정보

처리학원 건물을  칸막이로 이렇게 저렇게  변경하여 막아쓰지만

장소는 같은 장소인 것처럼  기억장소를 공용으로 사용하는 것을

말한다. 공용체는 구조체와 거의  같은 방식으로 정의된다. 태그

명도 있고 변수도 있다. 피리어드  연산자도 있고 화살표 연산자

도 쓰인다. 다만 쓰이는 용도와 내용만  다를뿐이다.   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;                                  |

| };                                                           |

|                                                              |

| struct  SREGS   {                                            |

|         unsigned int    es;                                  |

|         unsigned int    cs;                                  |

|         unsigned int    ss;                                  |

|         unsigned int    ds;                                  |

| };                                                           |

|                                                              |

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

여기서는 구조체와 공용체가 혼합되어 있는 것을 볼 수 있

다. 위의 내용은 대략 다음과 같은 것을 나타낸다.

6. CPU 레지스터 구조

16비트 컴퓨터를 기준으로 볼 때 CPU 는 다음과 같은 레지

스터들을 가지고 있다.

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

AX |  AH             |  AL             |

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

BX |  BH             |  BL             |

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

CX |  CH             |  CL             |

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

DX |  DH             |  DL             |

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

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

SP |                                   |

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

BP |                                   |

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

SI |                                   |

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

DI |                                   |

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

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

IP |                                   |

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

FL |                                   |

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

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

CS |                                   |

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

DS |                                   |

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

SS |                                   |

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

ES |                                   |

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

제 11장   라이브러리 루틴

1. 화일처리함수

화일을 접근할 때는 반드시 화일을 열어주고, 사용한 다음

에는 반드시  닫아주어야 한다. 실행화일의 경우는  도스가 알아

서 해  주겠지만 프로그램  내에서 지정하는  데이타화일의 경우

반드시 열어주고 닫아주는 일을  프로그래머 자신이 설계해야 한

다. 그러나 이런 일은 그렇게  어려운 일은 아니다. 왜냐하면 이

러한 함수를 C 언어 라이브러리 함수가 제공해 주기 때문이다.

fopen()

화일을 열어주는 함수이다. 형식은 아래와 같다.

fopen("화일명","화일접근모드");

화일명은 화일을 열어줄 때만  필요하다. 이 함수는 구

조체 포인터형  함수이므로 stdio.h 에 있는  구조체를 이용해야

한다.

typedef struct  {

short level;            /* fill/empty level of buffer */

unsigned flags;         /* File status flags    */

char fd;                /* File descriptor      */

unsigned char hold;     /*  Ungetc char  if no buffer */

short bsize;            /* Buffer size          */

unsigned char *buffer;  /* Data transfer buffer */

unsigned char *curp;    /* Current active pointer */

unsigned istemp;        /*  Temporary file indicator */

short token;            /* Used  for validity checking */

}  FILE;                     /* This is the FILE object */

위의 구조체는  FILE 이라는 구조체로  정의되어 있다.

typedef 를 사용하여 정의하였으므로  FILE 은 변수가 아니라 위

의 구조를 가진 데이타형임을 의미한다.

화일을 여는 예를 들어보자.

#include <stdio.h>

main()

{

FILE *in;

in = fopen("A.DAT","r");

if(!in) {

puts("FILE NOT FOUND.");

exit(1);

}

|

|

}

위의 예에서 포인터변수 *in 은 FILE 이라는 구조체 포

인터 변수이다. fopen() 이라는  함수가 구조체 포인터형 함수이

기 때문이다. 화일을 열때 화일  이름 뒤에 붙이는 화일접근모드

에는 다음과 같은 것들이 있다.

"r"  : 읽기 전용모드로서 화일에 데이타를  쓸 수는 없다.

화일이 존재하지 않으면 에러가 발생한다.

"w"  : 쓰기 전용모드로서 화일데이타를 읽을  수는 없다.

화일이 이미 존재하는 경우  본래의 내용은 삭제되므로

주의해야 한다.

"a"  : 읽기 쓰기가  모두 가능한 추가모드이다. 데이타를 화일

에 쓸 때는 기존의 내용 뒤에 추가된다.

"rt" : 읽기 전용모드로서  텍스트화일을 열때 사용한다.

"wt" : 쓰기 전용모드로서  텍스트화일을 열때 사용한다.

"at" : 추가 모드로서 텍스트화일을 열때 사용한다.

"rb" : 읽기 전용모드로서  바이너리화일을 열때 사용한다.

"wb" : 쓰기 전용모드로서  바이너리화일을 열때 사용한다.

"ab" :  추가 모드로서  바이터리화일을 열때  사용한다.

텍스트화일모드와 바이너리화일 모드에서 실제로 차이나는

부분은 예를 들면 '\n' 이  텍스트에서는 한 바이트로, 바이너리

에서는 두 바이트로 읽혀진다는 점이다.

fclose()

화일을 열고 읽거나 쓴 후  화일을 닫아주는 역할을 한

다. 함수의 인자로는 화일명이 필요없고  다만 화일 구조체 포인

터변수만 넘겨주면 된다.

FILE *in;

in = fopen("A.DAT","r");

|

fclose(in);

표준 입출력 함수와 유사한 스트림 함수들

fprintf(스트림, 포맷, 인자)

fscanf(스트림, 포맷, 변수의 주소)

fgetc(스트림)

fputc(문자, 스트림)

fgets(문자열 기억장소, 최대 문자수, 스트림)

fputs(문자열, 스트림)

|

|

fseek()

화일을 배열로  취급하여 직접 어떤 지점을  찾아갈 수

있는 함수로서 형식은 다음과 같다.

fseek(스트림, 편차, 모드)

위에서 편차란 모드에  따른 시작점으로부터 떨어진 바

이트수를 의미한다. 모드란 아래의 의미를 가진다.

0 : 화일의 처음으로부터

1 : 화일의 현재 위치로부터

2 : 화일의 마지막 위치로부터

2. 프린터 출력 방법

프린터는 스트림의 하나이므로 화일을  열 때 화일명 대신

prn 이라는 프린터 디바이스 드라이버를 지정하면 마치 화면이나

디스크에 출력하는 것처럼 프린터로  인쇄된다. 프린터에서 읽어

올 것은 없으므로 w 모드로 열어주면 된다.

FILE *printer;

printer = fopen("prn", "w");

fprintf(printer, "%s", "JUNG ANG COMPUTER");

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

|        기        능         |  제 어 코 드  |  아스키 십진   |

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

|  한글 프린트 모드           |   ESC   h      |    27,  104   |

|  영문 프린트 모드           |   ESC   e      |    27,  101   |

|  한글 고딕체                |   ESC   G      |    27,   71   |

|  한글 명조체                |   ESC   g      |    27,  103   |

|  한글 세로문자              |   ESC   j      |    27,  106   |

|  한글 가로문자              |   ESC   k      |    27,  107   |

|  워드프로세서 문자 모드     |  ESC    W      |    27,   87   |

|  워드프로세서 문자 해제     |  ESC    w      |    27,  119   |

|  영문과 한글크기 1:1 모드   |   ESC   I      |    27,   73   |

|  영문화 한글 1:1 모드 해제  |   ESC   i      |    27,  105   |

|  한글 축소                  |   ESC   S      |    27,   83   |

|  한글 축소 해제             |   ESC   s      |    27,  115   |

|  가로 2배크기 인자          |   ESC   D      |    27,   68   |

|  가로 2배크기 인자 해제     |   ESC   d      |    27,  100   |

|  역상 문자                  |   ESC   R      |    27,   82   |

|  역상 문자 해제             |   ESC   r      |    27,  114   |

|  밑줄 문자                  |   ESC   U      |    27,   85   |

|  밑줄 문자 해제             |   ESC   u      |    27,  117   |

|  두꺼운 문자                |   ESC   B      |    27,   66   |

|  두꺼운 문자 해제           |   ESC   b      |    27,   98   |

|  음영 문자                  |   ESC   F      |    27,   70   |

|  음영 문자 해제             |   ESC   f      |    27,  102   |

|  세로 2배문자 윗부분인쇄    |  ESC    [      |    27,   91   |

|  세로 2배문자 아랫부분인쇄  |  ESC    ]      |    27,   93   |

|  위로 2배 확대              |   ESC   6      |    27,   54   |

|  아래로 2배 확대            |   ESC   7      |    27,   55   |

|  세로 2배 문자 해제         |   ESC   c      |    27,   99   |

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

프린터에 있어서 까다로운 점은 프린터마다 제어코드가 다

르다는 점이다.  글자를 확대·축소·강조·글자체  등을 지정할

때 코드값이 프린터를 생산한 회사나  기종에 따라 다르다. 흔히

쓰이는 EPSON 프린터의 경우 많이  사용되는 코드값은 다음과 같

다.

3. 스트링 처리 (ctype.h)

(1) 문자검색 매크로

isalpha (문자)  : 알파벳이냐

isalnum (문자)  : 알파벳이나 숫자냐

isascii (문자)  : 아스키문자냐

iscntrl (문자)  : 제어문자냐

isdigit (문자)  : 숫자냐

islower (문자)  : 소문자냐

isupper (문자)  : 대문자냐

isspace (문자)  : 공백문자(space, tab, new line)냐

ispunct (문자)  : 구둣점이냐

isxdigit(문자)  : 16진 숫자냐

isprint (문자)  : 인쇄가능한 문자냐

isgraph (문자)  : 스페이스를 제외한  인쇄가능한 문자냐

(2) 문자변환 함수

toupper (문자)  : 소문자를 대문자로 변환

tolower (문자)  : 대문자를 소문자로 변환

4. 수치계산 함수 (math.h)

abs(x)    :  절대값 계산

acos(x)   :  아크 코사인값 계산

asin(x)   :  아크 사인값 계산

atan(x)   :  아크 탄젠트값 계산

cos(x)    :  코사인값 계산

sin(x)    :  사인값 계산

tan(x)    :  탄젠트값 계산

exp(x)    :  지수값 계산

log(x)    :  자연로그 계산

log10(x)  :  상용로그 계산

pow(x,y)  :  x 의 y 승 계산

pow10(x)  :  10 의 x 승 계산

sqrt(x)   :  x 의 제곱근값 계산

srand(seed) :  초기값을 seed 로 한 난수발생

/************************************************************

*                                                          *

*                      DEL_SPC.C                           *

*                                                          *

*                MADE BY HONG SAMYULL                      *

*                                                          *

************************************************************/

#include <stdio.h>

#include <string.h>                      /* strlen()  함수 정의 */

#include <ctype.h>                       /* isascii() 함수 정의 */

main()

{

int i, ret;

char line[81];

printf("문장을 입력하시요. 문장  마지막에는 SPACE가 있어서는 \

안됩니다.\n\n");

gets(line);

i = strlen(line);

ret = del_space(i,line);

if(ret)

printf("\n\n한글이므로 SPACE를 모두 제거했습니다.");

else

printf("\n\n한글이 아니므로 제일 앞부분만 SPACE를 \

제거했습니다.");

printf("\n\n%-80s\n",line);

getch();

}

del_space(char len, char *buf)

/*  한글이면  중간공백을  없애는 함수 */

{

int buff_len;

char i, j, k, sw=0;

buff_len = strlen(buf);

for( i=0; i<len; i++ ) {

for(j = 0; j < len; j++) {

if( buf[j] == 0x20 ) {

buff_len--;

for(k = j; k < buff_len; k++)

buf[k] = buf[k+1];

} else

break;

}

}

len = buff_len;

if( !(isascii(buf[0])) ) {

sw = 1;

for(i=0;i<len;i++) {

for(j = 0; j < len; j++) {

if( buf[j] == 0x20 ) {

buff_len--;

for(k = j; k < buff_len; k++)

buf[k] = buf[k+1];

}

}

}

}

buf[buff_len] = 0x00;

return (sw);

}

/*************************************

*  UPPER.C    Made by Samyull Hong  *

*************************************/

#include <stdio.h>

main(int argc,char *argv[])

{

FILE *in;

FILE *out;

int ch, c, pre = 0;

printf(  "Upper spell...  Copyright (c) 1991  by  Hong, samyull");

if(argc != 3) {

printf("\n\nUsage : upper <source-file> <target-file>\n");

exit();

}

if(!(strcmp(argv[1],argv[2]))) {

printf("\n\nTarget file name error !!!\n");

exit();

}

if ((in = fopen(argv[1],"r")) == NULL) {

printf("\n\nCannot open %s\n",strupr(argv[1]));

exit();

}

if ((out = fopen(argv[2],"r")) != NULL) {

printf("\n\n%s already exist ....  Overwrite ? (y/n) ",strupr(argv[2]));       scanf("%s",&c);

if ( !(c == 89 || c == 121)) {

fclose(out);

exit();

}

}

printf("\nReading & Writing ....\n");

out = fopen(argv[2],"w");

while ((ch = fgetc(in)) != EOF) {

if(ferror(in)) {

printf("\n\nError reading %s\n",strupr(argv[1]));

exit();

}

if(ch > 96 && ch < 123 && pre < 128)  c = ch - 0x20;

else                                  c = ch;

fputc(c,out);

if(ferror(out)) {

printf("\n\nError writing %s\n",strupr(argv[2]));

exit();

}

pre = ch;

}

fclose(in);   fclose(out);

printf("\nSuccessfully converted !!!\n");

}

5. 그래픽 및 소리 함수 (graphics.h)

(1) 그래픽 시스템 초기화 함수

initgraph(&graphdriver, &graphmode, "");

graphdriver 및 graphmode

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

| 그래픽카드 | graphdriver |                        |

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

| HGC        | HERCMONO    | HERCMONOHI (720 X 348) |

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

| HGC/EGA    | DETECT      |       없음             |

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

| VGA        |  VGA        |  VGAHI  (640 X  480)   |

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

(2) 그래픽 시스템 종료 함수

closegraph();

(3) 선 긋기 함수

line(x1,  y1,  x2, y2)  :  좌표  (x1,y1) 에서  좌표 (x2,y2) 까지

lineto(x, y) : 현위치부터 좌표 (x,y) 까지

linerel(rx, ry)  : 현위치부터 x방향으로 rx  만큼, y방향으로 ry

만큼 떨어진 좌표까지

(4) 좌표 얻기 함수

getx() : 현재의 x 좌표값

gety() : 현재의 y 좌표값

getmaxx() : 현화면의 x 좌표의 최대값

getmaxy() : 현화면의 y 좌표의 최대값

(5) 현재위치 이동 함수

moveto(x, y) : 절대좌표 (x,y) 로

moverel(rx, ry)  : x 방향으로  rx 만큼,  y 방향으로 ry 만큼

cleardevice() : 그래픽 스크린  지우고 좌표 (0,0) 으로

(6) BOX 그리기 함수

rectangle(left, top,  right, bottom) :  사각형을 지정좌표에 따

라 그린다.  (왼쪽, 윗쪽,  오른쪽, 아랫쪽  좌표순)

bar(left, top,  right, bottom) :  사각형을 지정좌표에 따라 그

린 후,  setfillstyle() 에  의해 지정된  패턴과 색으로 내부

를 칠한다.

bar3d(left, top, right, bottom, depth, topflag) : 3차원 형태

의 사각형을  그린 뒤 내부를 칠한다.  depth는 3차원의 두께

이며 (right -  left) / 4 등의  방식으로 계산된다. topflag

는 두개 이상의 3차원 사각형을  겹쳐 그릴 때 사용하는 것

으로 0이면 겹치지 않게, 1이면 겹쳐서 그린다.

(7) 원 그리기 함수

circle(x, y, r) : 중심좌표는  (x,y) 이고 반지름은 r 인 원

(9) 색과 무늬 관련 함수

setcolor(color) : 전경색 지정

setbkcolor(color) : 배경색 지정

getpixel(x, y) : 좌표 (x,y) 의 색 번호를 얻는다.

putpixel(x, y, color)  : 좌표 (x,y) 에  지정 색으로 점을 출력

color 지정

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

|번호|    명   칭       |색상|번호|      명    칭     |색상|

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

|  0 |   BLACK          |검정|  8 |  DARKGRAY         |회색|

|  1 |   BLUE           |파랑|  9 |  LIGHTBLUE        |하늘|

|  2 |   GREEN          |녹색| 10 |  LIGHTGREEN       |연두|

|  3 |   CYAN           |남색| 11 |  LIGHTCYAN        |파랑|

|  4 |   RED            |적색| 12 |  LIGHTRED         |    |

|  5 |   MAGENTA        |분홍| 13 |  LIGHTMAGENTA     |    |

|  6 |   BROWN          |밤색| 14 |  YELLOW           |노랑|

|  7 |   LIGHT GRAY     |은색| 15 |  WHITE            |흰색|

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

floodfill(x, y, border) :  (x,y) 좌표가 도형의 내부이냐 외부

이냐에 따라 내부와 외부를 칠한다.

setfillstyle(pattern, color) : 무늬와 색을 설정

(10) 그래픽화면 문자출력 관련 함수

outtext(문자열)  : 현재위치에  지정문자열  출력한후 다음위치로

현재위치 이동

outtextxy(x, y, 문자열)  : 좌표 (x, y)  에서부터 지정문자열을

출력하나 현재위치는 변함이 없다.

settextstyle(문자형, 출력방향,  크기) :  문자형, 출력방향, 크

기를 미리 설정

문 자 형 : DEFAULT_FONT    (0)

TRIPLEX_FONT    (1)

SMALL_FONT      (2)

SANS_SERIF_FONT (3)

GOTHIC_FONT     (4)

출력방향 : HORIZ_DIR       (0)

VERT_DIR        (1)

문자크기 : 0 / 보통크기

1 / 제일 작은 크기

2 / 조금 작은 크기

3  / 보통크기로서  가장  적당한 크기

4 - 9 / 수치가 클수록 커진다.

setusercharsize(multx, divx, multy,  divy) : 폰트의 크기를 지

정하는 함수로서  폭의 경우 multx :  divx 의 비로, 높이

의 경우 multy  : divy 의 비로  결정된다. 예를 들어  디

폴트 폭의  2배, 높이의 1.5배로  하려면 다음과 같다.

( multx = 2;  divx =  1;  multy = 3;  divx = 2; )

(11) VIEW PORT 함수

view port란 텍스트화면에서의 윈도우  개념과 같은 것으로 화면

상의 임의의 사각형 영역을 말한다.

setviewport(left, top, right,  bottom, flag) : 뷰포트 설정함

수로 view port를 해제하려면  전체 화면을 뷰포트로 설정하

면 되며,  flag 값이 0이면 뷰포트를  벗어나는 그래픽이  뷰

포트를 벗어날 수 있지만 flag  값이 1이면 벗어나는 그래픽

은 표시되지 않는다.

clearviewport() :  현재 설정된 뷰포트  내부를 clear하고  뷰포

트내의 (0, 0) 좌표로 현재 위치를 옳겨놓는다.

(12) 이미지 이동 복사를 위한 함수

imagesize(left, top,  right, bottom) :  이미지를 배열에 저장하

기 위해 필요한 크기(bytes)를 계산해 주는 함수

getimage(left, top, right, bottom,  array) : 사각형내부의 이

미지를 배열 array 에 저장하는 함수

putimage(left, top, array, para)  : 배열 array에 기억되어  있

는 이미지를 (left, top)  좌표에 출력하는 함수로서 para 는

이미지의 동작종류 parameter 를 나타낸다.

parameter 구분

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

| 숫자 |  명 칭   |  기  능  |

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

|   0  | COPY_PUT | MOV 기능 |

|   1  | XOR_PUT  | XOR 기능 |

|   2  | OR_PUT   | OR  기능 |

|   3  | AND_PUT  | AND 기능 |

|   4  | NOT_PUT  | NOT 기능 |

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

/* tot_gr.c        MADE BY HONG SAMYULL */

#include <graphics.h>

#include <stdlib.h>

#include <dos.h>

main()

{

int g_driver=DETECT, g_mode, i, x, y;

initgraph(&g_driver,&g_mode,"");

setcolor(12);

rand();

for(i = 0; i < 150; i++) {

x = random(720);

y = random(348);

rectangle(x-20,y-20,x+20,y+20);

delay(10);

}

getch();

cleardevice();

setcolor(7);

settextstyle(4,0,1);

setusercharsize(2,1,3,1);

outtextxy(50,100,"Jung Ang Computer.");

getch();

cleardevice();

for(i = 0; i < 150; i++) {

x = random(720);

y = random(348);

circle(x,y,40);

delay(10);

}

getch();

부록 1  :  아스키 코드표

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

| Decimal | Octal  | Hexa  | Character |  Mean                       |

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

|     0   |   000  |   00  |    ^1     |  NULL                       |

|     1   |   001  |   01  |    ^A     |  start of header            |

|     2   |   002  |   02  |    ^B     |  start of text              |

|     3   |   003  |   03  |    ^C     |  end of text                |

|     4   |   004  |   04  |    ^D     |  end of transmission        |

|     5   |   005  |   05  |    ^E     |  enquiry                    |

|     6   |   006  |   06  |    ^F     |  acknowledge                |

|     7   |   007  |   07  |    ^G     |  beep                       |

|     8   |   010  |   08  |    ^H     |  backspace                  |

|     9   |   011  |   09  |    ^I     |  horizontal tab             |

|    10   |   012  |   0A  |    ^J     |  line feed                  |

|    11   |   013  |   0B  |    ^K     |  vertical tab               |

|    12   |   014  |   0C  |    ^L     |  form feed                  |

|    13   |   015  |   0D  |    ^M     |  carriage return            |

|    14   |   016  |   0E  |    ^N     |  shift out                  |

|    15   |   017  |   0F  |    ^O     |  shift in                   |

|    16   |   020  |   10  |    ^P     |  data link escape           |

|    17   |   021  |   11  |    ^Q     |  device control #1 (XON)    |

|    18   |   022  |   12  |    ^R     |  device control #2          |

|    19   |   023  |   13  |    ^S     |  device control #3 (XOFF)   |

|    20   |   024  |   14  |    ^T     |  device control #4          |

|    21   |   025  |   15  |    ^U     |  negative acknowledge       |

|    22   |   026  |   16  |    ^V     |  syschronous idle           |

|    23   |   027  |   17  |    ^W     |  end transmission block     |

|    24   |   030  |   18  |    ^X     |  cancel                     |

|    25   |   031  |   19  |    ^Y     |  end of medium              |

|    26   |   032  |   1A  |    ^Z     |  substitute                 |

|    27   |   033  |   1B  |    ESC    |  escape                     |

|    28   |   034  |   1C  |    ^<     |  file seperator             |

|    29   |   035  |   1D  |    ^'     |  group seperator            |

|    30   |   036  |   1E  |    ^=     |  record seperator           |

|    31   |   037  |   1F  |    ^-     |  unit seperator             |

|    32   |   040  |   20  |    SP     |  space                      |

|    33   |   041  |   21  |     !     |  exclamation mark           |

|    34   |   042  |   22  |     "     |  double quote               |

|    35   |   043  |   23  |     #     |  hash mark                  |

|    36   |   044  |   24  |     $     |  dollar sign                |

|    37   |   045  |   25  |     %     |  percent sign               |

|    38   |   046  |   26  |     &     |  ampersand sign             |

|    39   |   047  |   27  |     '     |  single quote or apostrophe |

|    40   |   050  |   28  |     (     |  left parenthesis           |

|    41   |   051  |   29  |     )     |  right parenthesis          |

|    42   |   052  |   2A  |     *     |  asterisk                   |

|    43   |   053  |   2B  |     +     |  plus sign                  |

|    44   |   054  |   2C  |     ,     |  comma                      |

|    45   |   055  |   2D  |     -     |  minus sign or dash         |

|    46   |   056  |   2E  |     .     |  period or decimal point    |

|    47   |   057  |   2F  |     /     |  slash                      |

|    48   |   060  |   30  |     0     |  numeric (down)             |

|    49   |   061  |   31  |     1     |                             |

|    50   |   062  |   32  |     2     |                             |

|    51   |   063  |   33  |     3     |                             |

|    52   |   064  |   34  |     4     |                             |

|    53   |   065  |   35  |     5     |                             |

|    54   |   066  |   36  |     6     |                             |

|    55   |   067  |   37  |     7     |                             |

|    56   |   070  |   38  |     8     |                             |

|    57   |   071  |   39  |     9     |                             |

|    58   |   072  |   3A  |     :     |  colon                      |

|    59   |   073  |   3B  |     ;     |  semi-colon                 |

|    60   |   074  |   3C  |     <     |  less than sign             |

|    61   |   075  |   3D  |     =     |  equal sign                 |

|    62   |   076  |   3E  |     >     |  greater than sign          |

|    63   |   077  |   3F  |     ?     |  question mark              |

|    64   |   100  |   40  |     @     |  atsign                     |

|    65   |   101  |   41  |     A     |  upper case alphabet (down) |

|    66   |   102  |   42  |     B     |                             |

|    67   |   103  |   43  |     C     |                             |

|    68   |   104  |   44  |     D     |                             |

|    69   |   105  |   45  |     E     |                             |

|    70   |   106  |   46  |     F     |                             |

|    71   |   107  |   47  |     G     |                             |

|    72   |   110  |   48  |     H     |                             |

|    73   |   111  |   49  |     I     |                             |

|    74   |   112  |   4A  |     J     |                             |

|    75   |   113  |   4B  |     K     |                             |

|    76   |   114  |   4C  |     L     |                             |

|    77   |   115  |   4D  |     M     |                             |

|    78   |   116  |   4E  |     N     |                             |

|    79   |   117  |   4F  |     O     |                             |

|    80   |   120  |   50  |     P     |                             |

|    81   |   121  |   51  |     Q     |                             |

|    82   |   122  |   52  |     R     |                             |

|    83   |   123  |   53  |     S     |                             |

|    84   |   124  |   54  |     T     |                             |

|    85   |   125  |   55  |     U     |                             |

|    86   |   126  |   56  |     V     |                             |

|    87   |   127  |   57  |     W     |                             |

|    88   |   130  |   58  |     X     |                             |

|    89   |   131  |   59  |     Y     |                             |

|    90   |   132  |   5A  |     Z     |                             |

|    91   |   133  |   5B  |     [     |  left square bracket        |

|    92   |   134  |   5C  |     \     |  backslash                  |

|    93   |   135  |   5D  |     ]     |  right square bracket       |

|    94   |   136  |   5E  |     ^     |  carat                      |

|    95   |   137  |   5F  |     _     |  underscore                 |

|    96   |   140  |   60  |     `     |  back quote                 |

|    97   |   141  |   61  |     a     |  lower case alphabet (down) |

|    98   |   142  |   62  |     b     |                             |

|    99   |   143  |   63  |     c     |                             |

|   100   |   144  |   64  |     d     |                             |

|   101   |   145  |   65  |     e     |                             |

|   102   |   146  |   66  |     f     |                             |

|   103   |   147  |   67  |     g     |                             |

|   104   |   150  |   68  |     h     |                             |

|   105   |   151  |   69  |     i     |                             |

|   106   |   152  |   6A  |     j     |                             |

|   107   |   153  |   6B  |     k     |                             |

|   108   |   154  |   6C  |     l     |                             |

|   109   |   155  |   6D  |     m     |                             |

|   110   |   156  |   6E  |     n     |                             |

|   111   |   157  |   6F  |     o     |                             |

|   112   |   160  |   70  |     p     |                             |

|   113   |   161  |   71  |     q     |                             |

|   114   |   162  |   72  |     r     |                             |

|   115   |   163  |   73  |     s     |                             |

|   116   |   164  |   74  |     t     |                             |

|   117   |   165  |   75  |     u     |                             |

|   118   |   166  |   76  |     v     |                             |

|   119   |   167  |   77  |     w     |                             |

|   120   |   170  |   78  |     x     |                             |

|   121   |   171  |   79  |     y     |                             |

|   122   |   172  |   7A  |     z     |                             |

|   123   |   173  |   7B  |     {     |  left curly brace           |

|   124   |   174  |   7C  |     |     |  vertical bar               |

|   125   |   175  |   7D  |     }     |  right curly brace          |

|   126   |   176  |   7E  |     ~     |  tilde                      |

|   127   |   177  |   7F  |    DEL    |  delete or rubout           |

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