40
© 2012 생능출판사 All rights reserved 쉽게 풀어쓴 C언어 Express 제17장 동적메모리와 연결리스트

쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

  • Upload
    others

  • View
    11

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

쉽게 풀어쓴 C언어 Express쉽게 풀어쓴 C언어 Express

제17장 동적메모리와 연결리스트

Page 2: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

이번장에서학습할내용

•동적 메모리 할당의 이해•동적 메모리 할당 관련함수•연결 리스트

동적메모리할당에대한개념을

이해하고응용으로연결리스트를학습합니다.

Page 3: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

동적할당메모리의개념

프로그램이 메모리를 할당받는 방법 정적(static) 동적(dynamic)

Page 4: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

정적메모리할당

정적 메모리 할당 프로그램이 시작되기 전에 미리 정해진 크기의 메모리를 할당받는 것

메모리의 크기는 프로그램이 시작하기 전에 결정

(예) int score_s[100];

처음에 결정된 크기보다 더 큰 입력이 들어온다면 처리하지 못함 더 작은 입력이 들어온다면 남은 메모리 공간은 낭비

Page 5: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

동적메모리할당

동적메모리할당 실행 도중에 동적으로 메모리를할당받는 것

사용이 끝나면 시스템에 메모리를 반납

score = (int *) malloc(100*sizeof(int));

필요한 만큼만 할당을 받고 메모리를 매우 효율적으로 사용

malloc() 계열의 라이브러리 함수를 사용

할당요구

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

int main(void){int *p;p = (int *)malloc( sizeof(int) );...}

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

int main(void){int *p;p = (int *)malloc( sizeof(int) );...}

프로그램

운영체제

Page 6: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

동적메모리할당절차

Page 7: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

동적메모리할당예제#include <stdio.h>#include <stdlib.h>int main(void) {

int *score; int i;score = (int *)malloc( 100*sizeof(int) ); if( p == NULL ) // 반환값이 NULL인지 검사{

printf("동적 메모리 할당 오류\n");exit(1);

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

score[i] = 0;free(p); return 0;

}

동적 메모리 할당

동적 메모리 해제

Page 8: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

동적메모리할당

void *malloc(size_t size) size는 바이트의 수 malloc()함수는 메모리 블럭의 첫 번째 바이트에 대한 주소를반환

만약 요청한 메모리 공간을 할당할 수 없는 경우에는 NULL값을 반환

int *score;score = (int *)malloc(100*sizeof(int));if( score == NULL ){

... // 오류처리}

score?????

Page 9: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

동적메모리사용

할당받은 공간은 어떻게 사용하면 좋을까?

첫 번째 방법: 포인터를 통하여 사용 *score = 100; *(score+1) = 200; *(score+2) = 300; ...

두 번째 방법: 동적 메모리를 배열과 같이 취급 score[0] = 100; score[1] = 200; score[2] = 300; ...

score??300200100

Page 10: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

동적메모리반납

void free(void *ptr) free()는 동적으로 할당되었던 메모리 블록을 시스템에 반납 ptr은 malloc()을 이용하여 동적 할당된 메모리를 가리키는 포인터

int *score;score = (int *)malloc(100*sizeof(int));…free(score);

score?????

Page 11: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

예제#include <stdio.h>#include <stdlib.h>int main(void){

char *pc = NULL;int i = 0;pc = (char *)malloc(100*sizeof(char));if( pc == NULL ) {

printf("메모리 할당 오류\n");exit(1);

}for(i=0;i<26;i++){

pc[i] = 'a'+i; // 알파벳 소문자를 순서대로 대입}pc[i] = 0; // NULL 문자 추가printf("%s\n", pc);free(pc);return 0;

}

abcdefghijklmnopqrstuvwxyz

Page 12: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

예제struct Book {

int number;char title[10];

};

int main(void){

struct Book *p;

p = (struct Book *)malloc(2 * sizeof(struct Book));

if(p == NULL){printf("메모리 할당 오류\n") ;exit(1);

}

p->number = 1;strcpy(p->title,"C Programming");

(p+1)->number = 2;strcpy((p+1)->title,"Data Structure");

free(p);return 0;

}

구조체 배열 할당

Page 13: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

calloc()

void *calloc(size_t n, size_t size);

calloc()은 0으로초기화된메모리 할당 항목 단위로메모리를할당

(예) int *p; p = (int *)calloc(5, sizeof(int));

p??????

malloc()

p

calloc()

000000

Page 14: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

realloc()void *realloc(void *memblock, size_t size);

realloc() 함수는할당하였던메모리블록의크기를 변경 (예) int *p; p = (int *)malloc(5 * sizeof(int))); p = realloc(p, 7 * sizeof(int)));

