처음으로 배우는 C 프로그래밍 제4부 복합 데이터 형 제 10 장 구조체.

Slides:



Advertisements
Similar presentations
1.1 구조체란 1.2 중첩 구조체 1.3 구조체와 배열 1.4 구조체와 포인터 1.5 구조체와 함수 1.6 공용체와 열거형.
Advertisements

Chapter 12. 배열. 배열  동일한 항목들이 동일한 크기로 연속적으로 메모리에 저장되는 구조  동일한 자료 유형이 여러 개 필요한 경우에 이용할 수 있는 자료 구조.
6 장. printf 와 scanf 함수에 대한 고찰 printf 함수 이야기 printf 는 문자열을 출력하는 함수이다. – 예제 printf1.c 참조 printf 는 특수 문자 출력이 가능하다. 특수 문자의 미 \a 경고음 소리 발생 \b 백스페이스 (backspace)
1 08 배열. 한국대학교 객체지향연구소 2 C 로 배우는 프로그래밍 기초 2 nd Edition 배열  동일한 자료유형의 여러 변수를 일괄 선언  연속적인 항목들이 동일한 크기로 메모리에 저장되는 구조  동일한 자료 유형이 여러 개 필요한 경우에 이용할 수 있는.
1. 2 차원 배열  배열은 동일한 데이터 유형으로 여러 개의 변수를 사용할 경우 같은 이 름으로 지정하여 간편하게 사용할 수 있도록 하는 것으로서 앞에서 1 차원 배열을 공부하였습니다.  2 차원 배열은 바둑판을 생각하면 되며, 1 차원 배열에서 사용하는 첨자를 2.
1 구조체 윤 홍 란 컴퓨터 프로그래밍 2 구조체 정의  구조체란 ? o 서로 다른 형의 변수들을 하나로 묶어주는 mechanism. (cf. 배열 : 같은 형의 변수들을 하나로 묶어주는 mechanism) o 예 : 카드의.
제2장 C 언어의 확장 C++(1).
ㅎㅎ 구조체 구조체 사용하기 함수 매개변수로서의 구조체 구조체 포인터와 레퍼런스 구조체 배열.
ㅎㅎ 구조체 C++ 프로그래밍 기초 : 객체지향의 시작 구조체 사용하기 함수 매개변수로서의 구조체 구조체 포인터와 레퍼런스
쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express Slide 1 (of 27)
2장. 프로그램의 기본 구성. 2장. 프로그램의 기본 구성 2-1"Hello, World!" 들여다 보기 /* Hello.c */ #include int main(void) { printf("Hello, World! \n"); return 0;
제14장 동적 메모리.
연결리스트(linked list).
제 9 장 구조체와 공용체.
-Part2- 제3장 포인터란 무엇인가.
11장 구조체와 열거형 구조체의 정의 구조체 변수의 선언 구조체 초기화 및 사용 구조체 재정의 포인터를 이용해서 구조체 사용
자료 구조: Chapter 3 (2)구조체, 포인터
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
윤성우의 열혈 C 프로그래밍 윤성우 저 열혈강의 C 프로그래밍 개정판 Chapter 12. 포인터의 이해.
쉽게 풀어쓴 C언어 Express 제17장 동적메모리와 연결리스트 C Express Slide 1 (of 13)
5장. 참조 타입.
제 3장. C보다 나은 C++ II.
C 프로그래밍.
Dynamic Memory and Linked List
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
8장 함수 함수의 필요성 라이브러리 함수와 사용자 정의 함수 함수의 정의, 원형, 호출 배열을 함수 인자로 전달 재귀호출.
SqlParameter 클래스 선문 비트 18기 발표자 : 박성한.
컴퓨터 프로그래밍 기초 #02 : printf(), scanf()
23장. 구조체와 사용자 정의 자료형 2.
자료구조: CHAP 4 리스트 (3) 순천향대학교 컴퓨터공학과 하 상 호.
프로그래밍 랩 – 7주 리스트.
14장. 포인터와 함수에 대한 이해.
11장. 1차원 배열.
처음으로 배우는 C 프로그래밍 제4부 복합 데이터 형 제 8 장 배열, 주소, 포인터.
C#.
C 프로그래밍 C언어 (CSE2035) (Chap11. Derived types-enumerated, structure, and union) (1-1) Sungwook Kim Sogang University Seoul, Korea Tel:
JA A V W. 03.
사용자 함수 사용하기 함수 함수 정의 프로그램에서 특정한 기능을 수행하도록 만든 하나의 단위 작업
박성진 컴퓨터 프로그래밍 기초 [09] 배열 part 1 박성진
13. 포인터와 배열! 함께 이해하기 IT응용시스템공학과 김 형 진 교수.
3장 상수 변수 기본 자료형 키워드와 식별자 상수와 변수 기본 자료형 형변환 자료형의 재정의.
Java의 정석 제 5 장 배 열 Java 정석 남궁성 강의 의
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express Slide 1 (of 22)
19. 함수 포인터와 void 포인터.
3장. 변수와 연산자 교안 : 전자정보통신 홈페이지 / 커뮤니티/ 학술세미나
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
2장. 변수와 타입.
처음으로 배우는 C 프로그래밍 제4부 복합 데이터 형 제 7 장 배열.
컴퓨터 프로그래밍 기초 - 8th : 함수와 변수 / 배열 -
8주차: Strings, Arrays and Pointers
Canary value 스택 가드(Stack Guard).
제 6 장 함수(functions).
데이터 동적 할당 Collection class.
4장. 데이터 표현 방식의 이해. 4장. 데이터 표현 방식의 이해 4-1 컴퓨터의 데이터 표현 진법에 대한 이해 n 진수 표현 방식 : n개의 문자를 이용해서 데이터를 표현 그림 4-1.
제 8장. 클래스의 활용 학기 프로그래밍언어및실습 (C++).
멀티미디어시스템 제 5 장. 멀티미디어 데이터베이스 개념 IT응용시스템공학과 김 형 진 교수.
컴퓨터 프로그래밍 기초 - 9th : 배열 / 포인터 -
구조체(struct)와 공용체(union)
Summary of Pointers and Arrays
Numerical Analysis Programming using NRs
Chapter 11 구조체.
제 4 장 Record.
어서와 C언어는 처음이지 제21장.
개정판 누구나 즐기는 C언어 콘서트 제13장 동적 메모리 출처: pixabay.
처음으로 배우는 C 프로그래밍 제4부 복합 데이터 형 제 10 장 구조체.
13. 포인터와 배열! 함께 이해하기.
Pointers summary.
7 생성자 함수.
2019 2학기 9장 배열과 포인터 1. 주소, 주소연산자(&) 2. 포인터, 역참조연산자(*) 3. 배열과 포인터.
Presentation transcript:

