C lang

[C language] Geany편집기 -13. Structure(구조체, 구조체 연결, 구조체 배열)

걍작 2022. 3. 29. 00:10

#정리

#struct - 1.basic 

//구조체(사용자 정의 자료형) : 사용자가 자료형을 만들어서 쓸 수 있다.

 - 자바의 클래스선언, 객체(오브젝트)사용과 비슷하다. >> struct 선언, struct 변수 사용

//구조체 선언 (**블록 뒤에 ;을 꼭 붙여줘야한다.**)

 - struct Test{ int x; char c2; double d; char name[10]; char *pt_name; };

//구조체 원소 초기화 방법 2가지
 - 1. 배열로 구조체 원소 초기화 :  struct Test2 t2 = {33,3.141592};

 - 2. 개별 원소 초기화 : t2.x = 22; / t2.d = 33.3;

//4byte를 기준으로, 용량이 부족하면 4byte 만큼씩 추가하면서 영역을 확보한다.

// 남는 공간(padding byte)제거 명령(Byte Alignment)

 - #pragma pack(1) // Byte Alignment를 한다 라고도 한다.

//printf("x start index: %d\n", offsetof(struct Test, x));//x의 인덱스를 알려줌.

 - #include <stddef.h>선언 필요
//문자열 배열은 바로 값을 넣지 못한다.

 -strcpy(t.name,"kim");


#struct_typedef - 2.타입 정의 활용 

//구조체 타입을 사용자가 정의한 형태로 변경하는 방법 2가지  

<1. (score)구조체 선언과 함께 typedef를 이용하여 사용자가 정의한 이름으로 구조체 타입명을 변경.>

 - typedef struct Score{ 원소 }SS; >> SS sc = {"kim",77,88,99,0,0,'F'}; //struct Score 타입을  SS 타입으로 변경

<2. (board)구조체 선언 후, 메인 실행문에서  typedef를 이용하여 사용자가 정의한 이름으로 구조체 타입명을 변경.>

 - typedef struct Board SB; //하지만, 메인 코드에서 이렇게 다 작성하게 되면 오히려 줄만 늘어나고 의미가 없다.

//(member) 구조체 타입 이름 없이, 변수 (mb) 선언까지 한 번에 할 수도 있다.

 - 단, 이경우 변수 초기화를 배열로 할 수 없고, 일일히 값을 넣어줘야한다.



#struct_inner - 3. 구조체를 구조체의 원소로 사용 

//struct inner : 다른 구조체를 구조체의 원소로 초기화
 - typedef struct student{ ~ Contact ctt; Score sc; }Student; //구조체를 원소로 하는 구조체 선언

 - st.ctt = ctt; //student st 구조체의 원소 Contact ctt에 ctt의 값을 할당.
 - printf("tel: %s\n",st.ctt.tel); //구조체 안의 구조체 값 출력.



#struct_array - 4.구조체 배열 다루기 
//구조체 배열도정수 배열 생성과 동일한 형태로 생성한다.
- Student sts[2] ={st, st2}; // (정수 배열 생성) int sus[2] = {su1,su2}; 

//특정 인덱스[i]가 가지는 원소(구조체 sc)의 안에 있는 값을 꺼낸다.
 - printf("total: %d, avg: %.2lf, grade: %c\n",sts[i].sc.total, sts[i].sc.avg, sts[i].sc.grade);

 

 

 

#struct - 1.basic 

//구조체(사용자 정의 자료형) : 사용자가 자료형을 만들어서 쓸 수 있다.

 - 자바의 클래스선언, 객체(오브젝트)사용과 비슷하다. >> struct 선언, struct 변수 사용

//구조체 선언 (**블록 뒤에 ;을 꼭 붙여줘야한다.**)

 - struct Test{ int x; char c2; double d; char name[10]; char *pt_name; };

//구조체 원소 초기화 방법 2가지
 - 1. 배열로 구조체 원소 초기화 :  struct Test2 t2 = {33,3.141592};

 - 2. 개별 원소 초기화 : t2.x = 22; / t2.d = 33.3;

//4byte를 기준으로, 용량이 부족하면 4byte 만큼씩 추가하면서 영역을 확보한다.

// 남는 공간(padding byte)제거 명령(Byte Alignment)

 - #pragma pack(1) // Byte Alignment를 한다 라고도 한다.

//printf("x start index: %d\n", offsetof(struct Test, x));//x의 인덱스를 알려줌.

 - #include <stddef.h>선언 필요
