자료구조& 알고리즘 - clickseo.com · 우선순위와결합성 ... max Memory Mozilla...

Preview:

Citation preview

자료구조자료구조 && 알고리즘알고리즘자료구조자료구조 && 알고리즘알고리즘자료구조자료구조 & & 알고리즘알고리즘자료구조자료구조 & & 알고리즘알고리즘

C C 프로그래밍프로그래밍 기법기법C C 프로그래밍프로그래밍 기법기법

Seo, DooSeo, Doo--okok

clickseo@gmail.comclickseo@gmail.comhttp://www.Clickseo.comhttp://www.Clickseo.com

목목 차차

C C 언어언어 기본기본 문법문법

제어흐름제어흐름

포인터의포인터의 이해이해

함수함수, , 배열배열, , 문자열문자열

유도형유도형 구조체구조체 공용체공용체 열거형열거형유도형유도형 : : 구조체구조체, , 공용체공용체, , 열거형열거형

전처리전처리전처리전처리

포인터포인터 응용응용

2

C C 언어언어 기본기본 문법문법

변수 (variable)

프로그램에서 사용되는 자료를 저장하기 위한 공간” “프로그램에서 사용되는 자료를 저장하기 위한 공간”

할당 받은 메모리의 주소 대신 부르는 이름

• 사용자가 변수 이름을 만들어 저장하기 위한 자료의 형태를 지정하면 컴파일러는• 사용자가 변수 이름을 만들어 저장하기 위한 자료의 형태를 지정하면 컴파일러는

컴퓨터의 메인 메모리에 주소 값과 연결시켜준다.

프로그램 실행 중에 값 변경 가능하다.

사용되기 이전에 선언되어야 한다.…

‘A’1000

2000ch

char ch;int i;

A1001

1002100

2001

2002i

;

1003

2003

프로그램 메모리

3

프로그램 메모리

C C 언어언어 기본기본 문법문법 (cont(cont’’d)d)

상수 (constant)

수 프로그램 수행 중에 변하지 못하는 자료 값

실제 값 상수 실제 값 상수

• 정수형 상수 (integer constant)

• 실수형 상수 (real constant)

• 문자형 상수 (character constant)

• 문자열 상수 (string constant)

기억 장소를 갖는 상수

• 선언하는 것은 변수 선언과 똑같지만 앞에 const 키워드를 써야 하고 반드시

초기값이 있어야 한다는 것이 다르다.

4

C C 언어언어 기본기본 문법문법 (cont(cont’’d)d)

h t i d h t

문자형 char, unsigned char기본형

short, unsigned short

int, unsigned intlong, unsigned long

정수형

long long, unsigned long long

실수형 float, double, long double

형 없음

구조를 갖는 형 배열형

void

[ ]구조를 갖는 형 배열형

구조체

공용체

[ ]

struct

union

열거형

포인터형

공용체 union

enum

*

5

포인터형 *

C C 언어언어 기본기본 문법문법 (cont(cont’’d)d)

콘솔 입출력 함수

함수의 선언 기 능 헤더 파일

int getchar(void); 한 문자를 읽어 들인다.

int putchar(int ch); 한 문자를 출력한다.

stdio.hchar *gets(char *str); 문자열을 읽어 들인다.

int puts(char *str); 문자열을 출력한다.

int printf(char *control string ); 문자열을 서식을 갖춰 출력int printf(char *control-string, ...); 문자열을 서식을 갖춰 출력

int scanf(char *control-string, ...); 문자열을 서식을 갖춰 입력

int getch(void);입력 화면에 입력 문자는 표시 안 된다

( )g ( );

(비표준 문자 입력 함수).

conio hint putch(void);

putchar()와 달리 ‘\n’을 CR/LF의 조합으로 바꾸지

않는다(비표준 문자 출력 함수).

conio.hint getche(void);

입력 문자가 화면에 출력(에코)된다

(비표준 문자 입력 함수)

int kbhit(void);키의 눌림 여부를 조사한다. 눌린 경우 0이 아닌 수를

6

int kbhit(void);반환한다(비표준 키 입력 함수).

C C 언어언어 기본기본 문법문법 (cont(cont’’d)d)

우선 순위와 결합성

기능별 분류 연산자 결합성 우선순위

일차연산자 ( ) [ ] -> . 1

단항 연산자 + - ++ -- ! ~ * & sizeof (datatype) 2

산술연산자* / % 3+ - 4

시프트 연산자 << >> 5비교 연산자 < <= > >= 6등가 연산자 == != 7

비트논리연산자

& 8^ 9비트논리연산자 ^ 9| 10

논리 연산자&& 11|| 12|| 12

조건 연산자 ? : 13

대입 연산자= += -= *= /= %= >>= <<= &= ^= |=

14

7

|콤마 연산자 , 15

제어흐름제어흐름

프로그램 예제 : if…else 문과 삼원 조건식

#i l d < tdi h>#include <stdio.h>