처음으로 배우는 C 프로그래밍 제4부 복합 데이터 형 제 10 장 구조체

구조체 집단을 구성하는 개개 원소들이 어떻게 배치되어 있는지 혹은 어떻게 조직화되어 있는지를 나타냄 예: 회사 정보: 회사원 정보와 부서 정보 정부의 조직: 조직원, 조직의 형태, 조직의 배치 정보 개 개의 자료 항목이 어떻게 배치되어 있는지를 잘 설명하고 있는 단위(unit) 예 (우편물 주소) Name: (자료 항목) - 개체(entity) Street Address: (자료 항목) - 개체(entity) City: (자료 항목) - 개체(entity) State: (자료 항목) - 개체(entity) Zip Code: (자료 항목) - 개체(entity) 레코드(record): 개개의 자료 항목을 모아 형성한 더 큰 집단 => 구조체 구조체 형태: 개개의 자료 항목의 기호명, 자료형과 배치로 구성 구조체 내용: 기호명에 저장된 실 자료를 의미

구조체(계속) 구조체 형태: 개개의 자료 항목의 기호명, 자료형과 배치로 구성 Name Street Address City State Zip Code 구조체 내용: 기호명에 저장된 실 자료를 의미 Rhona Bronson-Karp 614 Freeman Street Orange NJ 07052

단일 구조체 자료 항목, 구조체 멤버 구조체 변수 구조체의 선언 자료형, 자료 명, 자료 항목 배치 작성 구조체 정의 예 (년월일을 저장하는 구조체) struct { int month; /* 월 */ int day; /* 일*/ int year; /* 년*/ } birth; 구조체 멤버 접근 방법(연산자 .) birth.month (birth 구조체 멤버 month 접근) birth.year (birth 구조체 멤버 year 접근) 자료 항목, 구조체 멤버 구조체 변수

