가변 배열 (2)

Yama·2023년 12월 19일
0

어소트락 수업

목록 보기
17/55

가변 배열 (1)은 int형을 대입하는 가변 배열(동적 배열)을 만들고 있었다.

참고 : 기능을 구현할떄 접근 방법

  • 어떻게 프로그래밍을 짤것인지 큰 맥락을 나열해놓고 코드를 짠다.
    • 프로그래머들은 코드 한 줄 치는데 몇 시간이 걸린다.(고민 시간)
    • 내가 할려는 기능을 생각하는 시간이 더 중요하다.

가변 배열 메모리 확장 함수

  • 공간 확장할떄 확장한 공간을 원래 공간과 이어붙이지 못하기 때문에 다른 큰 공간에 값을 옮겨야 한다.
  • 재할당 과정을 순차적으로 해야하는일?

메모리 공간 재할당(확장 함수) 구현하기

DArr.cpp

void Realloc(DArr* _pArr)
{
	_pArr->MaxCount *= 2;
	int* pNew = (int*)malloc(_pArr->MaxCount * sizeof(int));

	for (int i = 0; i < _pArr->CurCount; ++i)
	{
		pNew[i] = _pArr->pData[i];
	}

	free(_pArr->pData); 

	_pArr->pData = pNew;
}
  1. 더 큰 메모리 공간을 할당 받는다.
    • 지역 변수(pNew)를 사용한 이유는 pNew의에다가 기존의 값을 저장해서 Realloc함수에서만 사용되는 지역 스택에 저장할려고 사용했다.
	int* pNew = (int*)malloc(_pArr->MaxCount * 2 * sizeof(int));
  1. 기존에 가지고 있던 데이터를 새로운 곳으로 옮겨둔다.
    • 총 4번 반복해서 pNew에 기존에 있던 값을 옮기면 for문이 끝난다.
	for (int i = 0; i < _pArr->CurCount; ++i)
	{
		pNew[i] = _pArr->pData[i];
	}
  1. 기존 메모리 할당받은 공간을 해제시킨다.
    • 안할시 메모리 누수(leak)가 발생한다.
	free(_pArr->pData); 
  1. 새로운 공간을, 데이터를 저장하는 곳으로 갱신한다.
    • 기존 공간은 이미 해제되있고, 새로 할당받은 pNew의 자리를 갱신해준다.
	_pArr->pData = pNew;
  1. 최대 데이터 저장 개수를 2배로 늘린다.
	_pArr->MaxCount *= 2;
  1. 최대 데이터 미리 2배 시키고 시작하는법.(5.1)
    • 1번 코드를 수정하면 된다.
	_pArr->MaxCount *= 2;
	int* pNew = (int*)malloc(_pArr->MaxCount * sizeof(int));

동적 배열에서 인덱스 값(정보)를 가져오는법.

main.cpp

#include <iostream>

#include "DArr.h"
int main()
{
	DArr arr1 = {};


	InitDArr(&arr1);
	PushData(&arr1, 10);
	PushData(&arr1, 20);
	PushData(&arr1, 30);
	PushData(&arr1, 40);
    
	PushData(&arr1, 50);

	int data = 0;
	for (int i = 0; i < arr1.CurCount; ++i) // 1
	{
		data = GetData(&arr1, i);
	}
    
	data = GetData(&arr1, 5); // 2

	return 0;
}

DArr.cpp

#include "DArr.h"
#include <iostream>
#include <assert.h>

void InitDArr(DArr* _pArr)
{
	_pArr->CurCount = 0;
	_pArr->MaxCount = 4;
	_pArr->pData = (int*)malloc(sizeof(int) * _pArr->MaxCount);
}

void Realloc(DArr* _pArr)
{
	_pArr->MaxCount *= 2;
	int* pNew = (int*)malloc(_pArr->MaxCount * sizeof(int));

	for (int i = 0; i < _pArr->CurCount; ++i)
	{
		pNew[i] = _pArr->pData[i];
	}
	free(_pArr->pData);
	_pArr->pData = pNew;
}

void PushData(DArr* _pArr, int _Data)
{
	if (_pArr->MaxCount <= _pArr->CurCount)
	{
		Realloc(_pArr);
	}

	_pArr->pData[_pArr->CurCount++] = _Data;
}

int GetData(DArr* _pArr, int _Idx)
{
	if (_pArr->CurCount <= _Idx) // 3(1)
	{
		assert(nullptr); 
	}
	
	// assert(!(_pArr->CurCount <= _Idx)); // 3(2)

	return _pArr->pData[_Idx];
}