p

realloc()

924751 ??

p

malloc()

924751

Page 15: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

예제#include <stdio.h>#include <stdlib.h>#define INCREMENT 100 // 한 번에 증가시키는크기double *scores = NULL;int add_score(double new_score){

static int limit = 0; // 현재 동적 배열의 최대 크기static int count = 0; // 현재 동적 배열의 크기if( count < limit ){

scores[count++]= new_score;} else {

int new_limit = limit + INCREMENT;double *new_array = realloc(scores, new_limit*sizeof(double));if( new_array == NULL ){

fprintf(stderr, "메모리 할당 오류\n");}else { scores = new_array;

limit = new_limit;scores[count++] = new_score;

}return count;

}}

Page 16: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

예제int main(void){

int i, size;double value, total=0.0;size = 3;for(i=0;i<size;i++) {

printf("성적: ");scanf("%lf", &value);add_score(value);

}for(i=0;i<size;i++){

total += scores[i];}printf("평균: %f\n", total/size); free(scores);return 0;

}

성적: 10성적: 20성적: 30평균: 20.000000

Page 17: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

중간점검

1. 프로그램의 실행 도중에 메모리를 할당받아서 사용하는 것을__________이라고 한다.

2. 동적으로 메모리를 할당받을 때 사용하는 대표적인 함수는 ______이다.

3. 동적으로 할당된 메모리를 해제하는 함수는 ______이다.4. 동적 메모리 함수의 원형은 헤더파일 __________에 정의되어 있다.

Page 18: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

중간점검

1. 동적 할당 후에 메모리 블록을 초기화하여 넘겨주는 함수는 _____이다.

2. 할당되었던 동적 메모리의 크기를 변경하는 함수는 _____이다.3. 동적 메모리 할당에서의 단위는 ______이다.4. malloc()이 반환하는 자료형은 _______이다.

Page 19: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

연결리스트

배열(array) 장점: 구현이 간단하고 빠르다 단점: 크기가 고정된다. 중간에서 삽입, 삭제가 어렵다.

연결 리스트(linked list) 각각의 원소가 포인터를 사용하여 다음 원소의 위치를 가리킨다.

0011

2233

4455

6677

8899

메인메모리

A

B

CD

E

Page 20: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

연결리스트의장단점

중간에 데이터를 삽입, 삭제하는 경우

데이터를 저장할 공간이 필요할 때마다 동적으로 공간을 만들어서쉽게 추가

구현이 어렵고 오류가 나기 쉽다. 중간에 있는 데이터를 빠르게 가져올 수 없다.

데이터 삽입

B

AC D

E

N

데이터 삭제

B

AC D

E

Page 21: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

연결리스트의구조

노드(node) = 데이터필드(data field)+ 링크필드(link field)

data link

연결리스트의노드는데이터필드와링크필드로이루어집니다.

Page 22: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

연결리스트의구조

헤드포인터(head pointer): 첫번째노드를가리키는포인터

10 20 NULL30 NULL50 NULLNULL40plist

첫번째노드를가리키는포인터를헤드포인터라고하고맨마지막노드의링크필드는NULL입니다.

Page 23: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

노드생성

노드들은 동적으로 생성된다.

Page 24: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

자기참조구조체

자기참조구조체(self-referential structure)는 특별한 구조체로서구성 멤버 중에 같은 타입의 구조체를 가리키는 포인터가 존재하는구조체

typedef struct NODE {int data;struct NODE *link;

} NODE;

Page 25: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

간단한연결리스트생성

NODE *p1;p1 = (NODE *)malloc(sizeof(NODE));

p1->data = 10;p1->link = NULL;

NODE *p2;p2 = (NODE *)malloc(sizeof(NODE)); p2->data = 20;

p2->link = NULL; p1->link = p2;

free(p1);free(p2);

p1

10 NULLp1

10p1 20 NULL

10p1 20 NULL

Page 26: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

연결리스트의응용

소장하고 있는 책의 목록을 관리하는 프로그램을 작성 연결 리스트를 사용하여서 작성

Page 27: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

연결리스트를이용한프로그램

#include <stdio.h>#include <stdlib.h>#include <string.h>

#define S_SIZE 50

typedef struct NODE {char title[S_SIZE];int year;struct NODE *link;

} NODE;

Page 28: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