//문자열 배열은 바로 값을 넣지 못한다.

 -strcpy(t.name,"kim");

 

 

---------------------------------------

#mission : score /member /board

//board - 시스템에 내장된 시간 구조체 사용하여 시간 값을 받아옴.

 - localtime( );

 

 

--예문 코드 보기--

더보기
#include <stdio.h>
#include <time.h>

#pragma pack(1) //padding byte remove
struct Score{
	char *pt_name;
	int kor;
	int eng;
	int math;
	int total;
	double avg;
	char grade;
};
struct Member{
	int num;
	char *id;
	char *pw;
	char *name;
	char *tel;
};
struct Board{
	int num;
	char *title;
	char *content;
	char *writer;
	char *wdate;
};
char* local_time();

int main(int argc, char **argv)
{
	printf("structure score...\n");
	
	printf("--- score ---\n");
	struct Score sc = {"kim",77,88,99,0,0,'F'};
	sc.total = sc.kor + sc.eng + sc.math;
	sc.avg = sc.total/3;
	if(sc.avg>=90){
		sc.grade = 'A';
	}else if(sc.avg>=80){
		sc.grade = 'B';
	}else if(sc.avg>=70){
		sc.grade = 'C';
	}else if(sc.avg>=60){
		sc.grade = 'D';
	}else{
		sc.grade = 'F';
	}
	
	printf("name: %s\n",sc.pt_name);
	printf("kor: %d, eng: %d, math: %d\n",sc.kor, sc.eng, sc.math);
	printf("total: %d, avg: %.2lf, grade: %c\n",sc.total, sc.avg, sc.grade);
	
	printf("--- member ---\n");
	struct Member mb = {1,"admin","hi123456","kim","010-111"};
	printf("num:%d, id:%s, pw:%s, name:%s, tel:%s\n",mb.num,mb.id,mb.pw,mb.name,mb.tel);
	
	printf("--- board ---\n");
	struct Board bd = {1,"title1","content1","lee",local_time()};
	printf("num:%d, title:%s, content:%s, writer:%s, wdate:%s\n",bd.num, bd.title, bd.content, bd.writer, bd.wdate);

	
	return 0;
}

char* local_time(){
	struct tm *pt_time; //시스템에 내장된 구조체 사용
	time_t time_now;
	time(&time_now);
	printf("time_now:%ld\n",time_now);
	
	pt_time = localtime(&time_now);
	printf("time:%s\n",asctime(pt_time));//long타입의 시간을 문자열로 변환
	
	char *wdate = asctime(pt_time);
	printf("wdate:%s\n",wdate);
	
	return wdate;
}

 

 

 

#struct_typedef - 2.타입 정의 활용 

//구조체 타입을 사용자가 정의한 형태로 변경하는 방법 2가지  

<1. (score)구조체 선언과 함께 typedef를 이용하여 사용자가 정의한 이름으로 구조체 타입명을 변경.>

 - typedef struct Score{ 원소 }SS; >> SS sc = {"kim",77,88,99,0,0,'F'}; //struct Score 타입을  SS 타입으로 변경

<2. (board)구조체 선언 후, 메인 실행문에서  typedef를 이용하여 사용자가 정의한 이름으로 구조체 타입명을 변경.>

 - typedef struct Board SB; //하지만, 메인 코드에서 이렇게 다 작성하게 되면 오히려 줄만 늘어나고 의미가 없다.

//(member) 구조체 타입 이름 없이, 변수 (mb) 선언까지 한 번에 할 수도 있다.

 - 단, 이경우 변수 초기화를 배열로 할 수 없고, 일일히 값을 넣어줘야한다.

 

--예문 코드 보기--

더보기
#include <stdio.h>
#include <time.h>

#pragma pack(1) //padding byte remove
typedef struct Score{
	char *pt_name;
	int kor;
	int eng;
	int math;
	int total;
	double avg;
	char grade;
}SS;//새로운 타입으로 정의 : struct Score >> SS
struct{
	int num;
	char *id;
	char *pw;
	char *name;
	char *tel;
}mb;//변수 선언 : struct (이름 없음) 타입의 변수 "mb" 
struct Board{
	int num;
	char *title;
	char *content;
	char *writer;
	char *wdate;
};
char* local_time();