#include <stdio.h> void main(void) { struct { int month; int day; int year; } birth; birth.month = 10; birth.day = 12; birth.year = 63; printf("My birth date is %d/%d/%d.", birth.month, birth.day, birth.year); } 출력 결과 My birth date is 10/12/63.

구조체 정의 변수 명을 갖는 구조체 정의 단일 변수 여러 변수 struct {int month; int day; int year;} birth; 여러 변수 struct {int month; int day; int year;} birth, current; birth.month, birth.day, birth.year current.month, current.day, current.year

구조체 정의 (계속) 구조체 템플리트(template) 구조체 템플리트를 이용한 변수 선언 변수명이 없는 정의 struct Date { /* Date <- 구조체 태그(tag) 명, 구조체 이름 */ int month; int day; int year; }; 구조체 템플리트(template) 구조체 템플리트를 이용한 변수 선언 struct Date birth, current; 멤버 접근 birth.month, birth.day, birth.year current.month, current.day, current.year

구조체 템플리트 선언 구조체 멤버의 초기화 struct Date birth = {10, 12, 63}; #include <stdio.h> struct Date { int month; int day; int year; }; void main(void) { (1) struct Date birth; (2) birth.month = 10; (3) birth.day = 12; (4) birth.year = 63; printf("My birth date is %d/%d/%d", birth.month, birth.day, birth.year); } 구조체 템플리트 선언 구조체 멤버의 초기화 struct Date birth = {10, 12, 63};

구조체 선언 예 회사원 정보 회사원 정보를 위한 구조체 템플리트선언 구조체 정의와 초기화 Name Identification Number Regular Pay Rate Overtime Pay Rate 회사원 정보를 위한 구조체 템플리트선언 struct Pay_rec { char name[20]; int id_num; float reg_rate; float ot_rate; } ; 구조체 정의와 초기화 struct Pay_rec employee = {"H. Price", 12387, 15.89, 25.50};

사람의 생년월일을 위한 구조체 Date 구조체 사용 멤버 접근 방법 struct { char name[20]; /* 이름을 저장하는 변수 */ struct Date birth; /* 생년월일을 저장하는 변수 */ } person; 멤버 접근 방법 person.name person.birth.month person.birth.day person.birth.year

