범용성있는 소스코드에 대한 이해

honeyricecake·2022년 1월 28일
0

자료구조

목록 보기
9/36

배열리스트에 저장할 자료형을 구조체 포인터로 두고 잘 짠 소스코드는 범용성있게 사용할 수 있음을 이해해보자.

Point.h
#ifndef POINT_H
#define POINT_H

typedef struct _point
{
int xpos;
int ypos;
} Point; //구조체에 x좌표, y좌표, struct로 타입 디피니션

// Point 변수의 xpos, ypos 값 설정
void SetPointPos(Point * ppos, int xpos, int ypos); //SetPointPos함수를 보자, 구조체의 포인터를 받고, 즉, 메모리의 주소를 받고 xpos, ypos을 받아 그 메모리 주소에 입력하는 함수

// Point 변수의 xpos, ypos 정보 출력
void ShowPointPos(Point * ppos);//Point의 주소만 받으면 그 Point의 x좌표,y좌표 출력

// 두 Point 변수의 비교
int PointComp(Point pos1, Point pos2); //두 포인터 주소 받아서 두 Point변수 비교

#endif//위의 함수들이 어떤 코드일지는 예상이 간다.

ArrayList.h

#ifndef ARRAY_LIST_H
#define ARRAY_LIST_H

#include "Point.h" // 첫 번째 변경

#define TRUE 1
#define FALSE 0

#define LIST_LEN 100

// typedef int LData;
typedef Point LData; // 두 번째 변경, 헤더 파일에서 Point을 LData로 typedef해줌으로서 LData로 정의한 소스 파일을 사용 가능

typedef struct __ArrayList
{
LData arr[LIST_LEN]; //Ldata 즉, Pont*로 된 배열이 여러개
int numOfData; //numOfData, 자료의 개수가 ArrayList에 기록
int curPosition; //여기까지 봤으면 ArrayList.c가 어떻게 돼있었는지 확인하러가보자
} ArrayList;

typedef ArrayList List;

void ListInit(List plist);
void LInsert(List
plist, LData data);

int LFirst(List plist, LData pdata);
int LNext(List plist, LData pdata);

LData LRemove(List plist);
int LCount(List
plist);

#endif

ArrayList.c

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

void ListInit(List * plist)
{
(plist->numOfData) = 0;
(plist->curPosition) = -1; //자료는 안 건드리고 numofData와 curPosition만 초기화
}

void LInsert(List * plist, LData data)
{
if(plist->numOfData >= LIST_LEN) //자료개수가 LIST_LEN 이상이면 더 넣을 공간이 없으므로 저장 종료
{
puts("저장이 불가능합니다.");
return;
}

plist->arr[plist->numOfData] = data;//배열의 마지막 칸에 자료 저장, 다시 한번 상기시키자면 여기는 좌표 구조체의 메모리 주소
(plist->numOfData)++;

}

int LFirst(List plist, LData pdata)
{
if(plist->numOfData == 0)
return FALSE;//가리킬 자료 X

(plist->curPosition) = 0//0번째 배열을 가리킨다.
*pdata = plist->arr[0];//이 때 pdata는 좌표 구조체의 포인터
return TRUE;

}

int LNext(List plist, LData pdata)
{
if(plist->curPosition >= (plist->numOfData)-1)//curPosition이 numOfData - 1 이상이면 가지 못한다 numofData - 1이면 리스트의 마지막을 가리키고 있다는거고 그러면 LNext가 없기 떄문이다.
return FALSE;

(plist->curPosition)++;//curPosition 1칸 더
*pdata = plist->arr[plist->curPosition];//pdata를 참조하여 거기에 배열의 curPosition의 값 입력, 이는 비교에 사용, 주소가 데이터이면 그 주소를 찹조하여 저장
return TRUE;

}

LData LRemove(List * plist)
{
int rpos = plist->curPosition;//remove position의 약자 rpos
int num = plist->numOfData;
int i;
LData rdata = plist->arr[rpos];//rdata에 삭제할 데이터 저장

for(i=rpos; i<num-1; i++)
	plist->arr[i] = plist->arr[i+1];//i+1번째 칸에 있는 것을 i번째로

(plist->numOfData)--;//numOfData 하나 줄이는 것은 당연
(plist->curPosition)--;//curPosition은 무조건 -1해야한다. 그래야 한칸 앞으로 들어온 검사 안한 데이터를 확인한다.
return rdata;

}

int LCount(List * plist)
{
return plist->numOfData;
}

Point.c

#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] \n", ppos->xpos, ppos->ypos);
}

int PointComp(Point pos1, Point pos2)
{
if(pos1->xpos == pos2->xpos && pos1->ypos == pos2->ypos)
return 0;
else if(pos1->xpos == pos2->xpos)
return 1;
else if(pos1->ypos == pos2->ypos)
return 2;
else
return -1;
}

Main함수

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

int main(void)
{
List list;
Point compPos;//포인터 구조체 comPos
Point * ppos;//포인트형(?)포인터 ppos, 데이터가 point형 포인터이므로 이를 임시저장할 용도이다.

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))//ppos이 메모리 주소지만 메모리 주소 역시 저장된 곳이 있으므로 그 주소를 가져오기 가능, LFirst함수는 ppos의 주소를 받아서 ppos에 데이터를 써준다.
{
	ShowPointPos(ppos);//ppos 출력, 주소에 있는 걸 참조해서 출력한다.
	
	while(LNext(&list, &ppos))//데이터가 저장돼있으면 그러니까 LNext가 더이상 없을 때까지 LNext는 진행된다.
		ShowPointPos(ppos);
}
printf("\n");//모든 데이터를 출력한다.

/*** xpos가 2인 모든 데이터 삭제 ***/
compPos.xpos=2;
compPos.ypos=0;//포인터 구조체를 정의해놓은 이유가 있었다.

if(LFirst(&list, &ppos))
{
	if(PointComp(ppos, &compPos)==1)//주소 두개를 받아서 비교, 1이면 x가 같을 때
	{
		ppos=LRemove(&list);//list의 주소를 받아서 curPosition을 삭제하고 ppos로 리턴
		free(ppos);//여기서 ppos을 free하는데 데이터가 주소가 아닐 수도 있으니까 자료구조안에서 이를 free할 수는 없다. 즉, free는 메인함수를 짜는 프로그래머의 몫.
	}
	
	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;

}

0개의 댓글