Trivia
8강.구조체(2) 본문
8.1 구조체 배열
▶구조체가 여러 개 모인 구조
①선언: int, char 배열을 선언하는 것과 유사(단, struct가 붙음)
struct student {
int number;
char name[10];
double grade;
};
int main()
{
struct student list[100]; //구조체의 배열 선언
list[2].number = 201812300;
strcpy(list[2].name,"홍길동");
list[2].grade = 3.7;
②초기화: 배열 초기화 안에 구조체 초기화가 들어가야 하므로 중괄호 안에 중괄호가 필요
struct student list[3] = {
{ 1, "Lee", 160 },
{ 2, "Son", 164 },
{ 3, "Min", 173 }
};
cf) 각 요소들의 초기화 값 사이에는 콤마(,)가 존재
ex) 예제 프로그램
#include <stdio.h>
#include <stdlib.h>
#define SIZE 3
struct student {
int number;
char name[10];
double grade;
};
int main()
{
struct student list[SIZE];
int i;
for(i=0; i < SIZE; i++)
{
printf("%d번째 학생\n", i+1);
printf("학번을 입력하시오:");
scanf("%d", &list[i].number);
printf("이름을 입력하시오:");
scanf("%s", &list[i].name);
printf("학점을 입력하시오:");
scanf("%lf", &list[i].grade);
printf("\n");
}
for(i=0; i < SIZE; i++)
printf("학번:%d, 이름:%s, 학점:%f\n", list[i].number, list[i].name, list[i].grade);
return 0;
}
8.2 구조체와 포인터
▶구조체에서 포인터가 사용되는 경우
①구조체를 가르키는 포인터
struct student s = {201812300, "홍길동", 3.5};
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);
- 포인터 p: student 구조체를 가르킬 수 있는 포인터
- 구조체 포인터 p와 구조체 변수 s를 연결하려면 s의 주소를 추출하여 p에 대입
1. → 연산자
- 간접 멤버 연산자
- 구조체 포인터를 이용하여 멤버에 접근하기 위해 사용
ex) p → number : 포인터 p가 가리키는 구조체의 멤버 number라는 의미
2.구조체 변수와 포인터의 조합
- (*p).number: 포인터 p가 가리키는 구조체의 멤버 number를 의미
- *p.number: 연산자 우선순위에 의해 *(p.number)와 동일
구조체 p의 멤버 number가 가리키는 것을 의미
(number는 반드시 포인터이고, 아닐 경우 오류 처리)
- *p→number: 연산자 우선순위에 의해 *(p → number)와 동일
p가 가리키는 구조체의 멤버 number가 가리키는 내용을 의미
(number는 반드시 포인터이고, 아닐 경우 오류 처리)
ex) 예제 프로그램
//포인터를 통한 구조체 참조
#include <stdio.h>
#include <stdlib.h>
struct student{ //구조체 선언(정의)
int number;
char name[10];
double grade;
};
int main()
{
struct student s={201812300, "홍길동", 3.9}; //구조체 변수 선언
struct student *p;
p=&s; //s의 주소를 p에 대입
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;
}
학번=201812300, 이름=홍길동, 학점=3.900000
학번=201812300, 이름=홍길동, 학점=3.900000
학번=201812300, 이름=홍길동, 학점=3.900000
②포인터를 멤버로 가지는 구조체
ex) 예제 프로그램
#include <stdio.h>
#include <stdlib.h>
struct date{
int year;
int month;
int day;
};
struct student{
int number;
char name[10];
double grade;
struct date *dob;
};
int main()
{
struct student s={201812300, "홍길동", 3.9};
struct date d={1995, 12, 30};
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;
}
학번:201812300
이름:홍길동,
학점:3.900000
생년월일:1995년 12월 30일
8.3 구조체와 함수
▶구조체는 함수의 인수로 사용 가능, 함수에서 반환값으로 반환도 가능
▶"값에 의한 호출(call by value)" 원직이 적용: 구조체 변수의 모든 내용이 복사되어 함수로 전달/반환
▶구조체를 함수의 인수로 넘기는 방법
- 구조체의 복사본이 함수로 전달
- 구조체의 크기가 크면 그만큼 시간과 메모리가 소요
▶구조체의 포인터를 함수의 인수로 넘기는 방법
- 시간과 공간을 절약
- 원본 훼손의 가능성 존재
▶원본 데이터 훼손 방지 방법
- const 키워드 사용: 변수 앞에 사용 시 값과 주소 변경 불가능 (변수를 상수화)
int equal(struct student const *p1, struct student const *p2)
{
if(strcmp(p1->name, p2->name) == 0)
return 1;
else
return 0;
}
▶구조체를 함수의 반환값으로 전달하는 방법
- 반환값의 형을 구조체로 표시
- 원본이 아닌 복사본이 전달
- 한 번에 여러 개의 값의 반환이 가능
[응용예제 8.1] 상품 5개의 정보를 저장할 수 있는 구조체의 배열을 정의하시오.
(단, 상품은 번호, 이름, 가격을 멤버로 가진다.)
[답] struct product {
int number;
char name[10];
int price;
}
struct product parry[5];
[응용예제 8.2] 구조체를 가리키는 포인터 변수 p를 통하여 구조체 안의 변수 salary를 참조하는
표현으로 옳은 것은?
①p->salary ②p.salary ③(*p).salary ④p-salary
[답] ①, ③
[응용예제 8.3] 각 메뉴의 이름, 열량 정보를 구조체로 표현한다.
각각의 식사 코스에서 등장하는 음식들을 구조체의 배열로 표현하고 각 코스의
전체 열량을 계산하는 프로그램을 작성하시오.
[답] #include <stdio.h>
#include <stdlib.h>
struct menu {
int number;
char name[10];
int cal;
}
int total_calories(struct food arrary[], int size);
int main()
{
struct menu m_arr[3]={{1, "hamburger", 900}, {2, "pizza", 500}, {3, "chicken", 700}};
int total=total_calories{food_array, 3};
printf("%d\n", total);
return 0;
}
int total_calories(struct m_arr[], int size)
{
int i, total=0;
for(i=0; i<size; i++)
{
total +=arr[i].cal;
}
return total;
}