1 / 40

쉽게 풀어쓴 C 언어 Express

제 13 장 구조체. 쉽게 풀어쓴 C 언어 Express. C Express. 이번 장에서 학습할 내용. 구조체는 서로 다른 데이터들을 하나로 묶는 중요한 도구입니다. 구조체 구조체와 포인터 공용체 열거형 typedef. 자료형의 분류. 기본 자료형 : char , int , float, double, …. 자료형. 파생 자료형 : 배열 , 구조체 , 공용체 , …. 구조체의 필요성. 학생 데이터를 하나로 묶어서 처리하려면 ?. 구조체를 사용하면 변수들을 하나로 묶을 수 있습니다.

kamana
Download Presentation

쉽게 풀어쓴 C 언어 Express

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 제13장 구조체 쉽게 풀어쓴 C언어 Express C Express

  2. 이번 장에서 학습할 내용 구조체는 서로 다른 데이터들을 하나로 묶는 중요한 도구입니다. • 구조체 • 구조체와 포인터 • 공용체 • 열거형 • typedef

  3. 자료형의 분류 기본 자료형:char, int, float, double, … 자료형 파생 자료형:배열, 구조체, 공용체, …

  4. 구조체의 필요성 • 학생 데이터를 하나로 묶어서 처리하려면? 구조체를 사용하면 변수들을 하나로 묶을 수 있습니다. int number; char name[10]; double grade;

  5. 구조체와 배열 • 구조체(structure): 레코드(record) 다른 타입의 집합 같은 타입의 집합

  6. 구조체 선언 태그(tag): 이름 • 구조체 선언 형식 struct태그 { 자료형 멤버1; 자료형 멤버2; ... }; structstudent { intnumber; char name[10]; double grade; }; 멤버(필드)

  7. 구조체 선언의 예 // x,y값으로 이루어지는 화면의 좌표 struct point { int x; // x 좌표 int y; // y 좌표 }; // 직사각형 structrect { intx, y; intwidth, height; }; // 복소수 struct complex { double real; // 실수부 double imag; // 허수부 }; // 직원 struct employee { char name[20]; // 이름 int age; // 나이 intsex;// 성별 int salary; // 월급 }; // 날짜 struct date { int month; int day; int year; };

  8. 구조체 변수 선언 • 구조체 정의(선언)와 구조체 변수 선언은 다름 • 구조체 정의: 사용자 정의 자료형 선언

  9. 구조체의 초기화 • 중괄호를 이용하여 초깃값 나열 struct student { intnumber; charname[10]; doublegrade; }; struct student s1 = { 24, "Kim", 4.3 };

  10. 구조체 멤버 참조 • 구조체 멤버 참조 연산자: . struct student { int number; char name[10]; double grade; }; struct student s1; s1.number = 24; strcpy(s1.name, "Kim"); s1.grade = 4.3;

  11. 예제 #include<stdio.h> #include<string.h> structstudent { int number; char name[10]; doublegrade; }; 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; } 학번: 20070001 이름: 홍길동 학점: 4.300000

  12. 예제 #include<stdio.h> structstudent { int number; char name[10]; double grade; }; intmain(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; } 학번을 입력하시오: 20070001 이름을 입력하시오: 홍길동 학점을 입력하시오(실수): 4.3 학번: 20070001 이름: 홍길동 학점: 4.300000

  13. 예제 #include<stdio.h> #include<math.h> structpoint { int x, y; }; int main(void) { struct point p1, p2; intxdiff, 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; } 점의 좌표를 입력하시오(x y): 10 10 점의 좌표를 입력하시오(x y): 20 20 두 점 사이의 거리는 14.142136입니다. p2 (x,y) p1 (x,y)

  14. 구조체 중첩 struct date { int month; int day; int year; }; struct student { intnumber; charname[10]; structdate dob; // 구조체 안에 구조체 포함 doublegrade; }; struct student s1; s1.dob.month = 3; s1.dob.day = 29; s1.dob.year = 1983; s1 number name dob grade month day year

  15. 예제 #include<stdio.h> struct point { int x, y; }; structrect { struct point p1, p2; }; int main(void) { structrect 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.y - r.p1.y; area = w * h; peri= 2 * (w + h); printf("면적은 %d이고둘레는 %d입니다.\n", area, peri); return 0; } 왼쪽 상단의 좌표를 입력하시오: 1 1 오른쪽 하단의 좌표를 입력하시오: 6 6 면적은 25이고 둘레는 20입니다. x y

  16. 구조체 변수의 대입과 비교 • 같은 타입의 구조체 변수끼리 대입은 가능하지만 비교는 불가능 structpoint { int x, 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가같습니다."); return 0; }

  17. 구조체 배열 • 구조체 배열의 선언 struct student { int number; charname[10]; double grade; }; structstudent list[3]; list[1].number = 24; strcpy(list[1].name, "Kim"); list[1].grade = 4.3; • 구조체 배열의 초기화 structstudent list[3] = { { 25, "Mun", 3.92 }, { 24, "Kim", 4.3 }, { 23, "Tim", 2.9 } };

  18. 예제 #include<stdio.h> #define SIZE 3 structstudent { int number; char name[20]; double grade; }; int main(void) { struct student list[SIZE]; inti; for (i = 0; i < SIZE; i++) { printf("학번을입력하시오: "); scanf("%d", &list[i].number); printf("이름을입력하시오: "); scanf("%s", list[i].name); printf("학점을입력하시오(실수): "); scanf("%lf", &list[i].grade); } for (i = 0; i < SIZE; i++) printf("학번: %d, 이름: %s, 학점: %f\n", list[i].number, list[i].name, list[i].grade); return 0; } 학번을 입력하시오: 20070001 이름을 입력하시오: 홍길동 학점을 입력하시오(실수): 4.3 학번을 입력하시오: 20070002 이름을 입력하시오: 김유신 학점을 입력하시오(실수): 3.92 학번을 입력하시오: 20070003 이름을 입력하시오: 이성계 학점을 입력하시오(실수): 2.87 학번: 20070001, 이름: 홍길동, 학점: 4.300000 학번: 20070002, 이름: 김유신, 학점: 3.920000 학번: 20070003, 이름: 이성계, 학점: 2.870000

  19. 구조체를 가리키는 포인터 • 구조체를 가리키는 포인터 struct student { int number; char name[10]; double grade; }; structstudent s = { 20070001, "홍길동", 4.3 }; struct student *p = &s; printf("학번=%d ,이름=%s, 학점=%f \n", s.number, s.name, s.grade); printf("학번=%d, 이름=%s, 학점=%f \n", (*p).number, (*p).name, (*p).grade); intn = 3; struct s { int *ptr; … } p; p.ptr = &n; *p.ptr = 4; // *(p.ptr) = 4;  n = 4; n p ptr … 3  4

  20. ->연산자 • -> : 포인터로 구조체 멤버를 참조할 때 사용(*p).member  p->member #include<stdio.h> struct student { int number; char name[20]; double grade; }; int main(void) { struct student s = { 20070001, "홍길동", 4.3 }; struct student *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; } 학번=20070001, 이름=홍길동,학점=4.300000 학번=20070001, 이름=홍길동,학점=4.300000 학번=20070001, 이름=홍길동,학점=4.300000

  21. 포인터 멤버를 가지는 구조체 #include<stdio.h> struct date { int month, day, year; }; struct student { int number; char name[20]; double grade; structdate *dob; }; intmain(void) { struct date d = { 3, 20, 1980 }; struct student s = { 20070001, "Kim", 4.3, &d }; // 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; } s number name grade dob month day year 학번: 20070001 이름: Kim 학점: 4.300000 생년월일: 1980년 3월 20일

  22. 구조체와 함수 • 구조체를 함수의 인자로 전달하는 경우 • 복사본 전달 • 구조체가 크면 시간과 메모리 측면에서 비효율적 • 구조체의 포인터를 함수의 인자로 전달하는 경우 • 시간과 메모리 절약가능 • 원본 훼손 가능 • 읽기만 하고 변경하지 않는 경우: const선언 intf(structstudent s) { … } intf(structstudent *p) { … } intf(conststructstudent *p) { … } 포인터를 통한 구조체 변경 방지

  23. 구조체인자와 구조체 반환 #include<stdio.h> structvector { float x, y; }; struct vector get_vector_sum(struct vector a, struct vector b); int main(void) { struct vector a = { 2.0F, 3.0F }, b = { 5.0F, 6.0F }, sum; sum = get_vector_sum(a, b); printf("벡터의합은 (%f, %f)입니다.\n", sum.x, sum.y); return 0; } struct vector get_vector_sum(struct vector a, struct vector b) { struct vector result; result.x = a.x + b.x; result.y = a.y + b.y; return result; } 벡터의 합은 (7.000000, 9.000000)입니다.

  24. 구조체 포인터 인자 #include<stdio.h> structvector { float x, y; }; void vector_input(structvector *p); void vector_output(const struct vector *p); int main(void) { struct vector v; vector_input(&v); vector_output(&v); return 0; } void vector_input(struct vector *p) { printf("벡터입력: "); scanf("%f %f", &p->x, &p->y); } void vector_output(const struct vector *p) { printf("(%g, %g)", p->x, p->y); } 벡터 입력: 1.2 3.4 (1.2, 3.4)

  25. 구조체 포인터 반환 #include<stdio.h> structvector { float x, y; }; structvector*vector_input(structvector *p); void vector_output(const struct vector *p); int main(void) { struct vector v; vector_output(vector_input(&v)); return 0; } structvector*vector_input(struct vector *p) { printf("벡터입력: "); scanf("%f %f", &p->x, &p->y); return p; } void vector_output(const struct vector *p) { printf("(%g, %g)", p->x, p->y); } 벡터 입력: 1.2 3.4 (1.2, 3.4)

  26. 인자 전달: 배열과 구조체 • 배열인자: 포인터로 전달(원본 전달) • 구조체: 복사본 전달 void f(intary[ ]) { ++ary[0]; } // void f(int*ary) { ++*(ary + 0); } … int a[3] = { 10, 20, 30 }; f(a); // a[0]: 11 structs_array { int a[3]; }; void f(structs_arraysa) { ++sa.a[0]; } … structs_array s = { { 10, 20, 30 } }; f(s); // s.a[0]: 10

  27. 공용체 • 공용체(union) • 같은 메모리 영역을 멤버들이 공유 • 공용체 선언 및 사용 방법은 구조체와 유사 union example { char c; // 메모리 공유 inti; // 메모리 공유 }; • 공용체는 첫째 멤버로만 초기화 가능 unionu_tag { float v; char *s; }; unionu_tag u = 3.4F; // O unionu_tag u = "name"; // X

  28. 예제 #include<stdio.h> union example { char c; inti; }; int main(void) { union example v; v.c = 'A'; printf("v.c= %c\n", v.c); v.i = 10000; printf("v.i = %d\n", v.i); return 0; } v.c = A v.i = 10000

  29. IP 주소 예제 #include<stdio.h> unionip_address { unsignedcharsaddr[4]; unsignedintiaddr; }; int main(void) { unionip_addressaddr = { 0x7F, 0x00, 0x00, 0x01 }; printf("%08X\n", addr.iaddr); return 0; } (little endian) (big endian) 0100007F (little endian) 7F000001 (big endian)

  30. 공용체 활용 예제 #include <stdio.h>// variable types#define INT 1#define REAL  2#define STR  3 structs_var { // variable structurechar *name;int type;union { // valueintival;doublerval;char *sval; } u;};voidout_var(conststructs_var *p);int main() {structs_var v; v.name = "n"; v.type = INT;v.u.ival = 1; out_var(&v); v.name = "r"; v.type = REAL;v.u.rval = 3.4; out_var(&v); v.name = "s"; v.type = STR;v.u.sval = "C Language"; out_var(&v); return0;}voidout_var(conststructs_var *p) {printf("%s: ", p->name);switch (p->type) {case INT:printf("INT, %d\n", p->u.ival); break;case REAL:printf("REAL, %g\n", p->u.rval); break;case STR:printf("STR, %s\n", p->u.sval); break;default:printf("unknown type\n"); break; }} n: INT, 1 r: REAL, 3.4 s: STR, C Language

  31. 구조체와 공용체의 크기 • 정렬 제한 조건(alignment constraint) // anonymous structure struct { char c; int n; } s; sizeof s : 8 union { char c; int n; } u; sizeof u : 4 struct { char a; char b; int n; } s; sizeof s : 8 struct { char a; int n; char b; } s; sizeof s : 12

  32. 열거형 • 열거형(enumeration type): 정수형 상수 심볼 정의 enum days { SUN, MON, TUE, WED, THU, FRI, SAT }; // 0, 1, 2, 3, 4, 5, 6 태그 이름 정수형 상수 심볼 열거형변수 enum days today; today = SUN; // today = 0; printf("%d\n", MON); // 1 #define SUN 0 #define MON 1 … #define SAT 6

  33. 열거형 • 기호 상수(symbolic constant) 정의 • literal을 사용하는 것보다 가독성이 좋고 수정이 용이 • #define보다 편리하고 오류 가능성이 적음 • 자동으로 연속된 값 설정 가능 • 블록 구조 적용 • 단점: 정수형 상수만 정의 가능 • #define PI 3.14 // O • #define UNIV "SKHU" // O • enum { PI = 3.14 }; // X • enum { UNIV = "SKHU" }; // X #define INT 1 #define REAL 2 #define STR 3 // anonymous enum enum { INT = 1, REAL, STR }; // 1, 2, 3

  34. 열거형

  35. 열거형 초기화 enum{ E0, E1 = 3, E2 };// E0 = 0, E1 = 3, E2 = 4 enum{ C1 = 'A', C2, C3 };// C1 = 'A', C2 = 'B', C3 = 'C' enumColors { Red = 0xFF << 16, Green = 0xFF << 8, Blue = 0xFF }; enum Boolean { FALSE, TRUE }; enum levels { low = 1, medium, high }; enumCarTypes{ sedan, suv, sports_car, van, pickup, convertible };

  36. 예제 #include<stdio.h> enumdays { SUN, MON, TUE, WED, THU, FRI, SAT }; char*days_name[ ] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; intmain(void) { enumdays d = WED; printf("%d번째 요일은 %s입니다\n", d, days_name[d]); return0; } 3번째 요일은 Wednesday입니다

  37. typedef • typedef: 기존 자료형에 새로운 타입 이름 부여 typedefold_typenew_type; typedefunsigedchar BYTE; BYTE index; // unsigned char index; typedefint INT32; typedefunsigned int UINT32; INT32 i; // inti; UINT32 k; // unsigned int k; struct point { int x, y; }; typedefstructpoint POINT; POINT a, b; // struct point a, b; typedef struct { int x, y; } POINT; POINT a, b; // struct { int x, y; } a, b;

  38. 예제 #include<stdio.h> typedefstruct { int x, y; } POINT; POINT move(POINT p, POINT delta); int main(void) { POINT p = { 2, 3 }, delta = { 10, 10 }, result; result = move(p, delta); printf("새로운점의좌표는 (%d, %d)입니다.\n", result.x, result.y); return 0; } POINT move(POINT p, POINT delta) { POINT new_p = { p.x + delta.x, p.y + delta.y }; returnnew_p; } 새로운 점의 좌표는 (12, 13)입니다.

  39. typedef • 이식성(portability) 향상 • 기계독립적인 코드 작성 가능 • typedef unsigned long size_t; • #define은블록 구조가 적용되지 않고, 타입 정의 기능이 제한적임 • 문서화 기능 • 별도의 주석 없이도 자체적으로 설명력이 있음  가독성 향상 • // int: 2B, long: 4B 인 경우 • typedef long INT32; // 4B 정수형 • // int: 4B, long: 8B 인 경우 • typedefint INT32; // 4B 정수형 • #define INT32 int • INT32 n; // int n; • #define String char * • String s1, s2; // char * s1, s2; • // s1: char *, s2: char • typedef char *String; • String s1, s2; // char *s1, *s2; • // s1: char *, s2: char * • typedefintHeight; • Height h1, h2; • typedefintWeight; • Weight w1, w2;

  40. 예제 #include<stdio.h> typedefstruct { intnumber; char name[20]; double grade; } Student; Student LIST[ ] = { { 20120001, "홍길동", 4.2 }, { 20120002, "김철수", 3.2 }, { 20120003, "김영희", 3.9 } }; int main(void) { Student *best = LIST; Student *p = LIST + 1; Student *end = LIST + (sizeofLIST / sizeofLIST[0]); for ( ; p < end; p++) if (p->grade > best->grade) best = p; printf("수석:%s, %d, %g\n", best->name, best->number, best->grade); return 0; } 수석: 홍길동, 20120001, 4.2

More Related