int main(void){{

int a, x = 3, y = 4;

if(x < y) a = x;

elsea = y;

a = (x < y) ? x : y;

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

return 0;;}

8

제어흐름제어흐름 (cont(cont’’d)d)

프로그램 예제 : switch 문 사용 예제

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

int main (void){

int score, temp;char grade;

printf("0 ~ 100 사이의 점수를 입력하시오 : ");scanf ("%d", &score);

temp = score / 10;switch (temp){

case 10:case 9 : grade = 'A'; break;case 8 : grade = 'B'; break;case 7 : grade = 'C'; break;case 6 : grade = 'D'; break;default : grade = 'F';default : grade = 'F';

}printf(“\n학점 : %c \n", grade);

return 0;

9

}

제어흐름제어흐름 (cont(cont’’d)d)

프로그램 예제 : else-if 문 사용 예제

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

int main (void){

int score;char grade;

printf("0 ~ 100 사이의 점수를 입력하시오 : ");printf( 0 100 사이의 점수를 입력하시 );scanf ("%d", &score);

if (score >= 90) grade = 'A';l if ( > 80) d 'B'else if (score >= 80) grade = 'B';

else if (score >= 70) grade = 'C';else if (score >= 60) grade = 'D';else grade = 'F';

printf(“\n학점 : %c \n", grade);

return 0;

10

return 0;}

제어흐름제어흐름 (cont(cont’’d)d)

for 문과 while 문

#include <stdio.h>

int main(void)

#include <stdio.h>

int main(void){

int i;i = 0;

( ){

int i;초기문

while ( i < 10 ){

for(i = 0; i < 10; i++)printf(“Hello World!! ₩n”);조건문

{printf(“Hello World!! ₩n”);i++;

}

return 0;}

증감문}

return 0;}

}

11

}

제어흐름제어흐름 (cont(cont’’d)d)

do…while 문

수행 후 검사 루프 수행 후 검사 루프

세미콜론(;)으로 끝난다.

do

(실행할 명령문)

do

{

while (조건식); …

(실행할 명령문)

}

while (조건식);

12

제어흐름제어흐름 (cont(cont’’d)d)

점프문 (Jump Statement)

goto문은 구조적 프로그래밍에 적합하지 않다.

점프문

break continue return goto

13

포인터의포인터의 이해이해

포인터를 통한 변수 접근

// 변수와 포인터 변수 선언

int a; 0x12FF70 10

p a

int *p;

// 변수와 포인터 변수의 초기화

0x12FF78 0x12FF70

// 변수와 포인터 변수의 초기화

a = 10; p = &a;

*p a 100 // 변수 a 의 데이터 값

P &a 0x12FF70 // 변수 a 의 주소

a = a + 1; a++;*p = *p + 1; (*p)++;

14

p = p + 1; ( p)++;

포인터의포인터의 이해이해 (cont(cont’’d)d)

프로그램 예제 : 변수변경 -- 흥미로운 포인터

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

int main (void){

int a, b, c;int *pa, *pb, *pc;

a = 6;b = 2;

pa = &b;pb = pa;pc = &c;

pa = &a;*pb = 8;

*pc = *pa;*pc = a + *pb + *&c;*pc = a + *pb + *&c;

printf("a : %d, b : %d, c : %d \n", a, b, c); printf("*pa : %d, *pb : %d, *pc : %d \n", *pa, *pb, *pc);

15

return 0;}

포인터의포인터의 이해이해

void형 포인터란?

수 void형 포인터는 어느 것이든 가리킬 수 있는 포인터이다.

void형 포인터

“현재 가리키고 있는 대상체의 크기가 정해져 있지 않은 포인터”

void형 포인터

h

void *p;

char

int

p

int

double

16

함함 수수

여러 개의 함수로 프로그램 작성

#include <stdio.h>

int ADD(int, int);int ADD(int a int b)

void main(void){

i t b

int ADD(int a, int b)

{

int sum;int a, b, sum;

scanf("%d %d", &a, &b); sum = a + b;

sum = ADD(a, b);

printf("%d + %d = %d₩n" a b sum);

return sum;

}printf( %d + %d = %d₩n , a, b, sum);

return 0;}

17

}

함함 수수 (cont(cont’’d)d)

프로그램 예제 : 값에 의한 호출 -- swap 함수

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

void SWAP(int, int);

int main(void){

int a = 10, b = 20;

printf("호출 전 : a = %d, b = %d \n", a, b);

SWAP(a, b);

printf("호출 후 : a = %d, b = %d \n", a, b);???temp

return 0;}