int main(void){

NODE *list = NULL;NODE *prev, *p, *next;char buffer[S_SIZE];int year;

Page 29: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

while(1) {printf("책의제목을입력하시오: (종료하려면엔터)");gets(buffer);if( buffer[0] == '\0' )

break;p = (NODE *)malloc(sizeof(NODE));strcpy(p->title, buffer);printf("책의출판연도를입력하시오: ");gets(buffer);year = atoi(buffer);p->year = year;if( list == NULL ) // 리스트가비어있으면

list = p; // 새로운노드를첫번째노드로만든다.else // 리스트가비어있지않으면

prev->link = p;// 새로운노드를이전노드의끝에p->link = NULL; // 새로운노드의링크필드를 NULL로설정prev = p;

}

Page 30: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

printf("\n");// 연결리스트에들어있는정보를모두출력한다.p = list;while( p != NULL ){

printf("책의제목:%s 출판연도:%d \n", p->title, p->year);p = p->link;

}// 동적할당을반납한다.p = list;while( p != NULL ){

next = p->link;free(p);p = next;

}return 0;

}

Page 31: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

실행결과

책의제목을입력하시오: (종료하려면엔터)컴퓨터개론책의출판연도를입력하시오: 2006책의제목을입력하시오: (종료하려면엔터)C언어책의출판연도를입력하시오: 2007책의제목을입력하시오: (종료하려면엔터)책의제목:컴퓨터개론출판연도:2006책의제목:C언어출판연도:2007

Page 32: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

중간점검

1. 연결 리스트에서 다음 노드는 _____로 가리킨다.2. 연결 리스트의 일반적인 노드는 _____필드와 _____ 필드로 구성되어있다.

3. 구조체의 멤버 중에 자기 자신을 가리키는 포인터가 존재하는 구조체를 _________라고 한다.

4. 배열과 연결 리스트의 가장 큰 차이점은 무엇인가?

Page 33: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

실습: 영화관리프로그램 구조체 배열을 동적 메모리를 이용하여서 생성하고 여기에 영화 정보를 저장했다가 다시 화면에 예쁘게 출력하는 프로그램을 작성하여보자.

영화 정보를 사용자로부터 받는다.

Page 34: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

실행결과

몇편이나저장하시겠습니까? 1영화 제목:트랜스포머영화 평점:8.3========================제목 평점========================트랜스포머 8.300000========================

Page 35: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

힌트

이 문제는 물론 정적 배열을 사용하면 아주 쉬운 문제이지만 여기서동적 메모리 할당을 이용해보자. 동적 메모리를 사용하면 사용자가원하는 만큼의 공간을 실행 시간에 할당받을 수 있다. 먼저 영화 정보를 다음과 같이 구조체로 표현한다.

typedef struct movie { // 구조체타입정의char title[100]; // 영화제목double rating; // 영화평점

} MOVIE;

사용자가 입력하고자 하는 영화의 수를 size에 입력받은 후에, 동적으로 할당

movies = (MOVE *)malloc(sizeof(MOVIE)* size); // 동적메모리할당

Page 36: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

예제#include <stdio.h>typedef struct movie { // 구조체타입정의

char title[100]; // 영화제목double rating; // 영화평점

} MOVIE;int main(void){

MOVIE *movies; // 동적메모리공간을가리키는포인터int size, i;printf("몇 편이나저장하시겠습니까? ");scanf("%d", &size);movies = (MOVIE *)malloc(sizeof(MOVIE)* size); // 동적메모리할당if( movies == NULL ){

printf("동적메모리할당오류");exit(1);

}

Page 37: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

예제for(i=0; i<size ;i++) { // size편의 영화정보입력

printf("영화제목");fflush(stdin); // 입력버퍼를비운다. gets(movies[i].title); // 영화제목에는빈칸이있을수

있다. printf("영화평점");scanf("%lf", &(movies[i].rating));

}printf("========================\n");printf("제목 \t 평점 \n");printf("========================\n");for(i=0;i<size;i++)

printf("%s \t %f \n", movies[i].title, movies[i].rating);printf("\n========================\n");free(movies); // 동적메모리공간해제return 0;

}

Page 38: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

도전문제

사용자가 입력한 데이터를 파일에 기록하는 코드를 추가해보자. 프로그램이 시작할 때 파일에서 데이터를 읽어오는 코드도 추가하여보자.

Page 39: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved

Q & A

Page 40: 쉽게풀어쓴C언어Express - rts.gnu.ac.krrts.gnu.ac.kr/class/2014fall/c_prog/ch17.pdf · 사용자가입력하고자하는영화의수를size에입력받은후에, 동적 으로할당

© 2012 생능출판사 All rights reserved