530 likes | 706 Views
제 9 장 구조체 및 공용체. 문봉근. 제 9 장 구조체 및 공용체. 9.1 구조체 (structure) 9.2 공용체 (union) 9.3 열거형 (enumeration) 9.4 형 정의 (typedef) 9.5 비트 - 필드 (bit-field) 9.6 구조체 응용 프로그램. 9.1.1 구조체 정의 및 변수 선언. 구조체 (structure) 는 여러 개의 변수를 쉽게 사용할 수 있도록 하나의 이름으로 묶어 놓은 하나 이상의 변수의 집합
E N D
제9장 구조체 및 공용체 문봉근
제9장 구조체 및 공용체 9.1 구조체(structure) 9.2 공용체(union) 9.3 열거형(enumeration) 9.4 형 정의(typedef) 9.5 비트-필드(bit-field) 9.6 구조체 응용 프로그램
9.1.1 구조체 정의 및 변수 선언 • 구조체(structure)는 여러 개의 변수를 쉽게 사용할 수 있도록 하나의 이름으로 묶어 놓은 하나 이상의 변수의 집합 • 구조체에 포함되는 변수는 배열과는 달리 서로 다른 데이터형들로 구성된다. • 구조체는 배열이나 다른 구조체 등과 같은 C 언어에서 사용 가능한 모든 데이터형을 포함할 수 있다. • 즉, 구조체는 배열과는 달리 이질적인(heterogeneous) 자료형으로 원소들을 구성할 수 있는 구조적 자료형으로서, 각 원소들은 배열처럼 기억장소에 순차적으로 저장된다. • 구조체를 정의하고 구조체 변수를 선언하는 일반적인 형식 ■ 문법 (1)struct <tag명> {<component_list>}; /*형 정의*/ struct <tag명> <variable_list>; /*변수 선언*/ (2)struct <tag명> {<component_list>} <variable_list>; /*형 정의와 선언*/ (3)struct {<component_list>} <variable_list>; /*형 정의와 선언*/ (4)typedef struct {<component_list>} <identifier>; /* 형 정의 */ <identifier> <variable_list>; /* 변수 선언 */
9.1.1 구조체 정의 및 변수선언(계속) • 백화점 고객의 구조체 형태 • 이 구조체의 이름을 ‘customer‘할 때, 위와 같은 형태의 구조체를 정의하는 방법은 다음과 같다. struct customer{ int id; char name[20]; char address[30]; char telephone[12]; int amount; };
9.1.1 구조체 정의 및 변수선언(계속) • 여러 가지 구조체 정의 및 구조체 변수의 선언 (1) 사용예1 struct list{ char *univ; char *class; int count; }; main() { struct list y1, y2, y3; .............. } (2) 사용예2 struct{ char *univ; char *class; int count; } y1={"Hankuk","C Langugage", 40}; (3) 사용예3 struct list{ char *univ; char *class; int count; } y1, y2, y3; /*구조체 변수 3개 선언*/
9.1.2 구조체의 멤버 접근 • 특정 구조체 변수에 포함된 멤버 데이터에 접근하기 위해서는 도트연산자를 사용한다. • 도트연산자는 ‘구조체_변수명.멤버명’과 같이 구조체 변수명과 멤버명 사이에 기입된다. struct coord{ int x; int y; }; ........... struct coord first, second; ........... first.x=50; first.y=100; second.x=40; second.y=60; • 위의 예에는 first와 second가 구조체 변수로 선언되어 있다. • 이 구조체 변수의 멤버 데이터에는 정수형의 x, y가 있음을 구조체 정의로부터 알 수 있다. • 구조체 변수와 멤버 데이터 사이에 도트연산자가 들어간다는 사실 이외에는 일반적인 변수의 사용과 동일하다.
9.1.2 구조체의 멤버 접근(계속) • 예제 9.1 • 구조체 선언과 도트연산자를 이용한 구조체 멤버 표현. ☑ 프로그램 #include <stdio.h> #include <string.h> struct student { char name[20]; int korean; int english; }; void main() { struct student kdhong; strcpy(kdhong.name, "홍길동"); kdhong.korean=90; kdhong.english=99; printf("이름 : %s \n", kdhong.name); printf("국어 : %d \n", kdhong.korean); printf("영어 : %d \n", kdhong.english); } ꁼ 실행결과 이름 : 홍길동 국어 : 90 영어 : 99
9.1.2 구조체의 멤버 접근(계속) • 예제 9.2 • 구조체 선언과 데이터 입력 및 출력 방법. ☑ 프로그램 #include <stdio.h> struct robot { //구조체 선언하는 방법. struct [데이타 타입] int head; int body; char arm[20]; //char의 경우 배열로 받는다. long leg; }; void main(void) { struct robot tv; //데이타 타입에 따른 변수선언. printf(" input head(int) : "); scanf("%d", &tv.head); printf(" input body(int) : "); scanf("%d", &tv.body); printf(" input arm(char) : "); scanf("%s", tv.arm); //string으로 받아서 배열에 저장 printf(" input leg(long) : "); scanf("%ld", &tv.leg); printf("%d %d %s %ld\n", tv.head, tv.body, tv.arm, tv.leg); } ꁾ 입력 input head(int) : 34 input body(int) : 21 input arm(char) : kkk input leg(long) : 495 ꁼ 실행결과 34 21 kkk 495
9.1.2 구조체의 멤버 접근(계속) • 예제 9.3 • 입력된 자료를 구조체 변수의 각각의 멤버에 저장한 후에, 이를 화면에 다시 출력하는 프로그램을 작성하라. ☑ 프로그램 #include <stdio.h> main(void) { struct tel_nr /* 구조체 정의 */ { char name[20]; char addr[40]; char tel[20]; }; struct tel_nr one; /* 구조체 변수 선언 */ /* name, addr, tel은 문자형이기 때문에 scanf()에서 &을 사용할 수 없다 */ scanf("%s %s %s", one.name, one.addr, one.tel); printf(" %s\n %s\n %s\n", one.name, one.addr, one.tel); } ꁾ 입력 Hong Seoul (02)123-4567 ꁼ 실행결과 Hong Seoul (02)123-4567
9.1.2 구조체의 멤버 접근(계속) • 예제 9.4 • 멤버를 문자형으로 name을, 정수형으로 age와 income으로 하고 tag를 enployee로 하는 구조체를 선언한 후 구조체 변수 list를 선언하여 name에 "홍길동", age에 35, income에 220을 대입하고 표시하라. ☑ 프로그램1 /* (1) struct <tag명> {<component_list>}; */ /* struct <tag명> <variable_list>; */ #include <stdio.h> void main() { struct employee { char *name; int age, income; }; struct employee list; list.name="홍길동"; list.age = 35; list.income = 220; printf("%10s %3d %4d\n", list.name, list.age, list.income); } ꁼ 실행결과 홍길동 35 220
9.1.2 구조체의 멤버 접근(계속) • 예제 9.4(계속) ☑프로그램2 /* (2) struct <tag명> {<component_list>} <variable_list>; */ #include <stdio.h> void main() { struct employee { char *name; int age, income; } list; list.name="홍길동"; list.age = 35; list.income = 220; printf("%10s %3d %4d\n", list.name, list.age, list.income); } ꁼ 실행결과 홍길동 35 220
9.1.2 구조체의 멤버 접근(계속) • 예제 9.5 • 구조체 포인터를 사용한 예제 ☑ 프로그램 #include <stdio.h> #include <string.h> struct student { char name[20]; int korean; int english; }; void main() { struct student kdhong; struct student *sp=&kdhong; /*포인터sp에 lee의 시작주소 배정*/ strcpy(sp->name, "홍길동"); sp->korean=90; (*sp).english=99; /* sp->eng=99 와 같은 의미 */ printf("이름 : %s \n",sp->name); printf("국어 : %d \n",sp->korean); printf("영어 : %d \n",sp->english); } • 구조체의 포인터 변수는 구조체의 멤버 데이터에 접근하기 위해 간접 멤버 참조 연산자인 화살표연산자(arrow operator, ->)를 사용함 • 화살표연산자(->)는 ‘구조체_포인터명->멤버명’과 같이 구조체 포인터명과 멤버명 사이에 기입됨
9.1.2 구조체의 멤버 접근(계속) • 예제 9.6 ☑ 프로그램 #include <stdio.h> struct s_type{ int i; char ch; double d; }var1, var2; void struct_swap(struct s_type* a, struct s_type* b); main() { var1.i = 100; var1.ch = 'A'; var1.d = 10.0; var2.i = 200; var2.ch = 'B'; var2.d = 20.0; struct_swap(&var1, &var2); printf("var1: %d, %c, %lf\n", var1.i, var1.ch, var1.d); printf("var2: %d, %c, %lf\n", var2.i, var2.ch, var2.d); return 0; } void struct_swap(struct s_type* a, struct s_type* b) { struct s_type tmp; tmp = *a; *a = *b; *b = tmp; } ꁼ 실행결과 var1: 200, B, 20.000000 var2: 100, A, 10.000000
9.1.2 구조체의 멤버 접근(계속) • 예제 9.7 • 구조체를 이용한 성적계산 프로그램 ☑ 프로그램 #include <stdio.h> struct level { //구조체 선언하는 방법. struct [데이타 타입] char name[3]; int kor; int eng; int math; int total; float avr; }; void main(void) { struct level first_session[3]; //데이타 타입에 따른 변수선언. int i; for (i=0; i<3; i++) { printf(" 이름을 입력하시오 : "); scanf("%s", first_session[i].name); printf(" 국어 성적을 입력하시오 : "); scanf("%d", &first_session[i].kor); printf(" 영어 성적을 입력하시오 : "); scanf("%d", &first_session[i].eng); //string으로 받아서 배열에 저장 printf(" 수학 성적을 입력하시오 : "); scanf("%d", &first_session[i].math); first_session[i].total = first_session[i].kor + first_session[i].eng + first_session[i].math; first_session[i].avr = (float)first_session[i].total/3; printf("이름 : %s, 국어 : %d\n 영어 : %d, 수학: %d\n“, first_session[i].name, first_session[i].kor, first_session[i].eng, first_session[i].math,); printf("총점 : %d, 평균 : %f\n", first_session[i].total, first_session[i].avr); } }
9.1.3 구조체의 초기화 • 구조체의 초기화 방법은 일반적인 배열의 초기화와 매우 유사하다. • 구조체 초기화를 위해 대입연산자 (=)를 사용하며, 만일 구조체의 각 멤버의 수보다 적은 개수의 값이 할당되면 나머지는 ‘0’또는 ‘’로 간주된다. • 방법 : 구조체를 구성하는 각 멤버에 초기화 값을 중괄호({})를 사용하여 정의 (1) 사용예1 struct student{ int student_id; char name[20]; int kor; int eng; }; struct student teamA={1001, "Kim, Su Young", 97, 99}; (2) 사용예2 struct student{ int student_id; char name[20]; int kor; int eng; }teamA={1001, "Kim, Su Young", 97, 99};
9.1.3 구조체의 초기화(계속) (3) 사용예3 struct student{ int hakbun; char name[20]; int kuk; int eng; }; struct student teamA[3]={ { 1001, "Kim, Su Young", 97, 99}, { 1002, "Lee, Gi Chan", 97, 99}, { 1003, "Choi, Hee Sun", 97, 99}, };
9.1.4 중첩된 구조체 • 구조체가 멤버 데이터의 형태로 오는 경우, 이와 같은 구조체를 중첩 구조체(nested structure)라고 한다. • 구조체의 멤버 데이터는 C 언어에서 사용될 수 있는 모든 데이터 형태가 사용될 수 있다. • 중첩 구조체의 일례 struct rectangle { struct coord topleft; struct coord bottomright; }; • 이 구조체를 이용해서 사각형을 그리려면 우선 구조체 변수를 선언해 주어야 함. struct rectangle mybox; • 두개의 좌표로 이루어진 두 점의 이용 mybox.topleft.x=0; mybox.topleft.y=10; mybox.bottomright.x=100; mybox.bottomright.y=200;
9.1.4 중첩된 구조체(계속) • 예제 9.8 • 다음과 같은 메모리 맵을 갖는 중첩된 구조체의 멤버 변수를 확인하는 프로그램을 작성하라. ☑ 프로그램 struct tagg { /* 구조체 tagg 정의 */ char c[10]; struct subtag { /* 중첩된 구조체 subtag 정의 */ int i; double d; }z; /* 중첩된 구조체 subtag의 변수 선언 */ int j; } x; /* 구조체 tagg의 변수 선언 */ main(void) { x.z.i=10; /* 개별 항목에 대한 접근 */ x.j=100; printf("%d %d\n", x.z.i, x.j); } ꁼ 실행결과 10 100
9.1.5 구조체 배열 • 구조체 변수가 많아지면 프로그램이 복잡하게 되므로 통상의 변수와 마찬가지로, 이를 배열로 선언하면 편리하다. • struct list y1, y2, y3;를 struct list y[3];와 같이 사용할 수 있다. struct list{ char *univ; char *class; int count; }; main() { int i; struct list y[3]; ............ }
9.1.5 구조체 배열(계속) • 구조체 배열이란 구조체가 배열의 요소가 되는 경우를 말함 • 구조체 배열의 선언은 기존의 배열 선언 방법과 유사함. struct book { float value; char title[10]; char author[7]; }; struct book library[100]; • 구조체인 book 형태의 변수 100개로 이루어진 library라는 배열이다. • 각 배열의 요소가 구조체이기 때문에, 각 구조체에 대해서 멤버 데이터가 존재한다. • 그런데 배열의 요소는 그 변수 형태가 모두 동일하듯이 구조체 배열의 요소인 각 구조체 변수의 속성은 모두 같다.
9.1.5 구조체 배열(계속) library.value[2]; /* 틀림 */ library[2].value; /* 옳음 */ • 구조체 배열 library의 메모리 맵 상태
9.1.5 구조체 배열(계속) • 구조체 배열의 대입 • 배열의 요소인 각 구조체의 기본적인 형태가 같기 때문에 대입(assignment)도 가능하다. • 구조체는 같은 구조를 가진 구조체인 경우에는 구조체끼리의 연산이 가능하기 때문이다. library[3] = library[5] strcpy(library[3].value, library[5].value) • 구조체 배열 변수의 선언 형식 예 (1)형식1 : struct employee { char *name; int age, income; }list[5]; (2)형식2 : struct employee { char *name; int age, income; }; struct employee list[5];
9.1.5 구조체 배열(계속) • 예제 9.9 • 가족의 이름과 나이 및 성별을 출력하는 프로그램을 다음과 같은 member형 구조체 변수를 이용하여 작성하라. struct member { char *name; char *sex; int age; } ☑ 프로그램 #include <stdio.h> main() { int i; struct member { char *name; char *sex; int age; }; struct member a[4]={"Hong, Kil-dong","male",50, "Choi, Soon-Hee","female",46, "Hong, Heon-Jeong","female",3, "Hong, Yoo-Shin","male",2}; for(i=0;i<4;i++) printf("%s %s %d\n",a[i].name,a[i].sex,a[i].age); return 0; }
9.1.5 구조체 배열(계속) • 예제 9.10 • 1에서 20까지의 수의 제곱과 세제곱을 저장하기 위해 구조체 배열을 사용하는 프로그램을 작성하여라. 배열의 내용도 출력하여라. ☑ 프로그램 #include <stdio.h> struct power{ int i; int square; int cube; }nums[20]; main() { int i; for(i=1; i<=20; i++) { nums[i].i=i; nums[i].square=i*i; nums[i].cube=i*i*i; } for(i=1; i<=20; i++) printf("nums[%2d].square=%3d, nums[%2d].cube=%4d\n", i, nums[i].square, i, nums[i].cube); return 0; }
9.1.5 구조체 배열(계속) • 예제 9.11 • 고용자 이름, 전화번호, 작업시간 그리고 시간당 임금을 저장하는데 구조체 배열을 사용하는 프로그램을 작성하여라. 10명의 고용자를 저장할 수 있게 하여라. ☑ 프로그램 #include <stdio.h> #include <stdlib.h> struct s_type{ char name[40]; char phone[14]; int hours; double wage; }emp[10]; void main(void) { int i; char temp[80]; for(i=0; i<2; i++) { printf("Enter name: "); gets(emp[i].name); printf("Enter telephone number: "); gets(emp[i].phone); printf("Enter hours worked: "); gets(temp); emp[i].hours = atoi(temp); printf("Enter hourly wage: "); gets(temp); emp[i].wage = atof(temp); } for(i=0; i<2; i++) printf("name=%s, phone=%s, hour=%d, wage=%lf\n", emp[i].name, emp[i].phone, emp[i].hours, emp[i].wage); }
9.1.5 구조체 배열(계속) • 예제 9.12 • 20세 이상의 남자직원, 및 이름이 "ziny"인 사람 찾아서 출력하기 ☑ 프로그램 #include <stdio.h> #include <string.h> struct member { //구조체 선언하는 방법. struct [데이타 타입] char name[10]; //이름 char sex; //성별 int age; //나이 char level[10]; //직위 }; void main(void) { struct member member_session[5]= { {"ziny", 'M', 29, "사장"}, {"이말단", 'M', 25, "사원"}, {"임부장", 'M', 39, "부장"}, {"심대리", 'F', 22, "대리"}, {"김이사", 'M', 43, "이사"}}; //데이타 타입에 따른 변수선언. int i; for (i=0; i<5; i++) { if(member_session[i].sex == 'M' && member_session[i].age > 20) printf("이름 : %s \n직위 : %s\n", member_session[i].name, member_session[i].level); } printf("\n\n"); for (i=0; i<5; i++) { if (strspn(member_session[i].name,"ziny")!=0) //이름이 ziny인 사람만 검색 printf("이름 : %s \n직위 : %s\n", member_session[i].name, member_session[i].level); } }
9.1.6 구조체 포인터 • 구조체와 포인터의 관계 • 포인터변수가 구조체 멤버가 되는 경우 • 구조체 포인터의 경우 • 구조체 포인터의 예 struct member { int number; char name[5]; }; struct member *ptr; • 구조체와 구조체 간에, 또는 구조체 포인터와 구조체 간에 어떤 관계를 가지기 위해서는 서로 구조체 구조가 같아야 한다. struct member student; ptr = &sutdent; /* 포인터변수 ptr의 초기화 */
9.1.6 구조체 포인터(계속) • 구조체에 대한 포인터를 사용하여 구조체 멤버를 참조하는 방법 • 도트연산자(.) (*ptr).number = 13; • 간접연산자(*)는 도트연산자(.)보다 우선순위가 낮기 때문에 다음과 같이 괄호를 같이 써 주어야 한다. • 화살표연산자(->) ptr->number = 17;
9.1.6 구조체 포인터(계속) • 예제 9.13 • malloc() 함수를 이용한 배열의 영역을 확보하고 데이터를 저장하는 방법 ☑ 프로그램 #include <stdio.h> void main() { struct employee { char *name; int age, income; } *list; list=malloc(sizeof(list)); /*메모리 확보(크기는 list)*/ list->name="김철수"; list->age=38; list->income=562; printf("%s %d %d만원\n", list -> name, list -> age, list -> income); } ꁼ 실행결과 김철수 38 562만원
9.1.7 구조체와 함수 • 구조체는 다른 데이터형과 마찬가지로 함수의 인수로 구조체를 전달할 수도 있다. • 함수에서 매개 변수로 구조체를 주고받는 두 가지 방법 • 구조체를 매개 변수로 사용하는 경우 struct student {........} std, p; main() { p=sub(std); } struct student sub(struct student std_sub) { return std_sub; } • 구조체 포인터를 매개 변수로 사용하는 경우 struct student {........} std; void main() { sub(&std); } void sub(struct student *std_sub) { (*std_sub).id=1004; }
9.1.7 구조체와 함수(계속) • 예제 9.14 • 구조체의 내용을 표시해 주는 함수를 두 가지 방식으로 구조체에 전달 ☑ 프로그램 #include <stdio.h> struct student{ char name[20]; int korean; int english; }; void disp1(struct student aa) { printf("%s %d %d\n", aa.name, aa.korean, aa.english); } void disp2(struct student *bb) { printf("%s %d %d\n", bb->name, bb->korean, bb->english); } void main() { struct student lee={"Hong, Gil Dong", 90, 80}; disp1(lee); disp2(&lee); } ꁼ 실행결과 Hong, Gil Dong 90 80 Hong, Gil Dong 90 80
9.1.7 구조체와 함수(계속) • 예제 9.15 • 구조체 자체가 함수의 인수로 사용된 또 다른 예 ☑ 프로그램 #include <stdio.h> struct data{ /* 구조체의 선언 */ int x, y; }; int total(struct data tot); /* 함수의 원형 */ void main() { struct data value = {1, 3}; /* 구조체의 초기화 */ int sum = 0; sum = total ( value); /* 함수의 호출 */ printf("Sum = %d\n", sum); } int total(struct data tot) /* 함수의 정의 */ { return (tot.x + tot.y); } ꁼ 실행결과 Sum = 4
9.2 공용체 • 공용체(union) • 여러 자료형의 원소들이 공통으로 사용할 수 있는 기억장소를 정의하고, 한 번에 하나의 멤버만이 특정한 자료형 기억장소로 사용할 수 있도록 메모리를 관리하는 자료형 • 공용체(union)는 구조체와 유사하며, 구조체와 같은 방법으로 선언되고 사용된다. • 공용체는 한 번에 하나의 멤버만이 사용될 수 있다는 점에서 구조체와 다르다. • 공용체의 모든 멤버는 메모리에서 같은 영역을 차지하고 있다. 즉, 모든 멤버는 겹쳐져 있는 셈이다. • 공용체는 구조체와 거의 같기 때문에 멤버에 접근하기 위해서 사용되는 구조체연산자가 모두 사용될 수 있다. • 구조체와 달리 데이터를 초기화시킬 수 없다. ■ 문법 union <tag 명> {<component_list>} <variable_list>; • 구조체에서 <component_list>의 항목들은 각각 별도의 기억장소를 배정 받는데 반해, 공용체에서는 항목들 중에서 가장 큰 기억장소를 요하는 자료형의 크기만큼 확보하여 모든 항목들이 공통으로 사용한다. • 공용체 변수는 함수의 매개변수로 사용될 수 없다는 것이 또 하나의 특징이다.
9.2 공용체(계속) union shared { char c; int i; }; union shared generic_variable; generic_variable.c = 'a'; • 공용체는 한 번에 하나의 멤버만 사용될 수 있기 때문에 초기화도 하나의 멤버에 대해서만 해 줄 수 있다. • 공용체의 다른 멤버를 초기화 해주면 메모리 내에서는 그 위에 덮여 씌우기 때문에 처음에 초기화 해준 내용은 사라진다. union{ date married, widowed; /* 결혼과 과부의 경우 */ struct { date ddate; boolean firstd; } divorced; /* 이혼한 경우 */ boolean single; /* 독신의 경우 */ } status;
9.2 공용체(계속) • 예제 9.16 • 공용체 tagg의 변수 v1은 정수 n과 실수 i로 선언된 두 멤버 중에서 최근에 결정된 멤버 i에 대한 변수로만 사용되는 것을 보여 준다. ☑ 프로그램 #include <stdio.h> union tagg{ /* 공용체 정의 */ int n; float i; } v1, *pt; void main() { float k; pt=&v1; v1.n=10; v1.i=20.0; k=pt->i; /* pt->n으로 사용할 수 없다 */ printf("%f", k); } ꁼ 실행결과 20.000000
9.2 공용체(계속) • 예제 9.17 • short int를 int로 변경하기 위해 공용체를 사용하는 프로그램을 작성하여라. ☑ 프로그램 #include <stdio.h> void main() { union u_type{ int i; short int s; }uvar; uvar.i=500; uvar.s=1000; printf("%d\n", uvar.i); } ꁼ 실행결과 1000
9.2 공용체(계속) • 예제 9.18 • short int의 상위 바이트와 하위 바이트의 값을 개별적으로 출력하는 프로그램을 작성하여라. 이때, 하나의 정수와 2바이트 문자 배열의 두 원소로 구성된 공용체를 사용하여라. ☑ 프로그램 #include <stdio.h> void main(void) { union u_type { short int i; unsigned char c[2]; } uvar; uvar.i = 511; printf("High order byte: %u\n", uvar.c[1]); printf("Low order byte: %u\n", uvar.c[0]); } ꁼ 실행결과 High order byte: 1 Low order byte: 255
9.2 공용체(계속) • 예제 9.19 • 사용자가 입력한 정수를 포함하는 개개의 바이트를 문자로 출력하기 위해 공용체(union)를 사용하는 프로그램을 작성하여라. ☑ 프로그램 #include <stdio.h> union i_to_c{ char c[4]; int i; } ic; void main(void) { printf("Enter an integer: "); scanf("%x", &ic.i); printf("character represention of each byte: %c %c %c %c\n", ic.c[0], ic.c[1], ic.c[2], ic.c[3]); } ꁼ 실행결과 Enter an integer: 41424344 character represention of each byte: D C B A
9.2 공용체(계속) • 예제 9.20 • 하나의 double과 8바이트 문자 배열로 구성된 공용체를 사용하여, 한 번은 하나의 double을 쓰고 다음에는 하나의 문자(char)를 쓰는 함수를 작성하여라. ☑ 프로그램 #include <stdio.h> #include <stdlib.h> union u_type{ double d; unsigned char c[8]; }; uread(union u_type* pvar); main() { int i; union u_type var; uread(&var); printf("%lf\n", var.d); for(i=0; i<8; i++) printf("var.c[%d]=%c\n", i, var.c[i]); } uread(union u_type* pvar) { int i; printf("Enter a double number: "); scanf("%lf", &pvar->d); getchar(); printf("Enter 8 charaters: "); for(i=0; i<8; i++) scanf("%c", &pvar->c[i]); }
9.3 열거형 • C 언어는 사용자가 자료의 값을 임의로 정하고 이를 열거하여 새로운 자료형을 정의할 수 있는데, 이러한 자료형을 열거형(enum)이라고 한다. • 열거형은 상수의 성질을 갖는 데이터형으로서, 열거형의 정의 부분을 제외한 프로그램 문장 부분에서 열거형 상수에 어떤 값을 배정하는 행위는 불가능하다. • 열거형 상수를 사용하여 프로그램을 기호화(symbolic programming)하는 것은 프로그램의 수정을 용이하게 하고, 프로그램의 판독성(readability)을 향상시킨다. • ■ 문법 enum <identifier> enum { <identifier >, … } enum { <identifier > = <constant-expression>, … } enum <identifier> { <identifier>, … } enum <identifier> { <identifier> = <constant-expression>, … } • 열거형에 나열된 값들은 번역기에 의하여 나열된 순서에 따라 0부터 1씩 증가되는 값을 할당받아 참조 시에 이를 열거된 값에 일치시킨다. • 예를 들면, 컴파일러는 enum day {sun, tues, wed, thur, fri, sat} weekday를 enum day {0, 1, 2, 3, 4, 5, 6}으로 해석하여 번호로 값을 일치시킨다. • 이때 weekday=sun과 같은 배정문에서 weekday 값은 0으로 해석되나 사용자는 코드값 대신에 요일 이름을 사용함으로써 프로그램의 이해를 향상시킬 수 있다. enum num{sun=2, mon=0, tue=5, wed, thu, fri, sat, someday}day; • 이 경우, tue=5의 다음부터는 tue에 1씩 더하여 wed=6, thu=7, fri=8, sat=9, someday=10이 된다.
9.3 열거형(계속) • 예제 9.21 • 열거형을 이용하여 요일을 표시하였을 때 사용 방법. ☑ 프로그램 #include <stdio.h> void main() { enum day{ Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }d; d=Monday; printf("%d\n", d); } ꁼ 실행결과 1
9.3 열거형(계속) • 예제 9.22 • 열거형의 처음데이터만 초기값을 부여했을 경우. ☑ 프로그램 #include <stdio.h> void main() { enum day{ Sunday=3 Monday,Tuesday,Wednesday Thursday,Friday,Saturday }d; d=Monday; printf("%d\n", d); } ꁼ 실행결과 4
9.3 열거형(계속) • 예제 9.23 • 열거형의 초기값을 순서에 관계없이 부여했을 경우. ☑ 프로그램 #include <stdio.h> void main() { enum num{ sum=2, mon=0, tue=5, wed, thu, fri, sat, someday}d; d=someday; printf("%d\n", d); } ꁼ 실행결과 10
9.3 열거형(계속) • 예제 9.24 • 초기값이 부여되지 않은 열거형. ☑ 프로그램 #include <stdio.h> enum day {sun, mon, tue, wed, thu, fri, sat}; //초기값이 없기때문에 0~6까지 변수값이 대입된다. typedef enum day day; day find_next_day(day d) { return ((day)(((int)d+1)%7)); } void main(void) { day cur_day=tue; char* d_name[] = {"일", "월", "화", "수", "목", "금", "토"}; printf("%s요일\n", d_name[find_next_day(cur_day)]); } ꁼ 실행결과 수요일
9.3 열거형(계속) • 예제 9.25 • 열거형을 이용한 계산(전월 나타내기) ☑ 프로그램 #include <stdio.h> enum month {Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec}; typedef enum month mon; mon find_prev_mon(mon m) { return (mon)((m+11)%12); } void main(void) { mon cur_mon=Jan; char* m_name[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; printf("%s\n", m_name[find_prev_mon(cur_mon)]); } ꁼ 실행결과 December
9.4 형 정의 • 형 정의(typedef)는 프로그램 작성자가 데이터형을 자신이 만든 이름으로 바꾸어 준다. • 복잡한 선언을 간단한 이름으로 바꾸고자 할 때 많이 쓰이며, • 소문자를 사용해도 무방하지만, 대문자를 사용하여 다른 데이터형과 구별하는 것이 일반적이다. ■ 문법 typedef [기존의 데이터형] [새로운 데이터형] • 예제 9.26 • 일반적인 사용예 ☑ 프로그램 typedef float REAL typedef unsigned char BYTE void main() { REAL t; // = float t BYTE ch; // = unsigned char ch }
9.4 형 정의(계속) • 예제 9.27 • 문자형 typedef 선언의 예 ☑ 프로그램 #include <stdio.h> typedef char string[80]; void main() { string a, b; strcpy(a, "typedef의 시험용"); strcpy(b, "문자열이다."); printf("이것은 %s %s \n", a, b); } ꁼ 실행결과 이것은 typedef의 시험용 문자열이다.
9.4 형 정의(계속) • 예제 9.28 • 변수의 대입이 잘못된 예 ☑ 프로그램 #include <stdio.h> #include <string.h> typedef char string[80]; void main() { string a, b; strcpy(a, "이것은 시험용"); b=a; /*변수 a와 b는 배열*/ printf("이것은 %s %s \n", a, b); }
9.4 형 정의(계속) • 예제 9.29 • 형 정의(typedef)와 구조체 ☑ 프로그램 #include <stdio.h> typedef struct person { char name[10], street[20]; int id; } person; void read_info(struct person *a_person) { printf("이름을 입력하시오 : "); scanf("%s", a_person ->name); printf("%s가 살고 있는 거리를 입력하시오 : ", a_person->name); scanf("%s", a_person ->street); printf("%s의 id를 숫자로 입력하시오 : ", a_person->name); scanf("%d",&(a_person->id)); } void main() { person people[5]; int i; for(i=0; i<5;i++) { read_info(&people[i]); } printf("people[1]의 이름은 %s, 사는 곳은 %s, id는 %d.\n", people[1].name, people[1].street,people[1].id); }
9.4 형 정의(계속) • 예제 9.30 • 형 정의(typedef)와 열거형 ☑ 프로그램 #include <stdio.h> typedef enum { false, true } boolean; /* 열거형 boolean 정의 */ void main() { /* 열거형 color 정의와 변수선언 */ enum color{ white, red, blue, green, black } farbe; int a[5], i; boolean yesno; yesno=true; if (yesno) { for (farbe=white; farbe<=black; farbe++) scanf("%d", &a[farbe]); /*열거형 변수를 배열의 첨자로 사용*/ } for (farbe=white; farbe<=black; farbe++) printf("%d, %d ", a[farbe], farbe); printf("\n"); for (i=0; i<5; i++) /* 정수형 변수를 첨자로 사용 */ printf("%d ", a[i]); } ꁾ 입력 1 2 3 4 5 ꁼ 실행결과 1, 0 2, 1 3, 2 4, 3 5, 4 1 2 3 4 5