14 주차구조체와공용체
구조체의개념, 정의, 초기화방법 구조체와포인터와의관계 공용체와 typedef
자료형구조 자료형 (data type) 기초자료형 파생자료형 사용자정의자료형 char int float double void 배열포인터구조체공용체 typedef enum
구조체의용도 복잡한형태의데이터란한가지형태의자료가아닌복합형의자료로구성되어있어기본자료형이나배열로는표현하기힘든형태의데이터를말한다. 예를들어다음과같은형태의데이터를말한다. 성적데이터 : 학생이름, 학번, 국어성적, 영어성적, 수학성적, 총점, 평균, 학점, 석차,... 신상카드데이터 : 성명, 주소, 주민등록번호, 나이, 체중, 전화번호, 이력사항, 종교,... 하나의구조체안에는여러개의다양한형식의데이터를구성할수있다. 구조체안에구성하는데이터는멤버변수라고하며, 구조체의멤버변수가될수있는자료들은기본자료형이나배열등이올수있다. 이렇게구조체는여러개의데이터를하나로묶어주는기능이있어복잡한형태의데이터를구성하고관리할수있는것이다.
구조체 vs 배열
구조체선언형식 struct 태그 { 자료형멤버1; 자료형멤버2;...
구조체선언의예 // x 값과 y 값으로이루어지는화면의좌표 struct point { // 사각형 struct rect { int x; // x 좌표 int x; int y; // y 좌표 int y; int width; int grade; // 복소수 struct complex { double real; double imag; // 실수부 // 허수부 // 직원 struct employee { char name[20]; // 이름 // 날짜 struct date { int month; int day; int age; int gender; int salary; // 성별 // 월급 // 나이 int year;
구조체정의와구조체변수선언
중괄호를이용하여구조체초기화 struct student { int number; char name[10]; double grade; struct student s1 = { 24, "Kim", 4.3
구조체멤버참조방법 구조체멤버를참조하려면다음과같이. 연산자를사용한다. s1.number = 26; strcpy(s1.name, "Kim"); s1.grade = 4.3; // 정수멤버 // 문자열멤버 // 실수멤버.. 기호는구조체에서멤버를참조할때사용하는연산자입니다
예제 struct student { int number; char name[10]; double grade; 구조체선언 int main(void) { struct student s; s.number = 20070001; strcpy(s.name," 홍길동 "); s.grade = 4.3; 구조체변수선언 구조체멤버참조 printf(" 학번 : %d\n", s.number); printf(" 이름 : %s\n", s.name); printf( 학점 : %f\n", s.grade); return 0;
예제 struct student { int number; char name[10]; double grade; 구조체선언 int main(void) { struct student s; printf(" 학번을입력하시오 : "); scanf("%d", &s.number); 구조체변수선언 구조체멤버의주소전달 printf(" 이름을입력하시오 : "); scanf("%s", s.name); printf(" 학점을입력하시오 ( 실수 ): "); scanf("%lf", &s.grade); printf(" 학번 : %d\n", s.number); printf(" 이름 : %s\n", s.name); printf(" 학점 : %f\n", s.grade); return 0;
예제 #include <math.h> struct point { int x; int y; int main(void) { struct point p1, p2; int xdiff, ydiff; double dist; printf(" 점의좌표를입력하시오 (x y): "); scanf("%d %d", &p1.x, &p1.y); printf(" 점의좌표를입력하시오 (x y): "); scanf("%d %d", &p2.x, &p2.y); xdiff = p1.x - p2.x; ydiff = p1.y - p2.y; dist = sqrt(xdiff * xdiff + ydiff * ydiff); printf(" 두점사이의거리는 %f 입니다.\n", dist); return 0;
구조체를멤버로가지는구조체 struct date { int year; int month; int day; // 구조체선언 struct student { // 구조체선언 int number; char name[10]; struct date dob; // 구조체안에구조체포함 double grade; struct student s1; // 구조체변수선언 s1.dob.year = 1983; s1.dob.month = 03; s1.dob.day = 29; // 멤버참조
예제 #include <stdio.h> struct point { int x; int y; struct rect { struct point p1; struct point p2; int main(void) { struct rect r; int w, h, area, peri;
예제 printf(" 왼쪽상단의좌표를입력하시오 : "); scanf("%d %d", &r.p1.x, &r.p1.y); printf(" 오른쪽상단의좌표를입력하시오 : "); scanf("%d %d", &r.p2.x, &r.p2.y); w = r.p2.x - r.p1.x; h = r.p2.x - r.p1.x; area = w * h; peri = 2 * w + 2 * h; printf(" 면적은 %d 이고둘레는 %d 입니다.\n", area, peri); return 0;
구조체변수의대입과비교 struct point { int x; int y; int main(void) { struct point p1 = {10, 20 struct point p2 = {30, 40 p2 = p1; // 대입가능 if( p1 == p2 ) // 비교 -> 컴파일오류!! printf("p1 와 p2 이같습니다.") if( (p1.x == p2.x) && (p1.y == p2.y) ) printf("p1와 p2이같습니다.") // 올바른비교
구조체배열 struct student { int number; char name[20]; double grade; int main(void) { struct student list[100]; // 구조체의배열선언 list[2].number = 27; strcpy(list[2].name, " 홍길동 "); list[2].grade = 178.0;
구조체를가리키는포인터 struct student *p; struct student s = { 20070001, " 홍길동 ", 4.3 struct student *p; p = &s; printf(" 학번 =%d 이름 =%s 학점 =%f \n", s.number, s.name, s.grade); printf(" 학번 =%d 이름 =%s 학점 =%f \n", (*p).number,(*p).name,(*p).grade);
-> 연산자 struct student *p; struct student s = { 20070001, " 홍길동 ", 180.2 struct student *p; p = &s; printf(" 학번 =%d 이름 =%s 키 =%f \n", s.number, s.name, s.grade); printf(" 학번 =%d 이름 =%s 키 =%f \n", (*p).number,(*p).name,(*p).grade); printf(" 학번 =%d 이름 =%s 키 =%f \n", p->number, p->name, p->grade);
예제 // 포인터를통한구조체참조 #include <stdio.h> struct student { int number; char name[20]; double grade; int main(void) { struct student s = { 20070001, " 홍길동 ", 4.3 struct student *p; p = &s; printf(" 학번 =%d 이름 =%s 키 =%f \n", s.number, s.name, s.grade); printf(" 학번 =%d 이름 =%s 키 =%f \n", (*p).number,(*p).name,(*p).grade); printf(" 학번 =%d 이름 =%s 키 =%f \n", p->number, p->name, p->grade); return 0;
포인터를멤버로가지는구조체 struct date { int month; int day; int year; struct student { int number; char name[20]; double grade; struct date *dob;
예제 int main(void) { struct date d = { 3, 20, 1980 struct student s = { 20070001, "Kim", 4.3 s.dob = &d; printf(" 학번 : %d\n", s.number); printf(" 이름 : %s\n", s.name); printf(" 학점 : %f\n", s.grade); printf(" 생년월일 : %d 년 %d 월 %d 일 \n", s.dob->year, s.dob->month, s.dob->day ); return 0;
공용체 공용체 (union) 같은메모리영역을여러개의변수가공유 공용체를선언하고사용하는방법은구조체와아주비슷 union example { char c; int i; // 같은공간공유 // 같은공간공유
예제 #include <stdio.h> union example { int i; char c; int main(void) { union example v; 공용체선언 공용체변수선언. char 형으로참조. v.c = 'A'; printf("v.c:%c v.i:%i\n", v.c, v.i ); v.i = 10000; printf("v.c:%c v.i:%i\n", v.c, v.i); int 형으로참조.
예제 #include <stdio.h> union ip_address { unsigned long laddr; unsigned char saddr[4]; int main(void) { union ip_address addr; addr.saddr[0] = 1; addr.saddr[1] = 0; addr.saddr[2] = 0; addr.saddr[3] = 127; printf("%x\n", addr.laddr); return 0;
공용체에서타입필드사용 #include <stdio.h> #include <string.h> #define STU_NUMBER 1 #define REG_NUMBER 2 struct student { int type; union { int stu_number; char reg_number[15]; id; char name[20]; // 학번 // 주민등록번호
공용체에타입필드사용 void print(struct student s) { switch(s.type) { case STU_NUMBER: printf(" 학번 %d\n", s.id.stu_number); printf(" 이름 : %s\n", s.name); break; case REG_NUMBER: printf(" 주민등록번호 : %s\n", s.id.reg_number); printf(" 이름 : %s\n", s.name); break; default: printf(" 타입오류 \n"); break;
공용체에타입필드사용 int main(void) { struct student s1, s2; s1.type = STU_NUMBER; s1.id.stu_number = 20070001; strcpy(s1.name, " 홍길동 "); s2.type = REG_NUMBER; strcpy(s2.id.reg_number, "860101-1056076"); strcpy(s2.name, " 김철수 "); print(s1); print(s2);
열거형 (enumeration) enum days { SUN, MON, TUE, WED, THU, FRI, SAT enum days today; today = SUN; // OK! 열거형 (enumeration) 이란변수가가질수있는값들을미리열거해놓은자료형 ( 예 ) 요일을저장하고있는변수는 { 일요일, 월요일, 화요일, 수요일, 목요일, 금요일, 토요일 중의하나의값만가질수있다.
enum days { SUN, MON, TUE, WED, THU, FRI, SAT // SUN=0, MON=1,... enum days { SUN=1, MON, TUE, WED, THU, FRI, SAT // SUN=1, MON=2,... enum days { SUN=7, MON=1, TUE, WED, THU, FRI, SAT=6 // SUN=7, MON=1,... 다음과같이프로그램을작성할수있다. int today; today = 0; // 일요일 today = 1; // 월요일 되도록오류를줄이고가독성을높여야된다. 0 보다는 SUN 라는기호상수가더바람직하다. 의미를쉽게알수있기때문이다. today 에 9 와같은의미없는값이대입되지않도록미리차단하는것도필요하다.
예제 #include <stdio.h> enum days { SUN, MON, TUE, WED, THU, FRI, SAT char *days_name[] = { "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" int main(void) { enum days d; d = WED; printf("%d번째요일은 %s입니다\n", d, days_name[d]); return 0;
정수, 상수, 열거형 정수사용기호상수열거형 switch(code) { case 1: printf("lcd TV\n"); break; case 2: printf("pdp TV\n"); break; #define LCD 1 #define PDP 2 switch(code) { case LCD: printf("lcd TV\n"); break; case PDP: printf("pdp TV\n"); break; enum tvtype { LCD, PDP enum tvtype code; switch(code) { case LCD: printf("lcd TV\n"); break; case PDP: printf("pdp TV\n"); break; 컴퓨터는알기쉬우나사람은기억하기어렵다. 기호상수를작성할때오류를저지를수있다. 컴파일러가중복이일어나지않도록체크한다.
typedef 의사용 typedef 은새로운자료형 (type) 을정의 (define) C 의기본자료형을확장시키는역할 typedef old_type new_type; 예 ) typedef unsiged char BYTE; BYTE index; // unsigned int index; 와같다. typedef int INT32; typedef unsigned int UINT32; INT32 i; // int i; 와같다. UINT32 k; // unsigned int k; 와같다.
Quiz 구조체와공용체의사용용도에대하여설명하시오. 배열의이름은배열을가리키는포인터처럼동작한다. 하지만구조체의이름도구조체를가리키는포인터인가? 열거형과 #define 을사용하는방법의차이점은무엇인가? 다음과같이함수안에서구조체를반환하는경우에무엇이반환되는가? 이역변수 s 는함수가종료되면소멸되는데괜찮은가? struct tag1 f() { struct tag1 s; return s;