728x90
링크드 리스트는 구조체나 배열처럼 C++에서 제공하는 기능이아니다.

 

그렇기 때문에 직접 만들어서 사용해야 하는데,반적으로 조체와 포인터를 사용해서 만들 수 있다.

 

예를들어 우리가 1,2,3,4라는 4개의 데이터를 보관해야 한다고 생각했을때

 
이 4개의 데이터가 배열에 보관된 모습과 링크드 리스트에 보관된 모습을 비교해보자.

 

// 배열
arr : | a | b | c | d |
사용자는 배열의 시작주소(arr = &arr[0])만 보관하고 있으면 된다.

// 링크드 리스트
a -> b -> c -> d
사용자는 첫번째 노드(a)의 위치만 보관하고 있으면 된다. 

 

배열은 차례대로 위치한 공간에 a ,b, c, d를 포함하고 있다.

 

링크드 리스트는 a, b, c, d를 담은 공간이 차례대로 위치하지는 않는다.
대신에 a는 b와 연결되고, b는 c와 연결되고, c는 d와 연결되는 방식으로 전체 아이템들을 보관한다.
이름처럼 연결된 리스트이다.

위의 배열 링크드 리스트를 보면

 

배열의 경우 3에 접근을 하기 위해서는 *(arr+2), arr[2] 등과 같이 한번에 접근이 가능
하다.

 

하지만 링크드 리스트는 c가 있는 곳까지 가려면 a,b를 거쳐야 한다.

이렇게 구성된 상태에서 사용자가 배열과 링크드리스트를 사용하는 시나리오를 생각해보자.

 

배열은 각 원소들이 차례대로 줄지어서 위치하기 때문에 이렇게 단순한 덧셈을 통해 원소에 접근이 가능하다.

 

하지만 링크드리스트배열처럼 차례대로 위치한것이 아니기 때문에 첫번째 노드부터 하나씩
거쳐가면서 c을 보관한 곳을 찾아가야 한다. 

 

구체적으로 말하면 일단 첫번째노드(a)에 접근해서 두번째 노드(b)의 위치를 알아내고, 다시 두번째 노드(b)에 접근한뒤

다음엔 세번째 노드(c)의 위치를 알아낼 수 있다. 결국 c를 보관한 노드에 접근할수 있게되는 식이다.

 

여기까지만 보았을때는 배열이 훨신 좋다.

 

어떤 원소에 접근하려고 할때 배열은 덧셈 한번만 하면 끝나지만, 링크드리스트는 첫번째 노드부터 원하는 노드에 이르기까지

모든 노드를 한번씩 거쳐야 하기 때문이다.

하지만 링크드리스트의 진정한 강점은 노드의 삽입과 삭제가 훨씬 간단하다는 점이다.

 

우선 배열과 링크드리스트에 e라는 데이터를 보관할 새로운 공간을 추가하는 시나리오를 생각해보자
이는 두가지로 나누어 볼수 있는데 배열이나 링크드 리스트의 중간에 삽입하는 경우와 끝에 삽입하는 경우가 있다.

 

※원소와 노드

- 배열에서 a,b,c,d를 보관하는 공간을 원소(Elements)라고 부른다.
비슷하게 링크드 리스트에서 a,b,c,d를 보관하는 공간을 노드(Nodes)라고 부른다.

 


// 배열
arr : | a | b | c | d | e

 

배열이 원소 5개를 보관할 수 있을만큼 크게 정의됐다는 가정하에서 끝에 e를 추가할수있다.


 

// 링크드 리스트
a -- b -- c -- d
e를 보관할 노드를 만들어서 d의 노드와 연결시키면 된다.

 

배열의 끝에 e를 포함하는 원소를 추가하려면 처음 배열을 만들 때부터 충분한 크기의 공간을 만들어야 한다.
만약 원소 4개짜리 배열이었다면 실행중에 새로운 원소를 추가하는 것은 불가능하다.

하지만 링크드리스트 경우에는 e를 포함하는 새로운 노드를 만들고, 마지막 노드와 새로운 노드를 연결시켜주면 끝난다.

 

 

이번에는 배열이나 링크드 리스트 중간에 새로운 정보를 삽입하는 시나리오를 보자.

 

우선 배열의 경우 e라는 값을 a와 b사이에 삽입하려면 b~d까지의 원소를 뒤로 한칸씩 밀어내야 한다.