void SWAP (int a, int b){

20

10

SWAP 함수

스택 영역

a

b

{int temp;

temp = a;a = b;

20

10

main 함수

스택 영역a

b

a

18

b = temp;}

10a

함함 수수 (cont(cont’’d)d)

프로그램 예제 : 참조에 의한 호출 -- swap 함수

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

void SWAP(int *, int *);

int main(void){

int a = 10, b = 20;

printf("호출 전 : a = %d, b = %d \n", a, b);

SWAP(&a, &b);

printf("호출 후 : a = %d, b = %d \n", a, b); ???temp

return 0;}

void SWAP (int *pa, int *pb){

0x0012ff74

0x0012FF70

SWAP 함수

스택 영역

pa

pb

{int temp;

temp = *pa;*pa = *pb;

20

10

main 함수

스택 영역a

b

pa

19

p p*pb = temp;

}

10a

함함 수수 (cont(cont’’d)d)

프로세스와 프로그램stack

max

MemoryMemory

Mozilla Firefox

stack

Mozilla Firefox

Visual Studio

heap

data

CPU

Visual Studio

한글 2007

text 0

한글 2007

프로세스 : 운영체제에서 프로세스는 “실행중인 프로그램”

프로그램 : 컴퓨터를 실행시키기 위해 차례대로 작성된 “명령어저장장치

20집합”

프로그램 : 컴퓨터를 실행시키기 위해 차례대로 작성된 명령어

집합”

함함 수수 (cont(cont’’d)d)

기억 장소 활용에 따른 변수의 종류

변수의 종류 예약어 생존기간 유효범위 초기화 초기화 값

자동 변수 ( t ) 일시적 지역적 수행 시 임의 값자동 변수 (auto) 일시적 지역적 수행 시 임의 값

레지스터 변수 register 일시적 지역적 수행 시 임의 값

(내부) 정적 변수 static 영구적 지역적 컴파일 시 0

(외부) 정적 변수 static 영구적 전역적 컴파일 시 0

외부변수 (extern) 영구적 전역적 컴파일 시 0

21

배배 열열

arr[0]

배열 첨자int arr[10];

10arr[0]

arr[1]

[2]

[ ];10

20

arr[2]

arr[3]

[ ]

30

40

arr[4]

arr[5]배열 원소들...

50

60

arr[6]

arr[7]

70

80

arr[8]

arr[9]배열 이름

90

100

22

arr

배배 열열 (cont(cont’’d)d)

1차원 배열과 포인터

포인터 연산의 사용

• 다른 포인터에 할당

• 간접연산자의 사용 : a 가 배열 이름이고 n 이 상수일 때,

p = arr + 5;

,

다음 2개의 표현은 완전히 동일하다.

arr [n] == * ( arr + n )

10

20

30

arr[0] == *(arr+0)

arr[1] == *(arr+1)

arr[2] == *(arr+2)

arr + 0 == &arr[0]

arr + 1 == &arr[1]

arr + 2 == &arr[2]30

40

50

arr[2] == (arr+2)arr[3] == *(arr+3)

arr[4] == *(arr+4)

arr + 2 == &arr[2]arr + 3 == &arr[3]

arr + 4 == &arr[4]

23

arr

배배 열열 (cont(cont’’d)d)

개별 원소 전달 #include <stdio.h>

void PRINT (int);void PRINT (int);

int main (void)

{

i t i

10

20

arr[0]

a [1]

arr

int i;

int arr[5] = {10, 20, 30, 40, 50};

20

30

40

arr[1]

arr[2]arr[3]

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

PRINT (arr[i]);

return 0;

50arr[4]

}

void PRINT (int a){

a{

printf(“%3d”, a);return;

}

“함수가 요구하는 자료 형과 일치하는 형을

값-인수(value parameter)로 전달된다 ”

24

}값 인수(value parameter)로 전달된다.

배배 열열 (cont(cont’’d)d)

전체 배열 전달 #include <stdio.h>

void PRINT (int x[]);void PRINT (int x[]);

int main(void){

int arr[5] {10 20 30 40 50}

10

20

arr[0]

arr[1]

arr

“배열 이름은

첫 번째 원소의 시작주소”

int arr[5] = {10, 20, 30, 40, 50};

PRINT (arr);

t 0

20

30

40

arr[1]

arr[2]arr[3]

return 0;}

void PRINT (int p[]){

50arr[4]

{int i;

for (i = 0; i < 5; i++)i tf(“%3d” [i])

함수정의의 헤더부분의 pprintf(“%3d”, p[i]);

printf(“₩n”);

return;

다음 두 문장은 같다.

int p[]; int *p;

25

}

문자열문자열

문자와 문자열 상수

문자 상수 : 문자 상수를 쓰려면 작은 따옴표(‘ ’) 를 사용 문자 상수 : 문자 상수를 쓰려면 작은 따옴표(‘ ’) 를 사용

문자열 상수 : 문자열 상수를 쓰려면 큰 따옴표(“ ”) 를 사용자열 상수 자 상수 려 큰 따옴표( ) 사용

• 문자열은 데이터 자체는 하나지만 그 뒤에 구분자를 쓸 공간이 필요하다.

‘A’ “A”

‘A’ ‘A’ ‘\0’

문자열 “H”(2 bytes)

문자 ‘H’(1 bytes) (2 bytes)(1 bytes)

26

문자열과문자열과 포인터포인터 (cont(cont’’d)d)

문자열 초기화

포인터형 변수에 문자열의 시작 주소를 할당 포인터형 변수에 문자열의 시작 주소를 할당

• 문자열을 생성한 후, 포인터형 변수 p 에 주소를 저장

char *p = “Click Seo”;

“Click Seo”Click SeoC l i c k S e o \0

p

27

문자열문자열 입출력입출력 함수함수

문자열 입력 함수 : gets, fgets 입력 스트림에서 한 줄단위로 읽어 들여와 널 문자로 끝나는 문자열을 입력 스트림에서 한 줄단위로 읽어 들여와 널 문자로 끝나는 문자열을

생성한다.

#include <stdio.h>

char *gets (char *str);char *fgets (char *str, int size, FILE *fp);

호출 성공 : str의 주소를 반환

호출 실패 : NULL 을 반환

문자열 출력 함수 : puts, fputs 메모리에서 널 문자(‘\0)로 끝나는 문자열을 가져와 출력 스트림에

char fgets (char str, int size, FILE fp);

메모리에서 널 문자( \0)로 끝나는 문자열을 가져와 출력 스트림에

출력 한다.

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

int puts (const char *str);int fputs (const char *str FILE *fp);

호출 성공 : 음수가 아닌 정수를 반환

호출 실패 : EOF 를 반환

28

int fputs (const char str, FILE fp);

문자열문자열 조작조작 함수함수

문자열 조작 함수

문자열 라이브러리(<string.h>)에 존재한다.

• str 이라는 접두사로 시작한다.

• NULL : 널 포인터 상수• NULL : 널 포인터 상수

• size_t : unsigned integer 타입

str… (parameters)

문자열 길이 : strlen

문자열의 길이를 반환

• 즉, 널 문자를 제외한 문자열의 문자 개수를 반환한다.

#include <string.h>

size_t strlen (const char *str);

29

_ ( );

문자열문자열 조작조작 함수함수 (cont(cont’’d)d)

문자열 복사 : strcpy, strncpy 널 문자를 포함한 원본 문자열을 목적지 문자열로 복사 널 문자를 포함한 원본 문자열을 목적지 문자열로 복사

#include <string.h>

• 원본 문자열이 목적지 문자열보다 길 경우

char *strcpy (char *str1, const char *str2);

원본 문자열이 목적지 문자열보다 길 경우

– 메모리 상 목적지 문자열 뒤에 있는 데이터가 파괴된다.

– 원본 문자열보다 목적지 문자열이 항상 길도록 만들어주어야만 한다.

#include <string.h>

char *strncpy (char *str1, const char *str2, size_t n);py ( , , _ );

30

문자열문자열 조작조작 함수함수 (cont(cont’’d)d)

문자열 비교 : strcmp, strncmp 두 개의 문자열을 다른 문자가 나올 때까지나 끝이 날 때까지 비교한다 두 개의 문자열을 다른 문자가 나올 때까지나 끝이 날 때까지 비교한다.

#include <string.h>

• 두 가지 함수는 모두 비교 결과를 정수로 반환 : “두 문자열이 똑같으면 0을 반환”

int strcmp (const char *str1, const char *str2);int strncmp (const char *str1, const char *str2, size_t size);

두 가지 함수는 모두 비교 결과를 정수로 반환 : 두 문자열이 똑같으면 0을 반환

문자열 연결 : strcat, strncat자 , 한 문자열을 다른 문자열의 끝에 추가하는 기능을 한다.

#include <string.h>

char *strcat (char *str1, const char *str2);char *strncat (char *str1, const char *str2, size_t size);

31

( )

문자열문자열 조작조작 함수함수 (cont(cont’’d)d)

문자열에 있는 문자 또는 문자열 : strchr, strrchr, strstr

#include <string.h>

// 문자가 문자열에 존재하는지 검색하는 함수// 문자가 문자열에 존재하는지 검색하는 함수

char *strchr (const char *str, int ch);char *strrchr (const char *str, int ch);

// 문자열에서 부분 문자열이 존재하는지 검색하는 함수

char *strstr (const char *str, const char *sub_str);

• 주어진 문자열에서 문자(또는 문자열)가 있다면 검색된 위치(주소)를 반환

• 존재하지 않는 문자이면 널 포인터(NULL)를 반환

• strchr : 문자열의 처음 부터 처음으로 일치하는 문자를 검색

• strrchr : 문자열의 끝에서 부터 일치하는 문자를 검색

32

문자열문자열 관련관련 유틸리티유틸리티 함수함수

숫자를 문자열로 변환하는 함수

수 숫 수 수 수 수 정수형 숫자를 2진수, 8진수, 10진수 또는 16진수의 문자열로 변환

• itoa 함수 : integer to ascii

• ltoa 함수 : long to asciig

#include <stdlib.h>

// int 형 숫자를 문자열 str 로 변환

char *itoa (int value, char *str, int radix);

// long 형 숫자를 문자열 str 로 변환

char *ltoa (long value, char *str, int radix);

33

문자열문자열 관련관련 유틸리티유틸리티 함수함수 (cont(cont’’d)d)

문자열을 숫자로 변환하는 함수

숫 ( 수 수 ) 문자열을 숫자로(실수형 또는 정수형) 변환

#include <stdlib.h>

// 문자열 str 을 double 형 실수로 변환

double atof (const char *str);

// 문자열 str 을 int 형 정수로 변환

int atoi (const char *str);

// 문자열 s 을 long 형 정수로 변환

long atol (const char *str);

34

유도형유도형

구조체의 선언 및 초기화

구조체 초기화의 규칙 구조체 초기화의 규칙

• 초기값은 중괄호를 사용하며 콤마로 분리(구조체에 정의된 형식과 일치)

typedef struct _score{

char name[12];int kor, eng, math, tot;float ave;

} SCORE;

SCORE a = {“서두옥”, 70, 80, 90, 240, 80.0};

a.name a.kor a.eng a.math a.tot

“서두옥” 70 80 90 240 80.0aa.ave

35

g

유도형유도형 (cont(cont’’d)d)

구조체 배열 typedef struct _score{{

char name[12];int kor, eng, math, tot;float ave;float ave;

} SCORE;

SCORE arr[3];SCORE arr[3];

“서두옥” 70 80 90 240 80.0

“홍길동” 70 60 80 210 70.0

arr[0]

arr[1]

“서하은” 90 80 100 270 90.0

[ ]

arr[2]

arr

36

arr

유도형유도형 (cont(cont’’d)d)선호하는

중첩 구조체typedef struct{

int year;

선호하는방식

추천하지int year;int month;int day;

} DATE;

typedef struct{

struct

추천하지않는 방식

} ;typedef struct{

int hour;

{int year;int month;i t d int min;

int sec;} TIME;

int day;} date;struct{

typedef struct{

DATE date;

{int hour;int min;int sec;

TIME time;} STAMP;

} time;} STAMP;

STAMP t

37

STAMP stamp;STAMP stamp;

유도형유도형 (cont(cont’’d)d)

간접 표기법 (Indirection notation)

typedef struct _score{

char name[12];

a . name (*p) . name

char name[12];int kor, eng, math, tot;float ave;

} SCORE;} SCORE;

SCORE a;SCORE *p = &a;SCORE *p = &a;

(*p).eng (*p).tot

p“서두옥” 70 80 90 240 80.0a

(*p).name (*p).kor (*p).math (*p).ave

38

a.name a.kor a.eng a.math a.tot a.ave

유도형유도형 (cont(cont’’d)d)

선택 표기법 (Selection notation)

typedef struct _score{

char name[12];

a . name p -> name

char name[12];int kor, eng, math, tot;float ave;

} SCORE;} SCORE;

SCORE a;SCORE *p = &a;SCORE *p = &a;

p->eng p->tot

p“서두옥” 70 80 90 240 80.0a

p->name p->kor p->math p->ave

39

a.name a.kor a.eng a.math a.tot a.ave

유도형유도형 (cont(cont’’d)d)

프로그램 예제 : 개별 멤버 전달 (1/2)

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

typedef struct _score{

char name[12];char name[12];int kor, eng, math, tot;float ave;

} SCORE;

int SUM(int, int, int);float AVE(int, int, int);

int main(void)int main(void){

SCORE a;

printf("학생 성적을 입력 하시오 \n");printf( 학생 성적을 입력 하시오... \n );printf("학생 이름 : "); gets(a.name);printf("국어 점수 : "); scanf("%d", &a.kor);printf("영어 점수 : "); scanf("%d", &a.eng);printf("수학 점수 : "); scanf("%d" &a math);

40

printf( 수학 점수 : ); scanf( %d , &a.math);

유도형유도형 (cont(cont’’d)d)

프로그램 예제 : 개별 멤버 전달 (2/2)

a tot = SUM(a kor a eng a math);a.tot = SUM(a.kor, a.eng, a.math);a.ave = AVE(a.kor, a.eng, a.math);

printf("\n\t ### 입력 정보 ### \n\n");printf("%10s, %3d, %3d, %3d, %5d, %8.2f \n",

a name a kor a eng a math a tot a ave);a.name, a.kor, a.eng, a.math, a.tot, a.ave);

return 0;}

ko e a math tot

“서두옥” 70 80 90 ??? ???

eint SUM(int a, int b, int c){

return a + b + c;}

a.kor a.eng a.math a.tot a.ave

}

