Chap.6 자료 구조 - 배열, 구조체, 포인터, 동적메모리

자료구조(data structure)

• 정보의 표현: 데이터의 ‘관계적’ 묶음

- Program 설계에서 가장 중요

⇒ 원하는 ‘정보(information)’를 어떠한 '자료구조'로 나타낼 것인가

http://ko.wikipedia.org/wiki/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0 (자료 구조)

e.g. 생명체에 필요한 정보: 유전정보-DNA, 면역정보,...

배열: 행렬 계산

• [본문] p.211 - p.222: Chap 04 PPT

e.g. 문자열

포인터, 동적메모리: 자료의 구조화

e.g., 연결 리스트(linked list)

http://ko.wikipedia.org/wiki/%EC%97%B0%EA%B2%B0_%EB%A6%AC%EC%8A%A4%ED%8A%B8 (연결 리스트)

• 포인터 변수

- C의 가장 강력한 기능 중의 하나

- 메모리의 '주소값(address)'을 저장하는 변수

e.g., 32-bit 컴퓨터: 32bit

64-bit 컴퓨터: 64bit

http://ko.wikipedia.org/wiki/64%EB%B9%84%ED%8A%B8

http://windows.microsoft.com/ko-kr/windows7/find-out-32-or-64-bit

제어판>시스템 및 보안\>시스템

- 일반 변수와 구별하기 위하여 변수 앞에 간접(indirection) 연산자 ‘*’ 사용

e.g., p.725 표

char *p;	// p에 저장된 ‘주소’에 char 데이터가 저장

// i.e., char 데이터를 가리키는 pointer 변수

int   *pt;      // pt에 저장된 ‘주소’에 int 데이터가 저장

// i.e., int 데이터를 가리키는 pointer 변수

e.g., p.726 pgm.: 포인터 변수를 선언하고 주소를 저장하여 출력

#include <stdio.h>

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

{

long k=8;	// 데이터값(data) 저장

long *p;	// 주소값(address) 저장

p=&k;	// 변수 k의 주소값을 p에 저장

printf("k의 주소: %u\n", &k);

printf("p의 주소: %u\n", &p);

printf("p의 주소값: %u\n", p);

printf("p가 가리키는 곳의 데이터값: %d\n", *p); //&p, p, *p의 차이점?

*p=10;

printf("k의 데이터값: %d\n", k);	// k를 출력 (=*p)

return 0;

}

(설명) p.726 그림

- 포인터 변수는 다른 변수를 ‘참조(reference)’

⇒ 다른 ‘변수의 값’을 제어할 수 있음

p(=&k)

&p

&k

*p(=k)

4bytes

(=32bits)

• 포인터와 배열과의 관계

- ‘배열의 이름’은 그 배열의 첫 번째 요소가 저장되어 있는 ‘주소’임

⇒ 배열의 이름 = 포인터

e.g., p.728 pgm.: 배열의 이름과 포인터

#include <stdio.h>

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

{

int i, a[3]={10,20,30}, *pt;

printf("배열의 주소: %u\n", a);

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

printf("a[%d]의 주소: %u\n", i, &a[i]);

pt=a;	// 배열의 주소(address)를 pt에 저장

printf("포인터의 주소값: %u\n", pt);

//  ‘주소 print’ 후 주소 증가 (int ptr이므로 4bytes씩)

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

printf("a[%d]의 주소: %u\n", i, pt++);

pt=a;

// ‘pt가 가리키는 값’을 print 후 주소 증가

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

printf("a[%d]의 값: %d\n", i, *pt++);

// pt가 가리키는 값을 print 후 'pt가 가리키는 값을 증가' (pt는 일정)

pt=a;

for (i=0;i<3;i++)	// *pt++와의 차이점

printf("포인터: %u,  a[0]의 값: %d\n", pt, (*pt)++);

return 0;

}

• 포인터와 문자열

- 문자열 선언

char str1[]="copy";	// 배열 크기 생략

char str1[5]="copy";	// 배열 크기 지정, 문자열보다 하나 더 크게 선언	(마지막에 자동으로 NULL - ‘\0' 저장됨)

char *str2="text";	// char 포인터 사용 - 문자열의 첫번째 주소 저장

