본문 바로가기
코스웨어/16년 스마트컨트롤러

2016-09-02_조재찬_스터디일지_C언어-리스트에 구조체 변수 저장

by 알 수 없는 사용자 2016. 9. 2.
728x90
반응형
리스트에 구조체 변수 저장하기

#ifndef __POINT_H__
#define __POINT_H__

typedef struct _point
{
	int xpos;
	int ypos;
} Point;

// Point 변수의 xpos, ypos 값 저장
void SetPointPos(Point * ppos, int xpos, int ypos);

// Point 변수의 xpos, ypos 정보 출력 
void ShowPointPos(Point * ppos);

// 두 Point 변수의 비교
int PointComp(Point * pos1, Point * pos2); 

#endif


Point.c (PointComp 함수의 반환값은 임의로 지정)

#include <stdio.h>
#include "Point.h"

void SetPointPos(Point * ppos, int xpos, int ypos)	// 값 저장
{
	ppos->xpos = xpos;
	ppos->ypos = ypos;
}

void ShowPointPos(Point * ppos)
{
	printf("[%d %d]", ppos->xpos, ppos->ypos);
}

int PointComp(Point * pos1, Point * pos2)
{
	//	xpos가 서로 같으면 1, ypos가 서로 같으면 2, 모두 같으면 0, 모두 다르면 -1 반환
	if (pos1->xpos == pos2->xpos)
		return 1;
	else if (pos1->ypos == pos2->ypos)
		return 2;
	else if (pos1->xpos == pos2->xpos && pos1->ypos == pos2->ypos)
		return 0;
	else
		return -1;
}



- typedef 선언 변경
typedef int LData -> typedef Point * LData;

Point 구조체의 정의가 담긴 Point.h를 include
#include "Point.h"

#include <stdio.h> #include <stdlib.h> #include "ArrayList.h" #include "Point.h" int main(void) { List list; Point compPos; Point * ppos; ListInit(&list); /*** 4개의 데이터 저장 ***/ ppos = (Point*)malloc(sizeof(Point)); SetPointPos(ppos, 2, 1); LInsert(&list, ppos); ppos = (Point*)malloc(sizeof(Point)); SetPointPos(ppos, 2, 2); LInsert(&list, ppos); ppos = (Point*)malloc(sizeof(Point)); SetPointPos(ppos, 3, 1); LInsert(&list, ppos); ppos = (Point*)malloc(sizeof(Point)); SetPointPos(ppos, 3, 2); LInsert(&list, ppos); /*** 저장된 데이터의 출력 ***/ printf("현재 데이터의 수: %d \n", LCount(&list)); if(LFirst(&list, &ppos)) { ShowPointPos(ppos); while(LNext(&list, &ppos)) ShowPointPos(ppos); } printf("\n"); /*** xpos가 2인 모든 데이터 삭제 ***/ compPos.xpos=2; compPos.ypos=0; if(LFirst(&list, &ppos)) { if(PointComp(ppos, &compPos)==1) { ppos=LRemove(&list); free(ppos); } while(LNext(&list, &ppos)) { if(PointComp(ppos, &compPos)==1) { ppos=LRemove(&list); free(ppos); } } } /*** 삭제 후 남은 데이터 전체 출력 ***/ printf("현재 데이터의 수: %d \n", LCount(&list)); if(LFirst(&list, &ppos)) { ShowPointPos(ppos); while(LNext(&list, &ppos)) ShowPointPos(ppos); } printf("\n"); return 0; }


Output :
현재 데이터의 수: 4
[2 1][2 2][3 1][3 2]
현재 데이터의 수: 2
[3 1][3 2]


위의 소스 main함수에서 LRemove 함수가 삭제된 데이터를 return 하도록 한 이유를 알 수 있다.
실제 Point 구조체 변수의 값은 heap에 저장, 주소값만이 리스트에 저장된다.

이 주소값은 Point 구조체를 동적할당한 결과이다.
ppos = (Point*)malloc(sizeof(Point));

삭제한 값을 반환해줘야 free 함수를 통한 해당 메모리 공간을 해제 가능

일반적인 리스트가 메모리 해제까지 해주진 못하기 때문에
리스트에 저장된 값이 주소값이냐, 그 주소 값이 동적할당인 결과를 구분해 메모리 공간 해제를 하도록 구현하는 것은 무리다.