DArr.h

struct DArr
{
	
	int* pData;		
	int  MaxCount;	
	int  CurCount;
}

void InitDArr(DArr* _pArr);
void PushData(DArr* _pArr, int _Data);
int GetData(DArr* _pArr, int _Idx);
  • assert 함수 때문에 동적 배열에 입력된 데이터 숫자를 초과하는 인덱스에 접근하려는 경우 어서트가 참이되서 경고를 한다.

    • // 1이 for문이 돌면서 4번째인덱스(5번쨰칸)까지 돌면서 값을 10,20,30,40,50을 받아온다.
    • // 2은 5번쨰(6번째칸)에 있는걸 가져오라고 한다.(이상한값이 들어있을것)
    • // 3(1) 동적 배열의 공간의 값들만 가져오고 싶으면 assert 함수를 걸어서 assert가 참이되는 순간 코드를 멈추고 경고를 띄운다.
    • // 3(2)는 // 3(1)의 간략화 시킨것이다.
  • assert정리 : (https://blockdmask.tistory.com/286)

    	// 4 
    	// c++ 수업을 할떄 만들것,
    	// 동적 배열, 연결형 리스트, 이진 탐색 트리
    	// 만들고 상속 -> 다형성 -> 추상화 -> windowsapi(소규모 게임 엔진) -> 엔진을 활용해서 게임을 만들어서 발표.(2월초 발표)

헤더 모음

#include <vector> // 가변 배열(동적 배열)
#include <list> // 연결형 리스트
#include <map> // 이진 탐색 트리
using namespace std;
  • 자료구조는 클래스 이름(언어마다 클래스 이름이 다르다)을 외우는게 아니라 그 원리를 이해해야 하고 어떤 상황에 자료구조를 쓸지 알아야 한다.

재할당 함수를 메인에서 못쓰게하는법.

  • 내가 만든 재할당 함수는 헤더파일에 정의 되어 있어서 헤더 파일을 참고하면 막 쓸수 있다.
  • 근데 이 재할당 함수를 DArr.cpp에서만 내부적으로 돌아가게 하고싶으면
    • 헤더파일에 선언문 지우고
    • DArr.cpp에서 재할당함수를 pushData함수보다 위에 두면 된다.
      • 내부적으로 돌아가도 PushData함수가 재할당 함수를 사용하는데 컴파일러는 위에서 아래로 컴파일을 하니까.

강의 코드

main.cpp

#include <iostream>

#include "DArr.h"

int main()
{
	int iArr[100] = {};

	DArr arr1 = {};
	DArr arr2 = {};
	DArr arr3 = {};
	DArr arr4 = {};

	InitDArr(&arr1);
	PushData(&arr1, 10);
	PushData(&arr1, 20);
	PushData(&arr1, 30);
	PushData(&arr1, 40);
	PushData(&arr1, 50);

	int data = 0;
	for (int i = 0; i < arr1.CurCount; ++i)
	{
		data = GetData(&arr1, i);
	}

	// data = GetData(&arr1, 5);

	return 0;
}

DArr.h

#pragma once

struct DArr
{
	int* pData;		
	int  MaxCount;	
	int  CurCount;
};

void InitDArr(DArr* _pArr);

void PushData(DArr* _pArr, int _Data);

int GetData(DArr* _pArr, int _Idx);

DArr.cpp

#include "DArr.h"
#include <iostream>
#include <assert.h>

void InitDArr(DArr* _pArr)
{
	_pArr->CurCount = 0;
	_pArr->MaxCount = 4;
	_pArr->pData = (int*)malloc(sizeof(int) * _pArr->MaxCount);
}

void Realloc(DArr* _pArr)
{
	_pArr->MaxCount *= 2;
	int* pNew = (int*)malloc(_pArr->MaxCount * sizeof(int));

	for (int i = 0; i < _pArr->CurCount; ++i)
	{
		pNew[i] = _pArr->pData[i];
	}

	free(_pArr->pData);

	_pArr->pData = pNew;
}

void PushData(DArr* _pArr, int _Data)
{
	if (_pArr->MaxCount <= _pArr->CurCount)
	{
		Realloc(_pArr);
	}

	_pArr->pData[_pArr->CurCount++] = _Data;
}

int GetData(DArr* _pArr, int _Idx)
{
	assert(!(_pArr->CurCount <= _Idx));

	return _pArr->pData[_Idx];
}

1차 23.12.19
2차 23.12.20
3차 23.12.21
4차 23.12.22
5차 23.12.25
6차 24.01.01

0개의 댓글