구조체 메모리 할당 aPoint x y 구조체에 대한 메모리 할당 tag_name : 구조체의 이름 구조체 템플리트(틀) 정의는 구조체의 모양을 정의하며 그 형식은 다음과 같음 struct tag_name{ type1 member1; type2 member2; : typen membern; }; x-y 좌표 상에서 “하나의 점과 그 이름을 표시하는 구조체”의 예는 다음과 같음 예) struct aPoint { int x; int y; char name[10]; tag_name : 구조체의 이름 type1, … typen : 각 멤버의 자료형 member1, … membern : 각 멤버의 이름 Name[1] aPoint Name[9] Name[0] x y 구조체에 대한 메모리 할당

구조체 템플리트 정의와 변수선언 struct tag_name { type1 member1; type2 member2; : 구조체 템플리트 정의와 구조체 변수 선언을 한 번에 할 수 있음 struct tag_name { type1 member1; type2 member2; : typen membern; } struct_variables, ... ; 예) struct aPoint { int x; int y; char name[5]; } pt1, pt2, pt3; 10 20 청주 (10, 20, 청주) (10, 15, 대전) pt1

구조체 배열 사원에 대한 자료 사원번호 사원이름 사원급여지급비율 사원번호 사원이름 사원급여지급비율 ========================================== 32479 Abrams, B. 6.72 <= 첫 번째 레코드 33623 Bohm, P. 7.54 <= 두 번째 레코드 34145 Donaldson, S. 5.56 <= 세 번째 레코드 35987 Ernst, T. 5.43 <= 네 번째 레코드 36203 Gwodz, K. 8.72 <= 다섯 번째 레코드 36417 Hanson, H. 7.64 <= 여섯 번째 레코드 37634 Monroe, G. 5.29 <= 일곱 번째 레코드 38321 Price, S. 9.67 <= 여덟 번째 레코드 39435 Robbins, L. 8.50 <= 아홉 번째 레코드 39567 Willians, B. 7.20 <= 열 번째 레코드 정수형 배열 문자형 배열 실수형

구조체 배열(계속) 사원을 위한 구조체 사원들의 정보를 저장하기 위한 구조체 배열 struct Pay_rec { long idnum; char name[20]; float rate;}; 사원들의 정보를 저장하기 위한 구조체 배열 struct Pay_rec empolyee[10]; employee[0].rate : 첫번째 사원의 급여 지급 비율 employee[4].idnum : 다섯번째 사원의 사원 번호

#include <stdio.h> struct Pay_rec { long id; char name[20]; float rate; }; /* 전역 템플리트 구성 */ void main(void) { int i; struct Pay_rec employee[10] = { 32479, "Abrams, B.", 6.72, 33623, "Bohm, P.", 7.54, 34145, "Donaldson, S.", 5.56, 35987, "Ernst, T.", 5.43, 36203, "Gwodz, K.", 8.72, 36417, "Hanson, H.", 7.64, 37634, "Monroe, G.", 5.29, 38321, "Price, S.", 9.67, 39435, "Robbins, L.", 8.50, 39567, "Willians, B.", 7.20 }; for (i=0; i<5; i++) printf("\f2 nld %-20s %4.2f", employee[i].id, employee[i].name, employee[i].rate); } /* end of main */ 출력결과 32479 Abrams, B. 6.72 33623 Bohm, P. 7.54 34145 Donaldson, S. 5.56 35987 Ernst, T. 5.43 36203 Gwodz, K. 8.72

구조체 전달 struct { int id_num; double pay_rate; double hours; 구조체 멤버의 전달 스칼라(scalar) 변수와 같은 방법으로 전달 구조체 전달(값에 의해) struct { int id_num; double pay_rate; double hours; } emp; display(emp.id_num); calc_pay(emp.pay_rate, emp.hours); calc_net(emp);

The net pay for employee 6782 is $361.66 #include <stdio.h> struct Employee { int id_num; double pay_rate; double hours; }; void main(void) { struct Employee emp = 6782, 8.93, 40.5; double net_pay; double c_net(struct Employee); net_pay = calc_net(emp); /* emp로 값의 복사본 전달 */ printf("The net pay for employee %d is $%6.2f", emp.id_num, net_pay); } double calc_net(struct Employee temp) return (temp.pay_rate * temp.hours); 출력결과 The net pay for employee 6782 is $361.66

구조체 전달(계속) 구조체 전달(주소에 의한) 피호출문 호출문 void calc_net(struct Employee *pt) } 호출문 calc_net(&emp);

예) struct Employee *pt1, *pt2, *pt3; 포인터 변수로부터 구조체의 멤버를 참조하는 방법 구조체 타입의 포인터 변수 예) struct Employee *pt1, *pt2, *pt3; 포인터 변수로부터 구조체의 멤버를 참조하는 방법 포인터의 성질을 이용한 방법 (*pt1).hours ‘->’연산자를 이용한 방식 pt1 -> hours ‘->’연산 ‘->’연산자의 왼쪽은 구조체의 주소, 오른쪽은 그의 멤버이름을 넣어야 함 구조체 연산자 . 와 -> 는 함수의 ( )와 배열 첨자의 [ ]와 함께 연산 순위가 가장 높음 그러므로 *point.hours는 *(point.hours)와 같은 효과를 지니고, ++pt->hours는 ++(pt-> hours)와 같은 효과를 지닌다.

*pt.hours = *(pt.hours) <= 프로그램 오류 *pt == (*pt).id_num (*pt).id_num == pt->id_num (*pt).pay_rate == pt->pay_rate (*pt).hours == pt->hours (*pointer).member => pointer->member

주소에 의해 구조체 전달 예 #include <stdio.h> struct Employee { int id_num; double pay_rate; double hours; }; void main(void) { struct Employee emp = 6782, 8.93, 40.5; double net_pay, double c_net(struct Employee *); net_pay = calc_net(&emp); /* emp로 값의 복사본 전달 */ printf("The net pay for employee %d is $%6.2f", emp.id_num, net_pay); } double calc_net(struct Employee *temp) return (temp->pay_rate * temp->hours);

구조체 포인터 연산 pt++; ++pt; pt--; --pt; ++pt->hours;