그다음에 기존에 b가 있던 위치를 e에 넣으면 된다. 만약 10000개쯤있는 배열이라면 9999개의 원소를 밀어내야한다.

 

반면 링크드리스트 a와 b의 연결을 끊은 후에 a와 e, e와 b를 연결시키면 간단하게 끝난다. 

그 뒤에 9999개의 노드가 있더라도 똑같다.

이런식으로 비교를 해봤을때 삽입삭제 면에서는 링크드리스트가 훨씬 압승이라는 점을 느꼈을 것이다.

 

 

728x90
Posted by 정망스
,
728x90

요즘은 학원을 다니며 c++을 본격적으로 배우고있다.

자바나, 다른 웹언어를 더 많이 공부한 나로썬 종종 잘이해가 안가거나(본래 이해력이 많이 부족...)

멈칫 멈칫 거릴때가 너무 많다; 서론은 여기까지고..


특히 요새 애먹고 있는부분이 이 포인터 부분이다.


아직까지도 완벽히 다 이해한건 아니지만 요즘들어 배열과, 포인터를 많이 쓰던도중 


이번 글의 제목과 같이 "포인터배열", "배열포인터" 앞뒤 순서가 바뀐 이 둘의 차이가 궁금해졌고..

나 자신에게 이런거같다라고 정의를 하고 글에 끄적끄적 적어본다... (뭐 틀릴수도 있음... 양해바람)


(포인터)(배열) = 포인터배열포인터로 이루어진 배열이라는 뜻

(배열)(포인터) = 배열포인터는 배열을 가리키는 포인터라는 뜻으로 보면 될듯하다.


그렇다면 이제 간단한 코드로 한번 보자.


ex)포인터배열


char a[10] -> char형 변수 word[0],word[1].... word[9] 총 10개의 변수를 선언한것이다.


char* str[10] -> char형 포인터 변수 *str[0], *str[1]..... *str[9] 총 10개의 포인터 변수를 선언한것이다.

여기서 *str[10]을 포인터배열이라고 한다.



ex)배열포인터


char a; -> a는 char형 변수

char a[10]; -> a[10]은 char형 배열


char a[10];

char *str = a; -> a[10]은 char형 배열이고, *str은 a라는 배열을 가리키는 포인터이다.

여기서 *str을 배열포인터라고 한다.


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

2차원 배열을 배열포인터로 가리킬때는 선언방식이 조금 다르다고 한다.


char a[5][10];

char (*str)[10];

str = a;


2차원 배열을 가리키는 배열포인터는 반드시 배열의 크기를 맞춰줘야 한다고 한다.

이유는 포인터가 가리키는 현재 칸에서 다음칸으로 이동하는데 있어서 실제 배열을 이동하는것과 동일하게 이동

해야 하기 때문이라 한다.


ex) str = a[0], str+1 = a[1], ....... str+4 = a[4]




728x90
Posted by 정망스
,
728x90

교수님 추천: 지오지브라(수학 계산 프로그램)

 

게임에는, 심리스방식, 존방식

심리스방식: 맵이 계속해서 이어지는것 방대한 맵 wow 같은거

존방식: 각 지역을 딱딱 단위별로 잘라낸거

 

%: 나머지

/: 몫

 

#include 로 헤더파일을 추가할때

< > <--- 비주얼에서 지정하고있는 라이브러리 경로에있는 헤더파일을 참조할때 쓴다.

" " <---같은 경우는 우리가 프로젝트를 할때 임의로 만든 즉 사용자 지정 헤더를 참조할때 쓴다.현재 코드가 있는 위치를 기준으로 헤더파일을 찾는다.

 

 

-디버깅-

f9 -> 브레이크포인트

f5 -> 브레이크포인트 지점에 화살표모양

f10 -> 한단계씩 진행

f11 -> 함수만나면 이제 함수안으로 들어가서 진행하게끔

ctr+f10 -> 커서있는쪽으로 바로이동

조사식:

ex) 이름에 배열이름 "a"를치면 현재 a가 크기가 10인 배열이라하면 0~9까지의 값이 나온다

또, a하고 , 콤마를 찍고 10,뭐 100 치면 10개 , 100개의 배열과함께 안의 값이 나온다.

 

-주석-

범위선택하고 ctr+k, ctr+c 하면 선택 범위 주석

범위선택하고 ctr+k, ctr+u 하면 선택 범위 주석 해제

 

구조체는 메인함수 밖에서 선언해라, 구조체 객체만들때 한글로해도 된다.