float AVE(int a, int b, int c){

return (float)(a + b + c)/3;70 80 90

41

return (float)(a + b + c)/3;} a b c

유도형유도형 (cont(cont’’d)d)

프로그램 예제 : 전체 구조체 전달 (1/2)

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

typedef struct _score{

char name[12];int kor, eng, math, tot;float ave;

} SCORE;} SCORE;

SCORE INPUT(void);void OUTPUT(SCORE);

int main(){

SCORE a;“서두옥” 70 80 90 240 80.00a

a = INPUT();OUTPUT(a);

“서두옥” 70 80 90 240 80.00

temp = a;

temp

42

return 0;}

서두옥 70 80 90 240 80.00temp

유도형유도형 (cont(cont’’d)d)

프로그램 예제 : 전체 구조체 전달 (2/2)

SCORE INPUT(void)SCORE INPUT(void){

SCORE temp;

printf("학생 성적을 입력 하시오... \n\n");printf("학생 이름 : "); gets(temp.name);printf("국어 점수 : "); scanf("%d", &temp.kor);printf("영어 점수 : "); scanf("%d", &temp.eng);printf("수학 점수 : "); scanf("%d", &temp.math);

temp.tot = temp.kor + temp.eng + temp.math;temp.ave = (float)temp.tot / 3;

return temp;p;}