int main(int argc, char **argv)
{
	printf("structure score...\n");
	
	printf("--- score ---\n");
	SS sc = {"kim",77,88,99,0,0,'F'};
	sc.total = sc.kor + sc.eng + sc.math;
	sc.avg = sc.total/3;
	if(sc.avg>=90){
		sc.grade = 'A';
	}else if(sc.avg>=80){
		sc.grade = 'B';
	}else if(sc.avg>=70){
		sc.grade = 'C';
	}else if(sc.avg>=60){
		sc.grade = 'D';
	}else{
		sc.grade = 'F';
	}
	
	printf("name: %s\n",sc.pt_name);
	printf("kor: %d, eng: %d, math: %d\n",sc.kor, sc.eng, sc.math);
	printf("total: %d, avg: %.2lf, grade: %c\n",sc.total, sc.avg, sc.grade);
	
	printf("--- member ---\n");
	//mb = {1,"admin","hi123456","kim","010-111"}; 
	//배열로 값을 초기할 수 없고, 하드 코딩으로 하나씩 넣어야한다.
	mb.num =1;
	mb.id="admin";
	mb.pw="hi123456";
	mb.name="kim";
	mb.tel="010-111";
	printf("num:%d, id:%s, pw:%s, name:%s, tel:%s\n",
					mb.num,mb.id,mb.pw,mb.name,mb.tel);
	
	printf("--- board ---\n");
	//타입 변환과 변수 선언을 모두 메인 함수에서.
	typedef struct Board SB;
	SB bd = {1,"title1","content1","lee",local_time()};
	printf("num:%d, title:%s, content:%s, writer:%s, wdate:%s\n",
					bd.num, bd.title, bd.content, bd.writer, bd.wdate);

	
	return 0;
}

char* local_time(){
	
	struct tm *pt_time; //시스템에 내장된 구조체 사용
	time_t time_now;
	time(&time_now);
	printf("time_now:%ld\n",time_now);
	
	pt_time = localtime(&time_now);
	printf("time:%s\n",asctime(pt_time));//long타입의 시간을 문자열로 변환
	
	char *wdate = asctime(pt_time);
	printf("wdate:%s\n",wdate);
	
	return wdate;
}

 

 


#struct_inner - 3. 구조체를 구조체의 원소로 사용 

//struct inner : 다른 구조체를 구조체의 원소로 초기화
 - typedef struct student{ ~ Contact ctt; Score sc; }Student; //구조체를 원소로 하는 구조체 선언

 - st.ctt = ctt; //student st 구조체의 원소 Contact ctt에 ctt의 값을 할당.
 - printf("tel: %s\n",st.ctt.tel); //구조체 안의 구조체 값 출력.

 

--예문 코드 보기--

더보기
#include <stdio.h>

typedef struct contact{
	char *tel, *email, *addr; //동일 타입 변수 동시 선언
}Contact;

typedef struct score{
	int kor, eng, math, total;
	double avg;
	char grade;
}Score;//타입을 새롭게 정의

//struct inner : 다른 구조체를 구조체의 원소로 초기화
typedef struct student{
	char *pt_name;
	Contact ctt;
	Score sc;
}Student;

int main(int argc, char **argv)
{
	printf("struct inner ...\n");
	
	printf("--- contact ---\n");
	Contact ctt;
	ctt.tel = "010";
	ctt.email = "aaa@aaa.com";
	ctt.addr = "seoul";
	printf("ctt.tel: %s, ctt.email: %s, ctt.addr: %s \n",ctt.tel,ctt.email,ctt.addr);
	
	
	printf("--- score ---\n");
	Score sc = {77,88,99,0,0,'F'};
	sc.total = sc.kor + sc.eng + sc.math;
	sc.avg = sc.total/3;
	if(sc.avg>=90){
		sc.grade = 'A';
	}else if(sc.avg>=80){
		sc.grade = 'B';
	}else if(sc.avg>=70){
		sc.grade = 'C';
	}else if(sc.avg>=60){
		sc.grade = 'D';
	}else{
		sc.grade = 'F';
	}
	
	printf("kor: %d, eng: %d, math: %d\n",sc.kor, sc.eng, sc.math);
	printf("total: %d, avg: %.2lf, grade: %c\n",sc.total, sc.avg, sc.grade);
	
	
	printf("--- student ---\n");
	Student st;
	st.pt_name = "kim";
	st.ctt = ctt;//student st 구조체의 원소 Contact ctt에 ctt의 값을 할당.
	st.sc = sc;
	
	printf("name: %s\n",st.pt_name);
	printf("tel: %s\n",st.ctt.tel);
	printf("email: %s\n",st.ctt.email);
	printf("addr: %s\n",st.ctt.addr);
	printf("kor: %d, eng: %d, math: %d\n",st.sc.kor, st.sc.eng, st.sc.math);
	printf("total: %d, avg: %.2lf, grade: %c\n",st.sc.total, st.sc.avg, st.sc.grade);
	
	return 0;
}

 

 