따라서 LRemove 함수처럼 데이터를 소멸시키는 함수는, 반드시 소멸된 데이터를 return 하도록 정의해야 한다.
그렇지 않으면 그 메모리 공간이 프로그램 실행내내 계속 상주하는 문제가 생길 것이기 때문이다.




리스트 활용 예제


ArrayList.h의 typedef 선언 변경


typedef int LData;

-> typedef NameCard * LData;



ArrayList.h에 NameCard.h 를 include


#include "NameCard.h"



NameCard.c

#include <stdio.h>
#include <stdlib.h>	// 문자열 변환, 의사 난수 생성, 동적 메모리 관리 등의 함수들을 포함
#include <string.h>
#include "NameCard.h"

// NameCard 구조체 변수의 동적 할당 및 초기화 후 주소 값 반환
NameCard * MakeNameCard(char * name, char * phone)
{
	NameCard * pNameCard = (NameCard *)malloc(sizeof(NameCard));
	strncpy(pNameCard->name, name, sizeof(pNameCard->name));
	strncpy(pNameCard->phone, phone, sizeof(pNameCard->phone));
	return pNameCard;
}

// NameCard 구조체 변수의 정보 출력
void ShowNameCardInfo(NameCard * pcard)
{
	printf("이름 : %s \n", pcard->name);
	printf("전화번호 : %s \n\n", pcard->phone);
}

// 이름이 같으면 0, 다르면 0이 아닌 값 반환
int NameCompare(NameCard * pcard, char * name)
{	
	return strcmp(pcard->name, name);
}

// 전화번호 정보를 변경
void ChangePhoneNum(NameCard * pcard, char * phone)
{
	strncpy(pcard->phone, phone, sizeof(pcard->phone));
}


NameCardListMain.c

#include <stdio.h> #include <stdlib.h> #include "ArrayList.h" #include "NameCard.h" /* 3명의 전화번호 정보 저장, 이름 탐색후 정보 출력, 이름 탐색후 전화번호 변경, 이름 탐색후 정보 삭제, 모든 사람 전화번호 정보 출력*/ int main() { List list; NameCard * pcard; ListInit(&list); // 리스트 초기화 pcard = MakeNameCard("재찬", "010 - 5000 - 6000"); LInsert(&list, pcard); pcard = MakeNameCard("영희", "010 - 8000 - 1000"); LInsert(&list, pcard); pcard = MakeNameCard("철수", "010 - 4000 - 6000"); LInsert(&list, pcard); // 리스트에서 이름 탐색 후 정보출력 if (LFirst(&list, &pcard)) { if (!NameCompare(pcard, "재찬")) //이름이 같으면 0, 다르면 0이 아닌 값 반환 { ShowNameCardInfo(pcard); } else { while (LNext(&list, &pcard)) { if (!NameCompare(pcard, "재찬")) { ShowNameCardInfo(pcard); break; } } } } // 리스트에서 이름 탐색후 전화 번호 변경 if (LFirst(&list, &pcard)) { if (!NameCompare(pcard, "영희")) { ChangePhoneNum(pcard, "010-9999-9999"); } else { while (LNext(&list, &pcard)) { if (!NameCompare(pcard, "영희")) { ChangePhoneNum(pcard, "010-9999-9999"); break; } } } } // 리스트에서 이름 조회후 삭제 if (LFirst(&list, &pcard)) { if (!NameCompare(pcard, "철수")) { pcard = LRemove(&list); free(pcard); } else { while (LNext(&list, &pcard)) { if (!NameCompare(pcard, "철수")) { pcard = LRemove(&list); free(pcard); break; } } } } // 남아있는 모든 사람 정보 출력 printf("데이터 수 : %d \n", LCount(&list)); if (LFirst(&list, &pcard)) { ShowNameCardInfo(pcard); while (LNext(&list, &pcard)) ShowNameCardInfo(pcard); } printf("\n"); return 0; }


Output :

이름 : 재찬

전화번호 : 010 - 5000 - 6000


데이터 수 : 2

이름 : 재찬

전화번호 : 010 - 5000 - 6000


이름 : 영희

전화번호 : 010-9999-9999

728x90