여러가지 정보를 한군데에 묶어서 뭐 배열에 넣고 이렇게 쓰기위해서 구조체 쓴다.

 

-포인터-

앞에 보통 p로 시작해서 붙임.. 곡 규칙은 아님.

(*a).age 같은 경우에는 "."이 "*"보다 우선순위가 더 높아서 괄호를 해줘야 포인터를 인식한다

그런데 이렇게 치면 좀 복잡하니까

a->age로 입력할수도 있다. 표현은 똑같다.

 

*p = *d : 둘다 포인터이고, 둘다 같은 주소를 가르킨다는 뜻이다. 즉 p와 d가 가르키는곳이 같고, p나 d나 둘중 하나가 값이 수정되면

둘다 값이 바뀐다.

 

p = *d : p가 클래스라고 치고, d도 클래스인데 포인터형이라 하면, p를 생성함과동시에 d에 있는 값들을 참고로 해서 생성한다는뜻이다. p(*d)와 같다, 즉 생성자가 클래스이름이 test라 하면 test::test(test& a)를 호출하는것과 같다. a라는 매개변수에서 보이듯이 test형의 포인터를 참고로해서 새로운 p를 생성하게된다.

 

상속관계에 있어서도 평소 자바같으면 부모클래스 a = new 자식클래스는 원래 성립이 되지않는다. 자식클래스가 한마디로 메모리가 더 크기 떄문이다라고 생각한다. 하지만 c++에서는 포인터를 사용하여 부모클래스 *a = new 자식클래스 를하게되면 부모클래스의 포인터가 자식클래스를 가르키게되고 자식클래스의 메모리 크기만큼의 공간을 만들기떄문에 포인터로 하면 잘 생성된다.

 

연산자 오버로딩을 할시 포인터를 매개변수로 넘겨주는것과, 그냥 클래스를 넘겨주는것은 메모리 할당에 있어서 차이가 있다.

CTest& operater+(CTest& a) , CTest operater+(CTest a) 두개가 있다하고 return으로 *this를 한다고하자

왼쪽같은경우는 포인터를 받는 연산자 오버, 오른쪽같은경우는 그냥 클래스 객체를 받는 연산자 오버라 하면

왼쪽은 포인터를 매개로 넘겨주고 리턴시 포인터의 주소를 넘겨주게 된다.

즉 c = a + *b를 하게 되면   c메모리->포인터메모리->함수안에서 생성된메모리 이렇게 3개가 되어버린다.

c는 계속해서 처음에 넘겨줫던 포인터의 주소를 가지게 되어 포인터를 거쳐서 함수로 가게된다는 것이다. 매우 비효율적이고, 메모리또한 낭비다

 

하지만 그냥 c = a + b 처럼 클래스 객체를 그냥 매개로 넘겨주면 리턴시 클래스 객체를 그대로 받는것이기 때문에

c메모리 -> 함수안의 메모리 를 바로 가르키게된다, 불필요한 메모리가 생성되지 않는다.

 

그리고 함수안에서 생성된 new 나 이런 메모리들은 그 함수가 끝나면 프로그램이 다 끝난거니까 소멸자 호출과 함께 메모리는 제거 된다라고 일단 그렇게 생각한다 나는.

 

-클래스-

앞에보통 C로시작해서 붙임.. 꼭 규칙은 아님.

클래스 안에 public, protected등 접근 지정 안해주면 자동으로 변수들같은 정적인 데이터들은 private, 접근가능한 함수들 같은경우네는 public으로 자동 지정 된다.

 

멤버변수: m_

정수: n

 

두점 사이의 거리 = (x1,y1) , (x2,y2)

루트((x2-x1)제곱 + (y2-y1)제곱)

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

 

두점이 잇다하면 이동방향 계산 (x2,y2)는 이동할 좌표

(x2-x1, y2-y1)이 x1,y1에서 x2,y2까지 가는데의 이동방향 좌표가 된다.

 

구한후

(0,0)의 좌표를 기준으로 (x2-x1, y2-y1)과의 거리를 구한다.

즉 피타고라스 기준에서 c2=a2+b2 즉 c를 구하는것과 같다.

 

그 나온 c를 이제

x2-x1 / c 는 이동방향의 x좌표

y2-y1 / c 는 이동방향의 y좌표가 되는것이다!!

 

거리/방향 = 단위벡터

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

두개의 원이 있을 경우

각각 (x1,y1), (x2,y2) 좌표에 두개의 원이 있고 각각의 지름이 잇다고 하자.