#struct_array - 4.구조체 배열 다루기 


//구조체 배열도정수 배열 생성과 동일한 형태로 생성한다.
- Student sts[2] ={st, st2}; // (정수 배열 생성) int sus[2] = {su1,su2}; 

//특정 인덱스[i]가 가지는 원소(구조체 sc)의 안에 있는 값을 꺼낸다.
 - printf("total: %d, avg: %.2lf, grade: %c\n",sts[i].sc.total, sts[i].sc.avg, sts[i].sc.grade);

 

--예문 코드 보기--

더보기
#include <stdio.h>

typedef struct contact{
	char *tel, *email, *addr; //동일 타입 변수 동시 선언
}Contact;

typedef struct score{
	int kor, eng, math, total;
	double avg;
	char grade;
}Score;//타입을 새롭게 정의

typedef struct student{
	char *pt_name;
	Contact ctt;
	Score sc;
}Student;

int main(int argc, char **argv)
{
	printf("struct inner ...\n");
	
	//이렇게 배열 생성 하던 것처럼 구조체 배열도 생성한다.
	//int su1 = 10;
	//int su2 = 20;
	//int sus[2] = {su1,su2};
	
	printf("==== contact[] ====\n");
	Contact ctt;
	ctt.tel = "010";
	ctt.email = "aaa@aaa.com";
	ctt.addr = "seoul";
	
	Contact ctt2;
	ctt2.tel = "011";
	ctt2.email = "bbb@bbb.com";
	ctt2.addr = "pusan";

	Contact ctts[2] = {ctt,ctt2};
	for(int i=0;i<2;i++){
		printf("%s ",ctts[i].tel);
		printf("%s ",ctts[i].email);
		printf("%s \n",ctts[i].addr);
	}
	
	
	printf("==== score[] ====\n");
	Score sc = {77,88,99,0,0,'F'};
	Score sc2 = {55,66,77,0,0,'F'};
	Score scs[2] = {sc,sc2};
	for(int i=0;i<2;i++){
			scs[i].total = scs[i].kor + scs[i].eng + scs[i].math;
			scs[i].avg = scs[i].total/3;
			if(scs[i].avg>=90){
				scs[i].grade = 'A';
			}else if(scs[i].avg>=80){
				scs[i].grade = 'B';
			}else if(scs[i].avg>=70){
				scs[i].grade = 'C';
			}else if(scs[i].avg>=60){
				scs[i].grade = 'D';
			}else{
				scs[i].grade = 'F';
			}
		printf("kor: %d, eng: %d, math: %d\n",scs[i].kor, scs[i].eng, scs[i].math);
		printf("total: %d, avg: %.2lf, grade: %c\n",scs[i].total, scs[i].avg, scs[i].grade);
	}	


	printf("==== student[] ====\n");
	Student st;
	st.pt_name = "kim";
	st.ctt = ctt;
	st.sc = sc;
	Student st2 = {"lee",ctt2,sc2};
	Student sts[2] ={st, st2};
	for(int i=0;i<2;i++){
		printf("---student %d---\n",i+1);
		printf("name: %s, tel: %s, mail: %s, addr: %s\n",
			sts[i].pt_name,sts[i].ctt.tel,sts[i].ctt.email,sts[i].ctt.addr);
		printf("kor: %d, eng: %d, math: %d\n",sts[i].sc.kor, sts[i].sc.eng, sts[i].sc.math);
		
			sts[i].sc.total = sts[i].sc.kor + sts[i].sc.eng + sts[i].sc.math;
			sts[i].sc.avg = sts[i].sc.total/3;
			if(sts[i].sc.avg>=90){
				sts[i].sc.grade = 'A';
			}else if(sts[i].sc.avg>=80){
				sts[i].sc.grade = 'B';
			}else if(sts[i].sc.avg>=70){
				sts[i].sc.grade = 'C';
			}else if(sts[i].sc.avg>=60){
				sts[i].sc.grade = 'D';
			}else{
				sts[i].sc.grade = 'F';
			}
		
		//특정 인덱스[i]가 가지는 원소(구조체 sc)의 안에 있는 값을 꺼낸다.
		printf("total: %d, avg: %.2lf, grade: %c\n",sts[i].sc.total, sts[i].sc.avg, sts[i].sc.grade);
	}


	
	return 0;
}