자료형의 분류
구조체의 필요성
// 구조체
struct student {
int number; //학번
char name[10]; //이름
double grade; //학점
};
배열과 구조체
- 배열: 서로 같은 타입의 변수들을 묶는다.
- 구조체: 서로 다른 타입의 변수들을 묶는다.
구조체 선언
// 구조체 선언: struct
struct student { // 구조체 이름
int number; // 구조체 멤버
char name[10];
double grade;
};
구조체 선언의 예
// x값과 y값으로 이루어지는 화면의 좌표
struct point {
int x;
int y;
};
// 날짜
struct date {
int month;
int day;
int year;
};
// 사각형
struct ractangle {
int x, y;
int width;
int height;
};
구조체 변수 선언
struct student { // 구조체 정의
int number;
char name[10];
double grade;
};
int main(void) {
struct student s1; // 구조체 변수 선언
}
구조체 초기화
struct student {
int number;
char name[10];
double grade;
};
struct student s1 = { 24, "Kim", 4.3 }; // 구조체 초기화
구조체 멤버 참조
s1.grade = 3.8; //구조체 변수, 구조체 멤버
struct student { // 구조체 선언
int number;
char name[10];
double grade;
};
int main(void) {
struct student s; // 구조체 변수 선언
s.number = 20230001; // 구조체 멤버 참조
strcpy(s.name, "이지원"); // 문자열: strcpy(문자열 복사 함수)
s.grade = 4.3;
printf("학번: %d\n", s.number);
printf("이름: %d\n", s.name);
printf("학점: %.2f\n", s.grade);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
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("\n학번: %d\n", s.number);
printf("이름: %s\n", s.name);
printf("학점: %.2f\n", s.grade);
return 0;
}
Lab: 2차원 공간 상의 점을 구조체로 표현하기
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
struct dot {
int x;
int y;
};
int main(void) {
struct dot p1;
struct dot p2;
printf("점의 좌표를 입력하시오(x, y): ");
scanf("%d%d", &p1.x, &p1.y);
printf("점의 좌표를 입력하시오(x, y): ");
scanf("%d%d", &p2.x, &p2.y);
double answer = sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
printf("거리는 %lf입니다.\n", answer);
return 0;
}
구조체를 멤버로 가지는 구조체
: 구조체 안에 구조체 포함
- struct date dob;
struct date {
int year;
int month;
int day;
};
struct student {
int number;
char name[10];
struct date dob; //구조체 안에 구조체 포함
double grade;
};
int main(void) {
struct student s1; //구조체 변수 선언
s1.dob.year = 2001;
s1.dob.month = 3;
s1.dob.day = 21;
}
Lab: 사각형을 point 구조체로 나타내기
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
struct point { //point 구조체
int x;
int y;
};
struct rect { //rect 구조체
struct point p1;
struct point p2;
};
int main(void) {
struct rect r; //rect 구조체 변수 선언
int w, h, area, peri;
printf("왼쪽 상단의 좌표를 입력하시오: ");
scanf("%d%d", &r.p1.x, &r.p2.y); //r.p1.x
printf("오른쪽 하단의 좌표를 입력하시오: ");
scanf("%d%d", &r.p2.x, &r.p2.y);
w = r.p2.x - r.p1.x;
h = r.p1.y - r.p2.x;
area = w * h;
peri = 2 * (w + h);
printf("면적은 %d이고, 둘레는 %d입니다.\n", area, peri);
return 0;
}
구조체 변수의 대입과 비교
- 같은 구조체 변수끼리 대입은 가능하지만, 비교는 불가능하다.
p2 = p1; //대입: 가능
p2.x = p1.x; //대입: 가능
if(p1==p2) //비교: 불가능!
if(p1.x==p2.x) //비교: 가능
#include <stdio.h>
struct point {
int x;
int y;
};
int main(void) {
struct point p1 = { 10, 20 };
struct point p2 = { 30, 40 };
p2 = p1; //대입 가능
if ((p1.x == p2.x) && (p1.y == p2.y))
printf("p1과 p2가 같습니다.\n");
return 0;
}
구조체 배열
: 구조체를 여러 개 모은 것
struct student {
int number;
char name[20];
double grade;
};
int main(void) {
struct student list[100]; //구조체 배열 선언
list[2].number = 24;
strcpy(list[2].name, "홍길동");
list[2].grade = 4.3;
}
구조체 배열의 초기화
struct student {
int name;
int stu_num;
};
int main(void) {
struct student list[3] = { // 구조체 배열의 초기화
{"Jiwon", 210000},
{"Leziwn", 220000}
};
}
구조체 배열의 요소 개수 자동 계산
- n = sizeof(list)/sizeof(list[0]);
- n = sizeof(list)/sizeof(struct student);
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define SIZE 3
struct student {
int number;
char name;
double grade;
};
int main(void) {
struct student list[SIZE];
int i;
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;
}
구조체와 포인터
구조체를 가리키는 포인터
#include <stdio.h>
struct student {
int number;
char name[20];
double grade;
};
int main(void) {
struct student* p; // 구조체를 가리키는 포인터
struct student s = { 24, "Kim", 4.3 };
p = &s; // p = &s
printf("학번 = %d, 이름 = %s, 학점 = %f\n", s.number, s.name, s.grade);
printf("학번 = %d, 이름 = %s, 학점 = %f\n", (*p).number, (*p).name, (*p).grade);
return 0;
}
-> 연산자
: 구조체 포인터로 구조체 멤버를 참조할 때 사용
- (*p).number
- p->number
struct student* p;
struct student s = { 24, "Kim", 4.3 };
p = &s;
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 = { 1, "홍길동", 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* dob; // dob 포인터 선언
s.dob = &d // dob 포인터가 가리키는 구조체 == d
s.dob->year // dob 포인터 값 출력
#include <stdio.h>
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, 3000 };
struct student s = { 1, "Kim", 4.3 };
s.dob = &d; // 포인터가 가리키는 구조체 == d
printf("학번: %d, 이름: %s, 학점: %f\n", s.number, s.name, s.grade);
printf("생년월일: %d년 %d월 %d일\n", s.dob->year, s.dob->month, s.dob->day);
return 0;
}
구조체와 함수
▶ 구조체를 함수의 인수로 전달하는 경우
- 구조체의 복사본이 함수로 전달되게 된다.
- 만약 구조체의 크기가 크면, 그만큼 시간과 메모리가 소요된다.
// 구조체의 함수를 인수로 전달하는 경우
int equal(struct student s1, struct student s2) {
if (s1.number == s2.number)
return 1;
else
return 0;
}
int main(void) {
struct student a = { 1, "Lee", 3.8 };
struct student b = { 2, "Kim", 3.5 };
if (equal(a, b) == 1)
printf("같은 학생\n");
else
printf("다른 학생\n");
return 0;
}
▶ 구조체의 포인터를 함수의 인수로 전달하는 경우
- 시간과 공간을 절약할 수 있다.
- 원본 훼손의 가능성이 있다.
// 구조체의 포인터를 함수의 인수로 전달하는 경우
int equal(struct student* p1, struct student* p2) {
if (p1->number == p2->number)
return 1;
else
return 0;
}
포인터를 통한 변경 금지
: 원본을 읽기만 하고 수정할 필요는 없는 경우, 매개변수를 정의할 때 const 키워드를 쓴다.
- const struct student *p1
int equal(const struct student* p1, const struct student* p2) { // const
if (p1->number == p2->number)
return 1;
else
return 0;
}
구조체를 반환하는 경우
: 복사본이 반환된다.
struct student create() {
struct student s;
s.number = 3;
strcpy(s.name, "Park");
s.grade = 4.0;
return s;
}
int main(void) {
struct student a;
a = create(); // 구조체 s가 구조체 a로 복사된다.
return 0;
}
Lab: 벡터 연산
#include <stdio.h>
struct vector {
double x;
double y;
};
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;
}
int main(void) {
struct vector a = { 2.0, 3.0 };
struct vector b = { 5.0, 6.0 };
struct vector sum;
sum = get_vector_sum(a, b);
printf("벡터의 합은 (%f, %f)입니다.\n", sum.x, sum.y);
return 0;
}
공용체(union)
- 같은 메모리 영역을 여러 개의 변수가 공유한다.
- 공용체를 선언하고 사용하는 방법은 구조체와 비슷하다.
union example {
char c; // 같은 공간 공유
int i; // 같은 공간 공유
};
#include <stdio.h>
union example { //공용체 선언
int i;
char c;
};
int main(void) {
union example v; //공용체 변수 선언
v.i = 1000;
v.c = 'A';
printf("v.c: %c, v.i: %i\n", v.c, v.i); //%i
return 0;
}
구조체와 공용체의 차이점
// 구조체
struct student {
int number;
char gender;
double grade;
} s1;
// 공용체
union student {
int number;
char gender;
double grade;
} s2;
공용체에 타입 필드 사용
#include <stdio.h>
#include <string.h>
#define STU_NUM 1
#define REG_NUM 2
struct student {
int type; //type 필드
union {
int stu_num; //학번
char reg_num; //주민등록번호
} id;
char name[20];
};
void print(struct student s) {
switch (s.type) { //s.type
case STU_NUM:
printf("학번: %d\n", s.id.stu_num);
printf("이름: %s\n", s.name);
break;
case REG_NUM:
printf("주민등록번호: %d\n", s.id.reg_num);
printf("이름: %s\n", s.name);
break;
default:
printf("타입 오류\n");
break;
}
}
int main(void) {
struct student s1, s2; //구조체 변수 선언
s1.type = STU_NUM;
s1.id.stu_num = 2176297;
strcpy(s1.name, "이지원");
s2.type = REG_NUM;
s2.id.reg_num = 2727291;
strcpy(s2.name, "이지나");
print(s1);
print(s2);
return 0;
}
열거형(enumeration)
: 변수가 가질 수 있는 값들을 미리 열거해놓은 자료형
- enum
// 열거형 정의
// enum 열거형이름(태그) 기호상수들
enum days { SUN, MON, TUE, WED, THU, FRI, SAT };
열거형 초기화
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}; //SUN=7, MON=1, TUE=2,...
열거형의 예
enum colors { white, red, blue, green, black };
enum boolean { false, true };
enum levels { low, medium, high };
#include <stdio.h>
enum days { SUN, MON, TUE, WED, THU, FRI, SAT }; // 열거형 정의
char* days_name[] = { // 문자열 포인터 배열
"sun", "mon", "tue", "wed", "thur", "fri", "sat"
};
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("OLED TV\n");
break;
}
/* 기호 상수 */
// 기호 상수를 작성할 때 오류가 생길 수 있다.
#define LCD 1
#define OLED 2
switch (code) {
case LCD:
printf("LCD TV\n");
break;
case OLED:
printf("OLED TV\n");
break;
}
/* 열거형 */
enum tvtype { LCD, OLED }; //열거형 정의
enum tvtype code; //열거형 변수 선언
switch (code) {
case LCD:
printf("LCD TV\n");
break;
case OLED:
printf("OLED TV\n");
break;
}
typedef
: 기본 자료형에 새로운 자료형을 추가하는 것
// typedef 정의
// typedef 기존자료형 new자료형
typedef unsigned char BYTE;
typedef unsigned char BYTE;
BYTE index; // unsiged int index;
typedef int INT32;
typedef unsigned int UINT32;
INT32 i; // int i;
UINT32 k; // unsigned int k;
구조체로 새로운 타입 정의
struct point { // 구조체 정의
int x;
int y;
};
typedef struct point POINT; // struct point --> POINT
POINT a, b;
typedef struct complex { // struct --> complex
double real;
double image;
} COMPLEX; // complex의 변수 COMPLEX
COMPLEX x, y;
Lab: 2차원 공간 상의 점을 POINT 타입으로 정의
#include <stdio.h>
// 구조체 정의: POINT라는 이름으로 x와 y 좌표를 가지는 구조체 정의
typedef struct point {
int x;
int y;
} POINT;
// 좌표 이동 함수: 현재 좌표 p와 이동량 delta를 받아서 새로운 좌표를 계산하여 반환
POINT translate(POINT p, POINT delta) {
POINT new_p;
// 새로운 x 좌표는 현재 x 좌표에 이동량의 x를 더한 값
new_p.x = p.x + delta.x;
// 새로운 y 좌표는 현재 y 좌표에 이동량의 y를 더한 값
new_p.y = p.y + delta.y;
return new_p; // 새로운 좌표를 반환
}
int main(void) {
// 초기 좌표와 이동량을 설정
POINT p = { 2, 3 }; // 초기 좌표 (2, 3)
POINT delta = { 10, 10 }; // 이동량 (10, 10)
POINT result; // 결과 좌표를 저장할 변수
// translate 함수를 호출하여 좌표를 이동시키고 결과를 result에 저장
result = translate(p, delta);
// 결과를 출력
printf("(%d, %d) + (%d, %d) -> (%d, %d)\n", p.x, p.y, delta.x, delta.y, result.x, result.y);
return 0;
}
'Programming > 컴퓨터프로그래밍및실습' 카테고리의 다른 글
[컴프실] 제12장: 문자와 문자열 (0) | 2023.08.27 |
---|---|
[컴프실] 제11장: 포인터 (0) | 2023.08.11 |
[컴프실] 제10장-2: 정렬 (0) | 2023.07.23 |
[컴프실] 9~12일차 실습문제 (0) | 2023.07.20 |
[컴프실] 제10장: 배열 (0) | 2023.07.19 |