구조체
구조체의 형 선언과 멤버 참조
- 구조체는 배열처럼 여러 개의 변수를 묶어서 처리할 수 있는 방법을 제공
- 배열과 차이점은 다른 형태의 자료형도 함께 묶을 수 있다는 것이다
- struct예약어를 사용하여 구조체의 형태를 만든다
ex)
struct student{
int num;
double grade;
}; //세미콜론 꼭 붙여줘야 함
- 구조체 내의 멤버 참조 시 미리 선언해주어야 함
ex) struct student s;
- 구조체 내의 멤버들은 기억공간을 할당받지 않는다.
- 구조체는 사용자가 임의로 정의한 자료형
- 구조체 변수의 각 멤버를 참조하기 위해서 멤버참조 연산자 (.)을 사용
ex)
s.num=12;
s.grade=4.0;
예제 17-1) 구조체의 형 선언과 멤버 참조
과자 바사삭의 가격과 열량을 저장할 cracker구조체를 선언 후 가격과 열량을 키보드로 입력받아 화면에 출력
int main(){
struct cracker{
int price;
int cal;
};
struct cracker c;
printf("바사삭의 가격과 열량을 입력하세요 : ");
scanf("%d %d", &c.price, &c.cal);
printf("바사삭의 가격 : %d원", c.price);
printf("바사삭의 열량 : %dkcal", c.cal);
return 0;
}
결과
- 구조체의 멤버로 포인터 변수도 사용 가능하다.
- 포인터 변수를 멤버로 사용하는 경우 문자열을 간단히 연결할 수 있다.
- 하지만 문자열 저장을 위한 기억공간이 존재하지 않으므로 키보드로부터 새로운 문자열의 입력이 불가능하다.
- 구조체의 멤버로 다른 구조체를 사용할 수 있다.
ex)
struct profile{
int age;
double height;
char* np;
}
struct student{
struct profile pf;
int num;
int grade;
}
- 위의 경우 멤버참조를 두번하면 된다.
ex) s.pf.age=21;
예제17-2) 구조체 멤버의 참조
구조체의 포인터 멤버를 참조하여 키보드로부터 데이터를 입력받아 프로그램 실행하기
#include <stdlib.h>
struct profile{
int age;
double height;
char* np;
};
struct student{
struct profile pf;
int num;
double grade;
};
int main(){
struct student s1;
printf("나이를 입력하세요 : ");
scanf("%d", &s1.pf.age);
printf("키를 입력하세요 : ");
scanf("%d", &s1.pf.height);
s1.pf.np = (char*)malloc(sizeof(char)); //구조체의 포인터변수 멤버에 값을 입력하기 위해 동적할당을 해준다
printf("이름을 입력하세요 : ");
scanf("%s", s1.pf.np);
s1.num=5;
s1.grade=4.4;
printf("이름 : %s\n", s1.pf.np);
printf("나이 : %d\n", s1.pf.age);
printf(" 키 : %d\n", s1.pf.height);
printf("학번 : %d\n", s1.num);
printf("학점 : %.1lf\n", s1.grade);
return 0;
}
결과
- 구조체 변수를 선언하면 외부변수가 되므로 초기화를 해주지 않으면 모든 기억공간이 0으로 채워진다.
- 구조체 변수를 함수의 전달인자로 사용할 수 있다.
#include <stdio.h>
#include <stdlib.h>
struct student{
int age;
};
struct student add(struct student);
int main(){
struct student s1;
s1.age = 21;
printf("나이 : %d\n",s1.age);
s1 = add(s1); //함수 호출
printf("나이 : %d", s1.age);
return 0;
}
struct student add(struct student s2){
int a = 21;
s2.age = a + 10;
return s2;
}
결과
예제 17-3)구조체 변수를 전달인자로 받고 리턴하는 함수
student구조체 선언 후 평균 빼고 모두 초기화 해준다.
평균을 구하고 초기값을 리턴해주는 함수를 만든다.
메인함수에서 평균을 참조하여 출력한다.
#include <stdlib.h>
struct student{
int num;
char name[20];
int score[5];
double avg;
};
struct student average(struct student);
int main(){
struct student s = {14113346, "이주연", {90, 95, 100, 90, 100}};
s = average(s);
printf("평균 : %.1lf", s.avg);
return 0;
}
struct student average(struct student s){
double average=0;
printf("학번 : %d\n", s.num);
printf("이름 : %s\n", s.name);
printf("점수 : ");
for(int i=0;i<5;i++){
printf("%d\t", s.score[i]);
average += s.score[i];
}
s.avg = average/5.0;
printf("\n");
return s;
}
결과
구조체 배열
- 같은 형태의 구조체변수가 많이 필요할 경우 배열을 선언하여 사용할 수 있다.
ex)
구조체:
struct adress{
char name[20];
int age;
char tel[20];
char addr[80];
}
메인에서 구조체배열 선언&초기화:
struct adress list[5] = { {"이름1", 나이1, "전화번호1", "주소1"},
{"이름2", 나이2, "전화번호2", "주소2"},
{"이름3", 나이3, "전화번호3", "주소3"},
{"이름4", 나이4, "전화번호4", "주소4"},
{"이름5", 나이5, "전화번호5", "주소5"}};
#include <stdio.h>
struct address{
char name[20];
int age;
char tel[20];
char addr[80];
};
int main(){
struct address list[3]={{"이주연", 21, "010-1234-5678", "서울" },
{"지한별", 21, "010-9876-5432", "대전"},
{"홍서우", 21, "010-1111-2222", "서울" }};
for(int i=0;i<3;i++){
printf("%10s%5d%15s%20s\n", list[i].name, list[i].age, list[i].tel, list[i].addr);
}
return 0;
}
결과
구조체 포인터
- 구조체 전체를 가리키는 포인터
ex)
struct score{
int kor, eng, mat;
}
메인:
struct score a = {70, 90, 100};
struct score* sp = &a;
- 멤버참조 : (*sp).kor 또는 sp->kor
예제 17-4)구조체배열을 처리하는 함수
이름, 학점, 영어점수를 입력하여 엘리트의 데이터를 출력하는 프로그램
구조체 배열을 사용하여 키보드로부터 데이터를 입력받는다
엘리트는 학점 4.0이상 영어점수 900점 이상
struct profile{
char name[20];
double grade;
int english;
};
void input_data(struct profile *);
void elite(struct profile *);
int main(){
struct profile new_staff[5];
input_data(new_staff);
elite(new_staff);
return 0;
}
void input_data(struct profile *pf){
printf("이름, 학점, 영어점수\n");
for(int i=0;i<5;i++){
scanf("%s%lf%d", (pf+i) -> name, &(pf+i) -> grade, &(pf+i) ->english);
}printf("\n");
}
void elite(struct profile *pf){
for(int i=0;i<5;i++){
if((pf+i)->grade >= 4.0 && (pf+i)->english >= 900){
printf("이름 : %s, 학점 : %.1lf, 영어점수 : %d\n", (pf+i)->name, (pf+i)->grade, (pf+i)->english);
}
}
}
결과
공용체
- 공용체는 멤버들이 모두 같은 기억공간을 사용한다.
- 예약어 union사용
ex)union student{
int num;
double grade;
}
- 구조체와 비슷한 형태이다
union student{
int num;
double grade;
};
int main(){
union student s = {315};
printf("학번 : %d\n", s.num);
s.grade = 2.1;
printf("학점 : %lf\n", s.grade);
printf("학번 : %d", s.num);
return 0;
}
결과
학점에 데이터를 입력하여 학번의 데이터가 사라졌음을 알 수 있다.
열거형
- 기억공간에 저장될 데이터의 집합
- 예약어 enum사용
ex)enum seoson{spring, summer, fall, winter};
- 열거형 선언시 컴파일러는 실제로 멤버들을 정수형, 상수형으로 취급
enum season {spring, summer, fall, winter}; //열거형 사용
int main(){
enum season ss;
char* cp;
int select;
printf("계절을 선택하세요\n1.spring 2.summer 3.fall 4.winter\n");
scanf("%d", &select);
if(select==1) {ss = spring;}
else if(select == 2){ss=summer;}
else if(select == 3){ss=fall;}
else if(select == 4){ss=winter;}
else{printf("잘못된 번호입니다.");}
switch(ss){
case spring:
cp = "inline"; break;
case summer:
cp = "swimming"; break;
case fall:
cp = "trip"; break;
case winter:
cp = "skiing"; break;
}
printf("나의 레저활동은 %s\n", cp);
return 0;
}
결과
typedef를 사용한 형 재정의
- 자료형의 이름을 재정의하여 프로그램을 간결하게 작성할 수 있다.
typedef struct{
int num;
double grade;
}Student;
int main(){
Student s={14113346, 4.5}; //재정의 사용
data_prn(&s);
return 0;
}
printf("학번 : %d\n", sp->num);
printf("학점 : %.1lf\n", sp->grade);
}
결과