void OUTPUT(SCORE temp){

printf("\n\t ### 입력 정보 ### \n\n");printf("\n\t ### 입력 정보 ### \n\n");printf("%10s, %3d, %3d, %3d, %5d, %8.2f \n",

temp.name, temp.kor, temp.eng, temp.math, temp.tot, temp.ave);

return;

43

}

유도형유도형 (cont(cont’’d)d)

프로그램 예제 : 포인터를 이용한 구조체 전달 (1/2)

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

typedef struct _score{

char name[12];int kor, eng, math, tot;float ave;

} SCORE;} SCORE;

void INPUT(SCORE *);void OUTPUT(SCORE *);

int main(){

SCORE a; “서두옥” 70 80 90 240 80.00a

INPUT(&a);OUTPUT(&a); SCORE *p = &a;

p

44

return 0;}

p

유도형유도형 (cont(cont’’d)d)

프로그램 예제 : 포인터를 이용한 구조체 전달 (2/2)

void INPUT(SCORE *p)void INPUT(SCORE *p){

printf("학생 성적을 입력 하시오... \n\n");printf("학생 이름 : "); gets(p->name);printf("국어 점수 : "); scanf("%d" &p->kor);printf( 국어 점수 : ); scanf( %d , &p->kor);printf("영어 점수 : "); scanf("%d", &p->eng);printf("수학 점수 : "); scanf("%d", &p->math);

p->tot = p->kor + p->eng + p->math;p->tot = p->kor + p->eng + p->math;p->ave = (float)p->tot / 3;

return;}}