구조체 반환 함수의 반환 값으로 구조체를 받기를 원하는 경우 스칼라(scalar) 값을 반환할 때와 같은 방법으로 구조체를 반환 #include <stdio.h> struct Employee { int id_num; double pay_rate; double hours; }; struct Employee get_vals(void) { struct Employee em; …. return em; } 구조체반환 void main() { struct Employee emp; ... emp = get_vals(); /*함수 호출*/ } emp.id_num = em.id_num; emp.pay_rate = em.pay_rate; emp.hours = em.hours

#include <stdio.h> struct Employee { int id_num; double pay_rate; double hours; }; void main(void) { struct Employee emp; struct Employee get_vals(void); emp = get_vals(); printf("\f2 nThe employee id number is %d", emp.id_num); printf("The employee pay rate is $%5.2f", emp.pay_rate); printf("The employee hours are %5.2f", emp.hours); } struct Employee get_vals(void) struct Employee new_emp; new_emp.id_num = 6789; new_emp.pay_rate = 16.25; new_emp.hours = 38.0; return (new_emp); 출력결과 The employee id number is 6789 The employee pay rate is $16.25 The employee hours are 38.00

연결 리스트(Linked List) 자료 처리 방법 특정 순서로 존재하는 레코드(record)에 새로운 레코드를 삽입하거나 기존의 레코드를 삭제할 때 존재하는 레코드가 계속적으로 그 순서를 유지하도록 함 예 (알파벳순서로 정렬된 전화번호 목록) Acme, Sam (201) 898-2392 Dolan, Edith (213) 682-3104 Lanfrank, John (415) 718-4581 Mening, Stephanie (914) 382-7070 Zemann, Harold (718) 219-9912

연결리스트(계속) struct person { char name[20]; char telnum[20]; }; 배열 구조를 사용하는 경우 struct person { char name[20]; char telnum[20]; }; 삽입과 삭제의 문제점 발생 struct person hb[10]; Zemann, Harold (718) 219-9912 Acme, Sam (201) 898-2392 Dolan, Edith (213) 682-3104 Lanfrank, John (415) 718-4581 Mening, Stephanie (914) 382-7070 hb[0] hb[1] hb[2] hb[3] hb[4]

연결 리스트(계속) 연결 리스트는 간단한 구조체 집합으로 각 구조체는 리스트 내에서 논리적으로 순서화된 구조체 주소를 갖는 적어도 하나의 멤버를 포함 물리적 측면:물리적으로 적절한 순서로 저장되기보다는 오히려 새로운 레코드가 리스트에 추가될 때 물리적으로 컴퓨터의 저장장소내 사용 가능한 임의의 공간에 추가됨 논리적 측면:레코드들은 자기 앞의 레코드가 자신의 주소를 가리키게 함으로써 서로 연결됨 프로그래밍 관점: 처리될 현재의 레코드는 다음 레코드가 물리적으로 어디에 저장되어 있든지 무관하게 다음 레코드의 주소를 포함함 구조체 포인터

연결 리스트(계속) 연결 리스트 삽입 (June Hagar 자료 삽입)

연결 리스트(계속) 연결리스트(삭제)

연결 리스트(계속) Employee number 12345 was paid $456.20 구조체에 구조체 포인터 추가 #include <stdio.h> struct Test { int id_num; double *pt_pay; }; void main(void) { struct Test emp; double pay = 456.20; emp.id_num = 12345; emp.pt_pay = &pay; printf("Employee number %d was paid $%6.2f'', emp.id_num, *emp.pt_pay); } 출력결과 Employee number 12345 was paid $456.20

연결 리스트(계속) 구조체 포인터 전화번호 저장을 위한 연결 리스트 구조체 #include <stdio.h> struct Tele_typ { char name[30]; char phone_no[15]; struct Tele_typ *nextaddr; }; 구조체 포인터

void main(void) { struct Tele_typ t1 = ''Acme, Sam'', ''(201) 898-2392''; struct Tele_typ t2 = ''Dolan, Edith'', ''(213) 682-3104''; struct Tele_typ t3 = ''Lanfrank, John'', ''(415) 718-4581''; Tele_typ *first; /* 구조체 포인터 생성 */ first = &t1; /* t1 주소를 first 에 저장 */ t1.nextaddr = &t2; /* t2 주소를 t1.nextaddr에 저장 */ t2.nextaddr = &t3; /* t3 주소를 t2.nextaddr에 저장 */ t3.nextaddr = NULL; /* NULL 를 t3.nextaddr에 저장 */ printf(''%s %s %s'', first->name, t1.nextaddr->name, t2.nextaddr->name); } 출력결과 Acme, Sam Dolan, Edith Lanfrank, John