그렇다면 이 두 원의 사이의 거리 즉 위의 좌표값이 원의 중심이 되는데 이 중심의거리

즉 두점 사이의 거리가 <= 두원의 지름의 합 이면 두개의 원은 충돌한것이고

그렇지 않으면 충돌하지 않은 것이다.

 

 

-파일입출력-

FILE* f = NULL;
 fopen_s(&f, "a.txt", "rt");    // 매개변수가 파일, 파일이름, 모드
 fwrite("Hello", 5, 1, f);       // 매개변수가 입력할 텍스트, 크기, 몇번반복, 파일
 fclose(f);                        // 파일을 오픈한 후에는 반드시닫아줘야한다.

rt = 텍스트를 읽는다.    rb = 바이너리를 읽는다.

wt = 텍스를 쓴다.        wb= 바이너리를 쓴다.

 

fopen_s(&f, "a.txt", "rt");
 char buffer[10] = { 0 };
 fread_s(buffer, 5, 1, 10, f); //매개변수가 읽어올내용 저장한위치, 저장한 위치의크기, 읽어올 요소 크기, 몇번반복, 파일이름 
 cout << buffer << endl;

 

fseek(p, 0, SEEK_SET) //파일에 포인터위치를 처음으로 초기화

 

728x90
Posted by 정망스
,
728x90

 

140113.txt

140114.txt

140115.txt

140116.txt

140117中.txt

140120.txt

 

 

728x90
Posted by 정망스
,
728x90

 * 제공된 사진은 다른 블로그에 있는 사진을 참고로 올립니다.

 

Visual Studio 2010을 쓰면서 Direct X SDK를 설치하려고 하던중 VC++ 디렉터리라는 곳에서 재대로 설정이 되어있는지 확인하는 절차를 하던중.. 아래 사진과 같이 뭐 더이상 이 기능이 사용되지 않는다는 당황스러운 글들이 보였습니다.;;

 

보아하니. 2010부터는 프로젝트별로 고유의 디렉터리 설정을 가질수 있게 변경되어서 그렇다고 합니다.

 

그렇기 때문에 프로젝트 마다 일일히 디렉터리를 설정하기도 하는데, 모든 프로젝트가 공통적으로 적용될 디렉터리인 경우는 일일히 설정할 필요가 없습니다.

 

 

전역적으로 디렉터리 설정을 적용하기 위해서는 일단 속성 관리자 창을 엽니다. 일반적인 Win32 프로젝트라면 밑의 화면처럼 Microsoft.Cpp.Win32.user 항목이 있습니다.
( 참고 : 속성관리자를 보시면 각 프로젝트, 각 구성마다 Microsoft.Cpp.Win32.user가 있는데 한 곳만 설정해주시면 됩니다. )


 

 

  이 항목에 마우스 오른쪽 버튼  -> 속성 메뉴를 선택하시면 프로젝트 속성 설정창이 뜹니다.

이곳에서 VC++ 디렉터리 항목을 선택합니다.

 

이곳에서 항목별로 추가할 디렉터리등을 설정해줍니다.

include는 포함 디렉터리에, lib는 라이브러리 디렉터리에 설정합니다.

 

 

 디렉터리 설정을 마치고, 이제 작업하는 프로젝트에 설정이 적용되었는지를 확인해봅니다.

 

위 그림을 보시면 상속된 값에 위쪽에서 적용한 디렉터리가 적용되어있는 것을 확인할 수가 있습니다.

 

전역설정이 아니더라도 win32 프로젝트를 만드셔서 프로젝트 항목에 오른쪽 -> 속성으로 들어가셔서 여태 설명드렸던 방법과 동일하게 추가해주시면 됩니다.

 

 

이번엔 프로젝트 속성 페이지에서 링커 -> 입력 란에 들어가서 추가 종속성 편집을 하여 아래의 5가지 항목을 추가해줍니다.

 

 

이제 마지막으로 아래의 일반 탭에서 문자 집합 설정을 멀티바이트 문자 집합 사용으로 바꾸어 줍니다.

 

여기까지 하면 3D 게임프로그래밍 기본설정이 완료되었다고 합니다.

저도 다른 분들의 정보를 참고하여 정리하여 올리는거기 때문에 차후에 문제되는 부분이 있으면 수정하겠습니다.

728x90
Posted by 정망스
,


맨 위로
홈으로 ▲위로 ▼아래로 ♥댓글쓰기 새로고침