void OUTPUT(SCORE *p){

printf("\n\t ### 입력 정보 ### \n\n");printf( \n\t ### 입력 정보 ### \n\n );printf("%10s, %3d, %3d, %3d, %5d, %8.2f \n",

p->name, p->kor, p->eng, p->math, p->tot, p->ave);

return;

45

return;}

유도형유도형 (cont(cont’’d)d)

공용체의 개념

“메모리에서 서로 다른 데이터 형식을 공유할 수 있는 개념” “메모리에서 서로 다른 데이터 형식을 공유할 수 있는 개념”

• 공용체는 구조형과 같은 문법 양식을 따른다.

– struct 키워드 대신 union를 쓰는 것 외에는 모두 똑같다.

용체 참 하는 칙 형을 참 하는 것과 일하다• 공용체를 참조하는 규칙은 구조형을 참조하는 것과 동일하다.

d f itypedef union{

char ch; 1000 1001 1002 1003 1004 1005 1006 1007

int i;double d;

} TYPE;

TYPE temp; temp.ch temp.i temp.d

46

유도형유도형 (cont(cont’’d)d)

열거형의 개념

정수형에 기반 정수형에 기반

• 열거형에서 각 정수 값은 열거 상수라고 불리는 식별자

• 목적 : 정수에 이름을 할당하는 것

// 열거화된 변수형

enum {열거형 상수 } 변수 식별자;enum {열거형 상수, ….} 변수 식별자;

// 열거화된 태그형

enum tag {열거형 상수, …};

enum tag 변수 식별자;

47

전처리전처리

#define preprocessing(macro expansion)

#define MAX_SIZE 1024

#define ADD(a, b) ((a) + (b))

#define MAX_SIZE 1024

#define ADD(a, b) ((a) + (b))

int main(void)