구조체: 시간과 날짜와 관련된 함수들

• [본문] p.87 - p.99: Chap 02 PPT

e.g. 테이블

고객명	시	동	계좌		계좌	예금액
안중근	서울	신촌	556		900	100,000
유관순	서울	용산동	647		556	90,000
강감찬	대전	둔산동	801		647	85,000
윤봉길	대전	어은동	647		801	150,000
이순신	대구	수성동	900

• 포인터와 구조체

- [부록 5] p.738 - p.740

#include <stdio.h>

#include <string.h>

struct user{

char name[20];

char phone[14];

int quick;

};

int main(void)

{

struct user d[10];	// 구조체 배열 선언

struct user *p;	// 구조체 포인터 선언

strcpy(d[0].name, "김명환");	//구조체 멤버 데이터 입력 - ‘.’ 연산자

printf("phone 입력: ");

scanf("%s", d[0].phone);

d[0].quick=1;

printf("\nname : %s\n", d[0].name);	//구조체 멤버 데이터 출력

printf("phone: %s\n", d[0].phone);

printf("quick: %d\n", d[0].quick);

p=d;

printf("\nname : %s\n", p->name); //구조체 멤버 데이터 출력- ‘->’ 연산자

printf("phone: %s\n", p->phone);

printf("quick: %d\n", p->quick);

return 0;

}

• [본문] p.353 - p.376: Chap 05 PPT

- 연결 리스트(linked list)

#include <stdio.h>

#include <malloc.h>

struct linked_list{

char data;

struct linked_list *link;

};

void add_node(char data);

void print_linked_list(struct linked_list *now);

void print_reverse_linked_list(struct linked_list *now);

struct linked_list *head;

int main(void)

{

char key;

head=(struct linked_list*)malloc(sizeof(struct linked_list)); //동적할당

head->link=NULL;

printf("문자열 입력 후 'Enter' Key > ");

do{

key=getchar();

add_node(key);

}while(key!='\n');	// ‘Enter’ key - 문자열 입력 끝

printf("\n\n");

printf("입력된 순서: ");

print_linked_list(head->link);

printf("\n");

printf("입력된 역순: ");

print_reverse_linked_list(head->link);

printf("\n");

return 0;

}

void add_node(char data)

{

struct linked_list *new_node, *last;

last=head;

while(last->link != NULL)	// 마지막 노드를 찾음

last=last->link;

new_node=(struct linked_list*)malloc(sizeof(struct linked_list)); //동적할당

new_node->data=data;	// 새 노드 데이터 입력

new_node->link=last->link;  // 새 노드 링크에 NULL 입력

last->link=new_node;	// 마지막 노드와 새 노드를 연결

}

void print_linked_list(struct linked_list *now)

{

while(now != NULL){

printf("%c ", now->data);

now=now->link;	// 앞으로 전진

}

printf("\n");

}

void print_reverse_linked_list(struct linked_list *now)

{

if(now->link != NULL){

print_reverse_linked_list(now->link);	// 재귀 함수 이용 - stack

printf("%c ", now->data);

}

else

printf("%c ", now->data);

}

- 스택(stack): First In Last Out

#include <stdio.h>

#include <malloc.h>

struct stack_node{

char data;

struct stack_node *link;

};

void push(char data);

char pop(void);

struct stack_node *top=NULL;

int main(void)

{

char key;

printf("문자열 입력 후 'Enter' Key > ");

do{

key=getchar();

push(key);

}while(key!='\n');	// ‘Enter’ key - 문자열 입력 끝

printf("\n\n");

printf("데이터 pop 과정 \n");

while(top != NULL){

key=pop();

printf("%c \n", key);

}

printf("\n");

return 0;

}

void push(char data)

{

struct stack_node *new_node;

new_node=(struct stack_node*)malloc(sizeof(struct stack_node)); //동적할당

new_node->data=data;

new_node->link=top;	// 새로운 노드를 push

top=new_node;	// top은 새로운 노드

}

char pop(void)

{

struct stack_node *temp;

char data;

data=top->data;

temp=top;

top=top->link;	// top을 pop

free(temp);	// 동적 메모리 해제

return data;

}