리스트에 구조체 변수 저장하기
| #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