{

int main(void)

{{

char str[MAX_SIZE];

int res;

{

char str[1024];

int res;

res = ADD(10, 20); res = 10 + 20;

return 0;

}

return 0;

}

48

전처리전처리 (cont(cont’’d)d)

조건 컴파일 (conditional compile)

특정 조건을 만족할 경우에 지정한 범위 내의 문장을 컴파일

조건 컴파일 지시자 사용 형식 조건 컴파일 지시자 사용 형식

• { }를 사용하지 않기 때문에 #endif 생략불가

• ++, --, &, *와 기타 복합 연산자 사용 제한

• #ifdef 와 #ifndef는 #if defined(매크로명), #if !defined(매크로명)

#if 상수식1 #ifdef 매크로명 #ifndef 매크로명

실행문장영역1

#elif 상수식2

실행문장영역2

#else

실행문장영역1

#elif 상수식1

실행문장영역2

#else

실행문장영역1

#elif 상수식1

실행문장영역2

#else#else실행문장영역n

#endif

#else실행문장영역n

#endif

#else실행문장영역n

#endif

49

전처리전처리 (cont(cont’’d)d)

분할 컴파일#ifndef MAX_SIZE#define MAX_SIZE 3#endif

#if d f SCORE H#ifndef __SCORE_H_#define __SCORE_H_typedef struct _score{

char name[10];int kor, eng, math, tot;

score.h

, g, , ;float ave;

} SCORE;

extern void INPUT(SCORE *);extern void OUTPUT(SCORE *);#endif

#include <stdio.h>#include "score.h"

#endif

#include <stdio.h>#include "score.h"

int main(){

...}

void INPUT(SCORE *p){ ... }

void OUTPUT(SCORE *p){ ... }

main.c score.c

main.obj score.obj+링킹

50

main.obj score.obj

Clickseo.exe

링킹

포인터포인터 응용응용

포인터에 대한 포인터

0x0012FF70 0x0012FF7C 10

ppa pa a

int a;

0x0012FF64 0x0012FF70 0x0012FF7C

int a;int *pa;int **pa;

a = 10;pa = &a;ppa = &pa;

printf(“%3d”, a);printf(“%3d”, *pa);printf(“%3d”, **ppa);

51

printf( %3d , ppa);

포인터포인터 응용응용 (cont(cont’’d)d)

포인터 배열

#include <stdio.h>

int main() arr[0]

arr 10 a

b{

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

int *arr[3];

arr[1]

arr[2]

20

30

b

c

arr[0] = &a;arr[1] = &b;arr[2] = &c;

printf("a : %d, b : %d, c : %d \n", *arr[0], *arr[1], *arr[2] );

return 0;

}

52

포인터포인터 응용응용 (cont(cont’’d)d)

함수 포인터 “함수를 가리킬 수 있는 포인터” 함수를 가리킬 수 있는 포인터

• 자주 사용되는 함수의 주소를 배열에 저장해 두고 호출하면 속도가 빨라진다.

• 잘 쓰이지는 않지만, 수치해석이나 그래픽 같은 분야에서 사용

#i l d di h#include <stdio.h>

int ADD(int, int);

int main()int main(){

int a = 10, b = 20, sum = 0;int (*p)(int, int) = ADD;sum = p(a, b);

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

return 0;}}

int ADD(int a, int b){

return a + b;

53

}

포인터포인터 응용응용 (cont(cont’’d)d)

2차원 배열 : 1차원 배열의 배열

2차원 배열의 논리적인 구조 2차원 배열의 논리적인 구조

int table[3][5];

table[0]

table

[0] 0 1 2 3 4

10 11 12 13 14

table[0]

table[1]

t bl [2]

[0]

[1]

[2]

table[i][j];20 21 22 23 24table[2] [2]

[0] [1] [2] [3] [4]

54

포인터포인터 응용응용 (cont(cont’’d)d)

2차원 배열과 포인터 table[i][j] == *(*(table+i)+j)

table

0 1 2 3 4

10 11 12 13 14

table + 0 == &table[0]

table + 1 == &table[1]

table[0]

table[1] 0 3

20 21 22 23 24table + 2 == &table[2] table[2]

“배열 이름은 첫 번째 배열원소의

시작주소 값을 갖는 포인터 상수”

table == &table[0]table[0] == &table[0][0]

55

[ ] [ ][ ]

포인터포인터 응용응용 (cont(cont’’d)d)

한 행씩 전달 #include <stdio.h>

#define ROW 5#define COL 4

void PRINT (int []);

0 1 2 3

10 11 12 13

20 21 22 23

int main(void){

int row;

20 21 22 23

30 31 32 33

40 41 42 43table[row]int table[ROW][COL] =

{ { 00, 01, 02, 03},{10, 11, 12, 13},{20, 21, 22, 23},

void PRINT (int arr[])

table

arr{30, 31, 32, 33},{40, 41, 42, 43} };

for (row = 0; row < ROW; row++)

{

int i;

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

i tf(“%3d” arr[i] ) ( ; ; )PRINT (table[row]);

return 0;}

printf(“%3d”, arr[i] );

printf(“\n”);

return;

}

56

}}

포인터포인터 응용응용 (cont(cont’’d)d)

전체 배열 전달#include <stdio.h>

#define ROW 5

#define COL 4

00 01 02 03

10 11 12 13

20 21 22 23

void PRINT (int [][COL]);

int main(void)

{table

30 31 32 33

40 41 42 43table

{

int table[ROW][COL] =

{ {00, 01, 02, 03},

{10, 11, 12, 13},

void PRINT (int p[][COL]){

int i j;

table

p

{20, 21, 22, 23},

{30, 31, 32, 33},

{40, 41, 42, 43} };

int i, j;

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

for (j = 0; j < COL; j++)

PRINT(table);

return 0;

(j j j )printf(“%3d”, p[i][j] );

printf(“\n”);}return;

57

}}

포인터포인터 응용응용 (cont(cont’’d)d)

메모리 할당 : malloc

ll 함수는 매개변수로 필요한 메모리의 바이트의 수를 가지며 그 malloc 함수는 매개변수로 필요한 메모리의 바이트의 수를 가지며, 그

바이트 수를 수용할 수 있는 크기의 메모리 블록을 할당한다.

• 할당된 메모리의 첫 번째 바이트를 void 포인터로 되돌린다.

• 할당된 메모리는 초기화되어 있지 않다 (쓰레기 값).

void * malloc(size t size);void malloc(size_t size);

int *p = NULL;int p = NULL;

p = (int *) malloc(sizeof (int) )if (p == NULL){

printf(“메모리 할당 실패!!! ₩n”);exit(100);

}