구조체를 포인터로 전달 void main(void) #include <stdio.h> { struct Tele_typ t1 = "Acme, Sam", "(201) 898-2392"; struct Tele_typ t2 = "Dolan, Edith", "(213) 682-3104"; struct Tele_typ t3 = "Lanfrank, John", "(415) 718-4581"; Tele_typ *first; /* 구조체 포인터 생성 */ first = &t1; /* t1 주소를 first 에 저장 */ t1.nextaddr = &t2; /* t2 주소를 t1.nextaddr에 저장 */ t2.nextaddr = &t3; /* t3 주소를 t2.nextaddr에 저장 */ t3.nextaddr = NULL; /* NULL 를 t3.nextaddr에 저장 */ display(first); /* 구조체 first의 주소를 전달 */ } #include <stdio.h> struct Tele_typ { char name[30]; char phone_no[15]; struct Tele_typ *nextaddr; };

void display(struct Tele_typ *contents) /*contents는 Tele_typ 형 구조체의 포인터 변수임 */ { while (contents != NULL) /* 연결 리스트에 저장된 모든 구조체 정보를 출력 */ printf("%30s %-20s %s", contents->name, contents->phone_no); contents = contents->nextaddr; } return; 출력결과 Acme, Sam (201) 898-2392 Dolan, Edith (213) 682-3104 Lanfrank, John (415) 718-4581

동적 메모리 할당 프로그램에서 정의된 모든 변수는 그 변수의 값을 저장하기에 충분한 기억장소를 컴퓨터 메모리로부터 할당 받음 특정 메모리 위치가 변수를 위해 확보되면, 변수의 유효 범위(life time)내에서는 그 위치가 사용되든 그렇지 않든 그 위치는 변하지 않는다 예:500 개의 정수를 저장하는 배열 사용하는 정수: 10개, 490개의 기억 공간 낭비 => 효율적인 기억 장소 필요성 필요할 때 필요한 만큼 기억장소를 확보 불필요한 기억장소는 해제 예: 연결 리스트(삽입 정보, 정보 삭제)

동적 메모리 할당 함수 동적 메모리 할당을 위한 include 함수명: stdlib.h 메모리 할당 함수 - 함수명: malloc(int ) - 기능: 요구된 바이트 수() 만큼 기억장소를 확보한다. 성공적으로 기억장소를 확보하면 기억장소의 시작 주소를 반환하고 충분한 메모리가 없는 경우 NULL를 반환한다. -예: int *pt; pt = malloc(200 * sizeof(int)); 메모리 해제 함수 -함수명: free() -기능:미리 확보된 바이트의 블록을 해제한다. 해제될 기억장소의 시작 주소가 이 함수의 인자로 사용된다. -예: free(pt);

배열의 크기를 입력 받아 그 만큼의 배열을 위한 기억 장소 할당 int numgrades; int *grades; /* 정수형 포인터 변수 정의 */ printf("Enter the number of grades to be processed: "); scanf("%d", &numgrades); /* 요구된 만큼의 정수형 배열을 위한 기억장소 할당 */ grades = (int *) malloc(numgrades * sizeof(int));

#include <stdio.h> #include <stdlib.h> void main(void) { int numgrades; int *grades; /* 정수형 포인터 변수 정의 */ printf("Enter the number of grades to be processed: "); scanf("%d", &numgrades); /* 요구된 만큼의 정수형 배열을 위한 기억장소 할당 */ grades = (int *) malloc(numgrades * sizeof(int)); if (grades == (int *) NULL) {/* 동적기억장소할당이 정상적으로 이루어졌는지를 검사 */ printf("Failed to allocate grades array "); exit(1); }

An array was created for 4 integers for (i=0; i < numgrades; i++) { printf(" Enter a grade: "); scanf("%d", &grades[i]); } printf("\f2 nAn array was created for %d integers", numgrades); printf("\f2 nThe vales stored in the array are:"); for (i=0; i < numgrades; i++) printf(" %d", grades[i]); free(grades); 실행결과 Enter the number of grades to be processed: 4 Enter a grade: 85 Enter a grade: 96 Enter a grade: 77 Enter a grade: 92 An array was created for 4 integers The value stored in the array are: 85 96 77 92