p

b

58

} 4 bytes

포인터포인터 응용응용 (cont(cont’’d)d)

인접 메모리 할당 : calloc

일반적으로 배열을 위한 메모리 할당에 주로 쓰인다 일반적으로 배열을 위한 메모리 할당에 주로 쓰인다.

• 특정 크기의 요소들을 배열로 담을 수 있을 만큼 연속적인 메모리 블록을 할당

• 할당된 배열의 첫 번째 요소를 가리키는 포인터를 반환

• 할당된 메모리를 초기화(즉, 할당된 메모리의를 0 으로 초기화)

void * calloc(size t element-count size t element-size);void * calloc(size_t element-count, size_t element-size);

int *p = NULL;p ;

p = (int *) calloc(200, sizeof (int) )if (p == NULL){

printf(“메모리 할당 실패!!! ₩n”);exit(100);

}

p...

59

}800 bytes

포인터포인터 응용응용 (cont(cont’’d)d)

메모리 재할당 : realloc

메모리 재할당에 쓰인다.

void * realloc(void *p, size t new Size);void realloc(void p, size_t new_Size);

p18 55 33 12 64 1 90 31 5 77 10 integers

pp = (int *)realloc(p, 15 * sizeof(int));

15 integers

18 55 33 12 64 1 90 31 5 77 ? ? ? ? ?

60

포인터포인터 응용응용 (cont(cont’’d)d)

메모리 해제 : free

malloc, calloc, realloc에 의해 할당된 메모리가 더 이상 필요 없을

때는 free 함수를 사용하여 해제한다.

• 프로그램의 종료 시에는 메모리를 반드시 지울 필요는 없다 이때는 운영체제가 모든프로그램의 종료 시에는 메모리를 반드시 지울 필요는 없다. 이때는 운영체제가 모든

메모리를 해제한다.

p p

4 bytes 4 bytesfree (p) ;free (p) ;

p pp

800 bytes

...

p

800 bytes

...

61

free (p) ;

포인터포인터 응용응용 (cont(cont’’d)d)

명령행 인자

int main(int argc, char *argv[], char **env)int main(int argc, char **argv, char **env)

• argc :명령행 인자의 개수

• **argv : 명령행 인자(문자열)가 있는 메모리의 시작 주소

• **env : 현재 시스템에 설정되어 있는 환경 변수• **env : 현재 시스템에 설정되어 있는 환경 변수

C:₩> mycopy test.txt copy.txt3argc

argv[0]

argvm y c o p y . e x e \0

NULL

argv[1]

argv[2]

c o p y t x t \0

t e s t . t x t \0

a g [3]

62

NULL c o p y . t x t \0argv[3]

포인터포인터 응용응용 (cont(cont’’d)d)

명령행 인자 (cont’d)

**env : 현재 시스템에 설정되어 있는 환경 출력 **env : 현재 시스템에 설정되어 있는 환경 출력

#include <stdio.h>

void main(int argc, char **argv, char **env)

{

for( ; *env; env++)

puts(*env);

}

env[0]

envALLUSERPROFILE=C:₩Documents and Setting₩All Users

NULL

[ ]

env[1]

env[n]...

APPDATA=C:₩Documents and Settings₩서두옥₩Application Data

_MSDEV_BLD_ENV_=1

63

NULLenv[n]

참고문헌참고문헌[1] 서두옥, 이동호(감수), “또 하나의 C : 프로그래밍은 셀프입니다”, 프리렉, 2011.

[2] 서현우, “뇌를 자극하는 C 프로그래밍”, 한빛미디어, 2005.

[3] 윤성우 “열혈강의 C 프로그래밍” 프리렉 2006[3] 윤성우, “열혈강의 C 프로그래밍”, 프리렉, 2006.

[4] 정재은, “다시 체계적으로 배우는 C언어 포인터”, 정보문화사.

[5] 김일광, “C 프로그래밍 입문 : 프로그래밍을 모국어처럼 유창하게”, 한빛미디어, 2004.

[6] Behrouz A Forouzan Richard F Gilberg 김진 외 7인 공역 “구조적 프로그래밍 기법을 위한 C” 도서출판[6] Behrouz A. Forouzan, Richard F. Gilberg, 김진 외 7인 공역, “구조적 프로그래밍 기법을 위한 C”, 도서출판

인터비젼, 2004.

[7] Brian W. Kernighan, Dennis M. Ritchie, 김석환 외 2인 공역, “The C Programming Language : 2/e”, 대영사,

2004.

[8] SAMUEL P. HARBISON Ⅲ, GUY L. STEELE, “C 프로그래밍 언어 : C : A Reference Manual”, Pearson Education

Korea.

[8] Wikipedia, http://www.wikipedia.org/.

이 강의자료는 저작권법에 따라 보호받는 저작물이므로 무단 전제와 무단 복제를 금지하며,

내용의 전부 또는 일부를 이용하려면 반드시 저작권자의 서면 동의를 받아야 합니다.

C i ht © Cli k All i ht d

64

Copyright © Clickseo.com. All rights reserved.

Recommended