구조체 동적 기억장소 할당 struct Office_info { 자료 멤버들; }; struct Office_info *off; /*할당된 주소를 저장하기 위한 포인터 변수 */ /* 구조체를 저장하기 위한 공간 확보 */ off = (struct Office_info *) malloc(sizeof(struct Office_info)); /* 공간이 할당되었는지를 점검 */ if (off == (struct Office_info *) NULL) { printf("\f2 nAllocation of Office info record failed"); exit(1) }

동적 연결 리스트 초기 리스트

동적 연결 리스트 삽입 예 Carter 삽입

동적 연결 리스트 삽입 방법 INSERT (새로운 레코드를 연결 리스트에 추가) { -새로운 레코드를 위한 공간을 동적으로 할당 if 리스트에 임의의 레코드가 존재하지 않음 -새로운 레코드의 주소 필드를 NULL로 지정 -첫 번째 레코드 포인터를 새롭게 생성된 레코드의 주소로 지정 else -새로운 레코드가 리스트의 어느 위치에 놓여져야 할 것인지를 결정 if 레코드가 리스트의 첫 번째 레코드로 존재해야 함 -첫 번째 레코드 포인터의 값을 새롭게 추가된 레코드의 주소 필드에 복사 -첫 번째 레코드 포인터의 주소를 새롭게 추가된 레코드의 주소로 지정 -추가된 레코드의 바로 앞에 놓일 레코드의 포인터 멤버의 값을 새롭게 추가된 레코드의 주소 필드에 복사 새롭게 추가된 레코드의 주소로 지정 /* endif */ /* endif } /* end of INSERT

동적 연결 리스트 삽입 새로운 레코드의 선형 탐색(LINEAR LOCATION of a NEW RECORD) if 새로운 레코드의 키이 필드가 첫 번째 레코드 키이 필드보다 작으면 - 새로운 레코드가 첫 번째 레코드임 else while (리스트에 레코드가 있음) { - 새로운 레코드의 키이 값과 각 레코드의 키이 값과 비교 - 새로운 레코드 키가 두 개의 레코드사이에 존재하거나 혹은 리스트의 끝에 속하는 경우 비교를 멈춤 } endwhile endif

레코드 삽입 예 #include <stdio.h> #include <stdlib.h> #define MAXCHARS 30 /* 연결 리스트 레코드의 선언 */ struct Name_rec { char name[MAXCHARS]; struct Name_rec *next_addr; }; /* 첫 번째 레코드 포인터의 정의 */ struct Name_rec *first_rec; void main(void) { void read_insert(void); /* 함수 프로토타입 */ void display(void); first_rec = NULL; /* 리스트 포인터 초기화 */ read_insert(); display(); }

/* 이름을 입력받아 이를 연결 리스트에 삽입 */ void read_insert(void) { char name[MAXCHARS]; void insert(char []); printf("\f2 nEnter as many names as you wish, one per line"); printf("\f2 nTo stop entering names, enter a single x "); while(1) printf("Enter a name: "); gets(name); if (strcmp(name, "x") == 0) break; insert(name); }

void insert(char *name) { struct Name_rec *locate(char *); /* 함수 프로토타입 */ struct Name_rec *newaddr, *here; /* Name_rec 형 구조체 포인터 */ newaddr = (struct Name_rec *) malloc(sizeof(struct Name_rec)); if (newaddr == (struct Name_rec *) NULL) { /* 주소를 점검 */ printf("\f2 nCould not allocate the requested space"); exit(1); } /* 새로운 레코드가 어디에 놓여져야 할지를 결정, 모든 포인터 멤버를 갱신 */ if (first_rec == NULL) {/* 현재 리스트에 존재하는 레코드가 없는 경우 */ newaddr->next_addr = NULL; first_rec = newaddr; else if (strcmp(name, first_rec->name) < 0) { /* 리스트에 첫 번째 레코드로 추가되는경우 */ newaddr->next_addr = first_rec; } else {/* 레코드가 리스트의 첫 번째 레코드가 아닌 경우 */ here = locate(name); newaddr->next_addr = here->next_addr; here->next_addr = newaddr; strcpy(newaddr->name, name);

/* 존재하는 연결 리스트에 새로 추가될 레코드의 삽입될 위치를 결정 */ struct Name_rec *locate(char *name) { struct Name_rec *one, *two; one = first_rec; two = one->next_addr; if (two == NULL) return (one); /* 새로운 레코드는 존재하는 단일 레코드 다음에 삽입될 것임 */ while(1) { if (strcmp(name, two->name) <0) /* 리스트내의 이 위치에 레코드를 삽입한다 */ break; else if (two->next_addr == NULL) { /* 마지막 레코드 다음에 위치 */ one = two; } else { /* 계속적으로 삽입될 위치를 찾음 */ two = one->next_addr; return (one);

/* 연결 리스트로부터 name을 출력 */ void display(void) { struct Name_rec *contents; contents = first_rec; printf("\f2 nThe names currently on the list are:"); while (contents != NULL) { printf("%s", contents->name); contents = contents->next_addr; } return; 출력결과 Enter as many names as you wish, one per line To stop entering names, enter a single x Enter a name: Binstock Enter a name: Arnold Enter a name: Duberry Enter a name: Carter Enter a name: x The names currently on the list are: Arnold Binstock Carter Duberry

공용체(Union) 공용체는 사용할 때마다 이질적인 멤버의 자료형과 다른 크기를 가질 수 있도록 하는 구조체임 비교) 파스칼의 가변 레코드와 동일함 하나의 메모리 장소에 여러 데이터 형의 자료를 저장 가능하도록 지원함; 즉, 여러 자료형의 변수가 하나의 주소를 공유하게 함 그러나, 여러 값이 동시에 저장될 수는 없음; 즉, 한 시점에는 하나의 자료만 저장됨 공용체의 선언은 구조체와 동일함 union u_tag { int ival; float fval; char *sval; } u, *uptr, uarray[10]; 공용체 u_tag의 크기는 int, float, char 중에서 가장 큰 것으로 할당됨 비교) 구조체의 크기는 모든 멤버들의 크기의 합과 같음

공용체(계속) 구조체에서 정의된 . 과 -> 연산자도 공용체에서 동일한 의미로 사용 u.fval uptr->ival 공용체 u에는 세 가지 자료형 (int, float, char) 중 어느 것으로도 할당 가능 그러나, 할당된 값의 참조는 가장 최근에 할당한 자료형으로만 가능함 (이는 전적으로 프로그래머 책임임 ) ufval = 2.0; /* 10이 지워지고 2.0이 저장; 4byte사용 */ u.sval = “I am a boy,”; /*2.0이 지워지고 주소가 저장; 4byte사용 */ uptr = &u; x = uptr -> fval; /* Error!! 가장 최근에 문자 포인터로 사용했기 때문에 */ u.ival = 10; /* 10이 저장; 2byte사용 */ union u_tag { int ival; float fval; char *sval; } u, *uptr, uarray[10];

공용체(계속) 구조체 안에 공용체을, 반대로 공용체 안에 구조체를 선언할 수도 있음 char *name; int flags; struct { /*구조체 이름 생략 가능!!*/ char *name; int flags; int utype; union { int ival; float fval; char *sval; } u; } symtab[NSYM]; if ( symtab[n].utype == INT) printf(“%d\n”, symtab[n].u.ival); else if (symtab[n].utype == FLOAT) printf(“%f\n”, symtab[n].u.fval); else if (symtab[n].utype == STRING) printf(“%s\n”, symtab[n].u.sval);

범하기 쉬운 오류 구조체와 공용체가 관계 수식으로 사용될 수 없기 때문에 발생한다. 예를 들어, Tel_type과 Phon_type이 같은 형의 구조체일 지라도 수식 Tel_typ == Phon_type은 프로그래밍 오류이다 포인터가 구조체와 공용체와 관계할 때 발생하는 포인터 오류이다. 공용체와 관련 된 것으로 공용체가 특정한 시점에 공용체를 구성하는 멤버들 중 하나의 멤버만을 나타내고 있으므로 현재 저장된 변수 값이 무엇인지를 꼭 알고 있어야 한다. 만약 공용체에 저장된 값을 잘못된 변수를 통해 접근하면 원하지 않은 이상한 값을 여러분은 접근할 것이다.