2015.09.02 07:08


1. 함수의 원형

본격적으로 내용을 다루기에 앞서 함수 포인터의 원형과 포인터의 대상이 될 함수와의 원형은 같아야 한다.
이 점은 일반 서적에서 다루고 있는 내용이라 다 알 것이라고 생각되므로 함수의 원형에 대하여 간단하게
Q/A 식으로 짚고 넘어가겠다. 이해가 안되면 무조건 외우는 것도 한가지 방법이라고 생각됨.
마지막으로 함수 포인터는 함수가 아니라 원하는 함수의 주소를 담고 있는 변수이다. 근본적으로는 포인터
(변수 포인터)에 다른 변수의 주소를 넣는 것과 별로 다를 것이 없다. 다만 함수 포인터의 경우는 변수의
주소가 아닌 함수의 주소라는 점만 다를 뿐이다.

int a;
char c[5];
float* f;
"Hello, World"

Q) 위의 코드에서 a, c, f,
"Hello, World"의 원형은?
A)
int, char [], float *, const char *

만일 이 문제들을 못맞추었다면 다시 한번 책을 속독하기를 권함.

void foo();


const char* bar(int num);


class MyClass {
public:
   
void Func1(const string& txt);
   
static void Func2(const string& txt);
};

Q) foo, bar, MyClass::Func1, MyClass::Func2의 원형은?
A)
void (*)(), const char* (*)(int), void (MyClass::*)(const string&), void (*)(const string&)


2. 함수 포인터(전역 함수 포인터) / 멤버 함수 포인터

가. 어떻게 정의/선언하고 사용하는가?

    함수 포인터의 대상이 되는 함수의 원형을 적고 괄호안의 * 연산자의 뒤에 원하는 이름을 붙여서 사용.
    (괄호가 있는 이유는 없을 경우 함수의 리턴형이 * 연산자에 의해 원래 리턴형의 포인터로 처리되기
    때문에, 강력한 우선 순위를 가지는 괄호로 함수 포인터임을 명시.)

    예 1)

   
void foo();
   
void (*foo_ptr)();             // 로 정의/선언 후
    foo_ptr = &foo;                
// 로 함수의 주소를 대입 cf) void (*foo_ptr)() = &foo;
    (*foo_ptr)();                  
// 로 사용 cf) foo_ptr(); 도 가능

   
const char* bar(int num);
   
const char* (*bar_ptr)(int);   // 혹은 const char* (*bar_ptr)(int num);로 정의/선언
    bar_ptr = &bar;                
// 호출하려는 함수의 주소를 넣고
    (*bar_ptr)(5);                
// 로 사용 cf) bar_ptr(5); 도 가능

    예 2)

   
class MyClass {
   
public:
       
void Func1(const string& txt);
       
static void Func2(const string& txt);
    };

   
void (MyClass::*Func1Ptr)(const string&) = &MyClass::Func1;
   
void (*Func2Ptr)(const string&) = &MyClass::Func2;        

    MyClass mc;
    (mc->*Func1Ptr)(
"abc");
    (*Func2Ptr)(
"abc");            // 형태로 사용 cf) Func2Ptr("abc"); 도 가능

    예 3)

    만일 MyClass::Func1, MyClass::Func2에 대한 함수 포인터를 MyClass의 멤버 변수로 하려면

   
class MyClass {
   
public:
       
void Func1(const string& txt);
       
static void Func2(const string& txt);
       
void (MyClass::*Func1Ptr)(const string&); // 내부라도 MyClass 스코프임을 밝혀야 함.
       
void (*Func2Ptr)(const string&);
    };

    MyClass mc;
    mc.Func1Ptr = &MyClass::Func1;
// 클래스내에서 setter를 사용하면 그냥 &Func1
    mc.Func2Ptr = &MyClass::Func2;
// 편의상 public으로 지정해서 대입했음.

    (mc.*(mc.Func1Ptr))(
"abc");    // 또는 (mc.*mc.Func1)("abc");
    (*mc.Func2Ptr)(
"abc");         // 전역 함수 포인터와 유사하므로 mc.Func2Ptr("abc") 가능.

    cf) 다른 멤버 함수에서 멤버 함수 포인터를 사용할 때는
    (
this->*Func1Ptr)("abc");
    Func2Ptr(
"abc");               // (*Func2Ptr)("abc")

    물론 꼭 MyClass의 멤버 변수로 존재할 필요는 없다. 다른 클래스의 멤버 변수로도 가능하다.

    주의 : 위의 경우는 꼭 필요한 상황인지, 설계상의 문제는 없는지 다시 한 번 고려할 것.
           다른 방법으로도 충분히 해결되는 문제임.


나.
typedef의 사용법 & 함수 포인터 배열

    함수 포인터의 배열은 무척 간단하다. 위의 예제의 foo 함수의 경우에는

   
void (*foo_ptr[])() = {foo1, foo2, foo3, ...};     // 선언&정의 + 대입
    (*foo_ptr[i])();                                  
// 사용

    로 하면 된다. 다른 함수 포인터도 유사하다.

    위에서 밝힌대로 함수 포인터는 변수이다. 변수는 형을 가진다. 그러면 함수 포인터의 형은 무엇인가?
    호출하려는 함수의 원형이 그 함수 포인터의 형이다. 즉 
typedef를 사용할 수 있다는 말이 된다.
    foo 함수에 대한 함수 포인터의 경우를 예로 들면

   
typedef void (*foo_ptr)();

    형태로 사용한다. 다만
void (*foo_ptr)();는 foo_ptr이 함수 포인터의 이름인데 반해
   
typedef void (*foo_ptr)(); 에서 foo_ptr은 함수 포인터의 형, void (*)()을 뜻하게 된다.
   
int a처럼 선언하듯이 typedef를 쓰면 foo_ptr fp; 뿐만 아니라 배열 선언을 foo_ptr fp[5];
    처럼 쓸 수 있고, 한결 깔끔하고 편리해지게 된다.
    개인적으로 함수 포인터와
typedef는 꼭 같이 쓰기를 권유한다.

    예 1)

   
class MyClass {
   
public:
       
void Func1(const string& txt);
       
static void Func2(const string& txt);
    };

   
typedef void (MyClass::*Func1Ptr)(const string&);
   
typedef void (*Func2Ptr)(const string&);

    Func1Ptr fptr = &MyClass::Func1;      
// 한결 더 의미가 명확해지고 코드 중복을 피할 수 있다.
    Func2Ptr ftpr2 = &MyClass::Func2;

    MyClass mc;
    (mc.*fptr)(
"abc");
    (*fptr2)(
"abc");

    예 2)

   
class MyClass {
       
typedef void (MyClass::*Func1Ptr)(const string&);
       
typedef void (*Func2Ptr)(const string&);
   
public:
       
void Func1(const string& txt);
       
static void Func2(const string& txt);
        MyClass() : fptr(Func1), fptr2(Func2) { }
       
void Invoke(const string& txt)
        {
            (
this->*fptr)(txt);
            (*fptr2)(txt);
        }
   
private:
        Func1Ptr fptr;
        Func2Ptr fptr2;
    };

    MyClass mc;
    mc.Invoke(
"abc");


참고 사이트
http://www.newty.de/fpt/fpt.html#defi

신고


Posted by injunech
2015.09.02 06:50


< 함수 포인터 >

먼저 이 글은 포인터에 대한 이해를 필요로 한다.

포인터에 대한 기본지식이 있다고 가정하고 글을 쓰도록 하겠다.


int GetAreaEx( int x, int y )
{
    return x * y;
}



우선 이런 간단한 함수가 있다. 우리는 이 함수를 호출하기 위해 명시적으로

GetAreaEx( x, y );

이런식으로 기술해야 한다.

하지만 예를 들어 GetArea2, GetArea3, ..., GetAreaN 이런식으로 비슷한 함수가 존재하고

이를 상황에따라 다르게 호출해야 한다면 이 방식으로는 관리도 어려울 뿐더러 효율성도 떨어지고 코드량도 많이질 것이다.

또한 외부(스크립트 등)에서 어떤 특정한 함수를 호출하려 할때도 방법이 묘연할 것이다.


int (*GetArea)( int, int );

이 선언은 무엇일까?

언뜻보기에는 함수를 선언하는 것 같다.

이 선언은 함수에 대한 포인터를 선언한 것이다.

변수의 주소를 담는 포인터와 마찬가지로 함수포인터는 함수의 주소를 담는다.

GetArea = GetAreaEx; // 함수포인터 GetArea에 GetAreaEx()의 주소를 담는다
int nArea = (*GetArea)( x, y ); // (*GetArea)( x, y ); 로 GetAreaEx()함수를 호출하고 리턴받은 값을 nArea에 대입



이런식으로 GetAreaEx를 호출할 수 있다.

유의할점은 *GetArea를 꼭 ()로 감싸주어야 한다는 사실이다.

빼먹으면 컴파일러가 함수포인터를 통한 호출로 인식하지 못한다.


int (*GetArea[])( int, int ) = { GetAreaEx, GetArea2, GetArea3, ..., GetAreaN };

이것은 함수포인터 배열을 정적으로 선언한 것이다. 이렇게 배열로 기능이 비슷한 함수들을 묶어놓았다.

void CallFunc( int nState, int x, y )
{
    int nResult = (*GetArea[nState])( x, y );
}



그리고 그 함수들을 상황에 맞게 호출한다.

만약 함수포인터를 쓰지 않는다면

void CallFunc( int nState, int x, int y )
{
    int nResult;
    switch( nState )
    { 
         case STATE_EX:
              nResult = GetAreaEx( x, y );
         break;
         case STATE_2:
              nResult = GetArea2( x, y );
         break;
         case STATE_3:
              nResult = GetArea3( x, y ); 
         break;
    }
}


위와 같이 기술해야 할 것이다.

두 방식의 차이점과 함수포인터의 이점을 알 수 있겠는가

그렇다면 함수포인터 배열을 동적으로 할당하는 방법은 없을까?

다음과 같은 방법으로 할당할 수 있다.

int (**GetArea)( int, int ); // 함수포인터의 포인터
GetArea = new (int (*[N])( int, int )); // N은 배열의 크기



그리고 다음과 같이 사용하면 된다.

GetArea[0] = GetAreaEx;
GetArea[1] = GetArea2;
GetArea[2] = GetArea3;
...

int nResult = (*GetArea[nState])( x, y );



물론 사용후 delete [] GetArea; 해서 해제하는것을 잊으면 안된다.



< 클래스 멤버함수의 함수포인터화 >

함수포인터는 함수의 주소값을 담는다고 했다.

그렇다면 클래스 멤버함수의 주소값도 단순히 함수포인터에 담아서 호출할 수 있지 않을까?

int (*func)();
func = CFunc::GetArea;


하지만 이 방법은 GetArea()멤버함수가 static으로 선언되었을 때만 가능하다.

static으로 선언되지 않은 멤버함수(멤버변수를 건들여야 하는 멤버함수)를 이 방법으로 담으려 한다면 컴파일 에러가 뜰 것이다.

여기에 다음과 같은 해결방법이 있다.

첫번째 방법은

class CFunc
{
public:
    static int GetArea( CFunc * cls, int x, int y );
};



위와 같이 선언하고 호출할때 해당 인트턴스의 포인터를 넘겨줘서

int GetArea( CFunc * cls, int x, int y )
{
    int a = cls->GetZ();
}



이런식으로 멤버변수를 읽거나 쓸수 있겠지만 이 방식으로는 한계가 있다.

Get, Set 같은 public 외부함수로 억세스하지 않으면 private나 protected안에 선언되어 있는

멤버변수는 건드릴 수 없다.

두번째는 멤버함수의 소속을 명시화하는 방법이다.

int (CFunc::*func)( int, int );
func = CFunc::GetArea;
CFunc A;
(A.*func)( x, y );



위와 같은 방법으로 해결가능하다. 물론 호출할 인스턴스가 명확해야 한다.

세번째는 클래스 안에 함수포인터를 멤버변수로 두고 별도의 함수포인터를 컨트롤하는 멤버함수를 만드는 방법이 있다.

이 방법이 멤버함수 관리가 가장 쉬우며 효율적이다.

class CFunc
{
public:
    int (CFunc::*pFunc)( int, int );
    int GetArea( int x, int y );
    void CallFunc( void ) { (this->*pFunc)( x, y ); } // CallFunc 함수호출시 자체 오버헤드를 줄이기 위해 inline
    CFunc();
    ~CFunc() {}
};

CFunc::CFunc()
{
    pFunc = GetArea;
}
int CFunc::GetArea( int x, int y )
{
    return x * y;
}


위와 같다면 CallFunc(); 로 GetArea 호출이 가능해진다.

지금은 단순히 한개의 멤버함수 호출만 할뿐 의미가 없다. 이제 실제 효율적으로 쓰이게 배열을 써보자.

class CFunc
{
public:
    int (CFunc::**pFunc)( int, int );
    int GetArea( int x, int y );
    void CallFunc( int nState, int x, int y ) { (this->*pFunc[nState])( x, y ); }
    CFunc();
    ~CFunc();
};

CFunc::CFunc()
{
    // init
    pFunc = new (int (CFunc::*[10])( int, int )); // 동적할당, 10에는 원하는 멤버함수 갯수만큼
    // 0번은 남겨둔다.

    pFunc[1] = GetArea;
    pFunc[2] = GetAreaEx;
    pFunc[3] = GetArea2;
    pFunc[4] = GetArea3;
    ...
    pFunc[9] = GetArea9;
}
CFunc::~CFunc()
{
    delete [] pFunc; // 해제
}
int CFunc::GetArea( int x, int y )
{
    return x * y;
}


자, 이제 함수하나의 호출로 상황에따라 여러 멤버함수를 호출할 수 있는 기반이 마련되었다.

CFunc A;
A.CallFunc( nState, x, y );



이렇게...

어떠한가. 함수포인터의 위력이 느껴지는가?




< STL을 이용한 함수포인터 관리 >

우리는 지금까지 함수포인터를 동적으로 배열을 할당해서 써왔다.

함수 포인터를 STL(Standard Template Library)을 써서 관리해보자.

클래스의 멤버함수의 함수포인터화에서 3번째 방법을 조금 개선시켜 보겠다.



단순히 인덱스(숫자)를 이용한 관리라면 deque정도가 괜찮을듯 싶으나,

만약 함수의 이름을 문자열로 호출하고 싶다면 map을 써볼 수 있다.

(만약 FuncCall( "GetArea", x, y ); 이런식으로 멤버함수를 호출하고 싶다면)

map은 내부적으로 트리구조를 가지고 있다.

그래서 따로 정적/동적으로 배열을 할당하지 않아도 입력된 값을 비교해서 스스로 자신의 크기를 늘린다.

mapValue["GetArea"] = 99;

이런식으로 []안에 숫자 뿐만아니라 비교할 수 있는 모든 것이 들어갈 수 있다.

먼저 map을 사용하기 위해

#include < map >
using namespace std;



를 선언한다. map은 표준 네임스페이스를 사용하므로 std의 이름공간을 활용한다.

map< []안에 들어갈 타입, 입력될 데이터타입, 비교 논리 > mapFunctor;

선언방법은 이렇게 되는데 비교 논리는 첫번째 인수가 클래스이고 안에 비교오퍼레이터가 있다면 생략가능하다

자, 이제 해보자.



struct ltstr
{
    bool operator() ( const char * s1, const char * s2 ) const
    {
         return strcmp( s1, s2 ) < 0;
    }
};

class CFunc
{
public:
    typedef int (CFunc::*_Func)( int, int );
    map< const char *, _Func, ltstr > mapFunctor;
    int GetArea( int x, int y );
    void CallFunc( const char * szFuncName, int x, int y ) 
    { 
         (this->*mapFunctor[szFuncName])( x, y ); 
    }

    CFunc();
    ~CFunc();
};

CFunc::CFunc()
{
    // init
    mapFunctor["GetArea"] = GetArea;
    mapFunctor["GetAreaEx"] = GetAreaEx;
}
CFunc::~CFunc()
{
    // map 클리어
    mapFunctor.clear();
}
int CFunc::GetArea( int x, int y )
{
    return x * y;
}


char * 대신 string을 사용한다면 string안에 내부적으로 비교 오퍼레이터함수가 있기 때문에

map< string, _Func > mapFunctor;

이렇게 선언하고 사용할 수 있을 것이다.

이제 A.CallFunc( "GetAreaEx", x, y ); 란 호출로 GetAreaEx를 호출할 수 있다.

이 방식은 여러가지로 응용가능한데 스킬명에 의한 화면효과 호출이라던지

C로 미리 작성된 내부 함수를 외부 스크립트로 호출한다던지 할때 유용하게 쓰일 수 있다.

(스크립트 호출일 경우 함수이름을 인덱스화 해서 deque를 쓰는게 속도상 더 유리할 듯 하다)






출처 : http://zeph.tistory.com/155



신고


Posted by injunech
2015.08.23 22:46


1. Node

cocos2d-x의 기본 단위

거의 모든 객체들은 이 Node클래스를 상속받는다. 이것만 잘 알아도 cocos2d-x의 많은 부분을 알수 있다.

http://www.cocos2d-x.org/reference/native-cpp/V3.0alpha0/d3/d82/classcocos2d_1_1_node.html

Node의 멤버들..

-position : 위치 값,

-scale : 크기 배율값,

-rotation : 회전 각도,

-anchor point : 앵커 포인터(위치값의 기준 점을 설정 0~1까지 float),

-size : width, height,

-visible : 보이는지 여부,

-z-order : 출력시 위에 보이느냐 아래 보이느냐를 결정하는 수치

node->setPosition(Point(0, 0));
//대부분의 속성값은 get / set으로 사용가능

부모자식관계

Node의 가장 중요한 특징은 부모자식관계라고 생각한다. 클래스 상속과는 별개의 영역이며, 햇갈려서는 안된다.

자식은 부모의 영역안에서 상대적인 좌표로 이동, 회전, 스케일된다. 예를 들어 부모노드가 100, 100 좌표에 위치한다면, 그 자식인 노드의 좌표값이 0, 0 이라도 부모노드의 상대적 좌표값이 적용되어 실제로 전체화면에서는 100, 100 좌표에 있는 것 처럼 보인다.

반대로 여러 자식들을 가지고 있는 부모노드의 위치 스케일 등을 변경하면 그 안에 들어있는 모든 자식노드들의 값이 한꺼번에 변경된다. 이 때문에 부모 노드는 자식 노드를 담는 컨테이너로 사용되기도 한다.

parent->setPosition(Point(100, 100)); // 부모를 100, 100위치에 놓는다.
auto child = Node::create(); //자식을 만든다.
child->setPosition(Point(0,0));//자식을 0,0에 놓는다.
parent->addChild(child) //자식이 100, 100자리에 그려진걸 보고서 당황하지 않는다.

스마트 포인터

Node를 상속받는 모든 클래스들은 CREATE_FUNC(ClassName)으로 등록하면, ClassName::create()하는 것만으로 자동으로 메모리를 할당하고 알아서 해제가 된다.

새로운 인스턴스 생성할때, virtual bool init()이라는 함수를 자동으로 호출하므로 반드시 init함수의 형태를 구현해두어야한다.

기본적으로 레퍼런스 카운트 방식을 사용한다. addChild(node)하면 알아서 카운트가 1이 증가하고, removeChild(node)하면 카운트가 1줄어든다. 카운트가 0이되면 사라진다.

만약 할당한 메모리를 유지하고 싶다면, 인스턴스 객체에 node.retain()을 걸어주면 수동으로 카운트가 1 증가한다. 반대로 node.release()를 걸어주면 수동으로 카운트가 1 줄어든다. 하지만 메모리 릭이 발생하지 않도록 주의해서 관리해야한다.

스케쥴

http://injakaun.tistory.com/102

노드를 상속받은 클래스들은 스케쥴을 통해 게임 루프를 처리해주는 스케쥴러에 특정 함수를 등록할 수 있다. 스케쥴로 등록한 함수는 게임 루프시마다 호출된다. 주로 각 객체의 update함수들이 등록되어 루프할때마다 호출된다.

schedule( schedule_selector( GameLayer::update ) , 0.1f );
//schedule_selector의 인자로 함수포인터를 넘겨주는데, 반드시 앞에 어떤 클래스의 함수인지를 써줘야한다.
//그리고 뒤에 이 함수가 실행되는 딜레이를 적어준다.
scheduleUpdate(); //귀찮으면 이걸 쓴다. 대신 update함수는 노드에서 제공하는 형식을 맞춰줘야한다.

무작정 스케쥴업데이트를 사용하면 업데이트 순서가 꼬일 수 있으니 주의하자. 자식노드의 업데이트를 부모노드의 업데이트에 몰아서 한큐에 처리하는 방식으로 꼬임 문제를 해결하였다. sheduleUpdateWithPriority를 사용하는 것도 방법이 될 수 있을 거라 생각한다.

unschedule을 통해서 스케쥴러에서 제외시킬 수 있고, pause와 resume을 통해 잠시 멈췄다가 다시 수행하게 할 수 있다. scheduleOnce를 잘쓰면 괜히 여러번 호출할 필요없이 한번만 불러오게 할 수도 있다.

*removeChild이나 changeScene을 하면 그 안에 있던 객체는 retain을 해서 남아있더라도 그 객체에서 shedule된 함수들이 스케쥴러에서 제외된다. 제외된 함수들은 다시 스케쥴러에 넣어주지 않는한 루프에 호출되지 않는다.

2.Node의 상속자들

cocos2d::Scene / cocos2d::Layer / cocos2d::Sprite

Director

디렉터는 Node의 상속자는 아니지만 다른 상속자들과 밀접한 관련이 있기에 미리 언급하고 넘어간다. 디렉터는 cocos2d-x 내부에 있는 싱글톤 클래스로 화면을 관리하는 역할을 담당한다. 주로 화면에 출력할 Scene을 선택하고 전환하는 역할로 사용되었다. 추가로 다양한 씬 전환기법도 제공한다.

http://injakaun.tistory.com/98

Director::runWithScene(menuScene); //일단 디렉터로 씬하나 띄워야 뭐가 실행된다.
Director::getInstance()->replaceScene(gameScene); //적당히 조건에 맞게 씬을 변경한다.
//replaceScene을 하면 기존에 있던 씬은 제거(refCount--)된다. 추가로 업데이트들도 스케쥴에서 제외되므로 주의한다.

Scene

씬은 cocos2d-x에서 가장 기본이 되는 화면이다. Node의 상속자들의 부모자식관계망에서 제일 꼭대기에 위치한다. Scene에는 직접 스프라이트같은걸 붙이지는 않는다. 세부적인 화면 형태는 Layer에서 결정하고, 그런 Layer들을 모아서 한번에 출력하는 컨테이너로 Scene을 사용하는게 편리하다.

Layer

Layer도 Scene이랑 크게 다를것은 없으나 Scene과는 달리 여러개가 동시에 한 화면에 올릴 수 있기 때문에 각 분류에 따라 만들어지는 경향이 있다. 우리 프로젝트에서도 UI, Game, Background Layer들로 나누어서 각각 자신의 처리를 할 수 있게 하였다. 그리고 각 레이어들의 z축 값을 다르게 줘서 특정 레이어를 위에 특정 레이어를 아래 배치할 수도 있다.

auto gameLayer = Layer::create(); //게임 레이어를 만들어줍니다.
auto uiLayer = Layer::create(); //UI레이어도 만들어요
auto gameScene = Scene::create(); //게임이 돌아가느 화면인 게임씬을 만들고
gameScene->addChild(gameLayer, 1); //게임 레이어를 게임씬에 붙입니다. z축 값을 1로줘서 
gameScene->addChild(uiLayer, 2); //z축 값을 2 로 줘서 들어간 ui레이어는 항상 게임레이어보다 위에 출력됩니다.
Director::runWithScene(gameScene); //이걸 디렉터한테 실행시킵니다.

Sprite

실제 이미지가 올라가는 대부분의 노드가 Sprite이다. Sprite도 다른 Sprite를 자식노드로 가질 수 있기 때문에, 플레이어스프라이트에 장비스프라이트를 자식 노드로 붙여 계속 플레이어를 따라다니는 것처럼 만들어 줄 수 있다.

그리고 스프라이트는 여러장의 이미지들을 계속 변경하는 에니메이션을 추가하여 실제 움직이는 객체처럼 만들어 줄 수도 있다.

신고


Posted by injunech
2015.07.12 13:27


Cocose2d-x 를 Android (eclipse) 개발 환경에서 Class 추가 필요 없이 자동으로 Classes 폴더를 읽어서 넣는 방법입니다.


자신의 프로젝트 > proj.android > jni > Android.mk


아래 부분과 같이 변경한다.


FILE_LIST := $(wildcard $(LOCAL_PATH)/../../Classes/*.cpp)

LOCAL_SRC_FILES := hellocpp/main.cpp $(FILE_LIST:$(LOCAL_PATH)/%=%) 

신고


Posted by injunech
2015.06.19 12:00


Visual Studio 단축키



편집 관련 단축키


편집 관련 단축키들은 익혀두면 다른 문서를 작성 할때도 많이 도움이 될 것이다.

문서 편집 관련 단축키들은 사용하면 사용할 수록 코딩 속도가 빨라진다.

 

 

Ctrl + F : 찾기

중요도 : ★★★☆☆

활용 : 특정 클래스, 함수, 변수 등을 검색한다.

 

 

Ctrl + Shift + F : 파일에서 찾기

중요도 : ★☆☆☆☆

활용 : 특정 클래스, 함수, 변수 등을 검색한다. 현제 프로젝트가 아닌 파일에서도 찾을 수 있다.

 

  

Ctrl + Space : NameSpace

중요도 : ★★★★★

활용 : 현재 접근 가능한 클래스명, 함수명, DEFINE문 등의 목록을 보여준다.

         코드를 치는 도중 Ctrl + Space를 누르면 이전에 선언된 것과 

         가까운 목록을 보여주며 선택을 함으로써 쉽게 완성이 가능하다.

         목록이 하나뿐이라면 그것으로 자동 완성 해준다.

 

 

Ctrl + Shift + Space : Parameter

중요도 : ★★★★★

활용 : 커서가 클래스명의 뒤에 있을 때 접근가능한 변수, 함수 목록을 보여준다.

         코드를 치는 도중 Ctrl + Shift + Space를 누르면 이전에 선언된 것과

         가까운 목록을 보여주며 선택을 함으로써 쉽게 완성이 가능하다.

         목록이 하나뿐이라면 그것으로 자동 완성 해준다.

  

 

Home : 커서가 위치한 줄의 코드 시작 위치로

중요도 : ★★★★★

활용 : 커서의 위치와 관계없이 해당 줄의 코드 시작위치로 커서를 옮긴다.

         블록을 잡기 위해서, 커서의 빠른 이동 등에 많이 사용된다.

 

 

End : 커서가 위치한 줄의 코드 끝 위치로

중요도 : ★★★★★

활용 : 커서의 위치와 관계없이 해당 줄의 코드 마지막위치로 커서를 옮긴다.

  

Shift + Home : 커서가 위치한 줄 모두 블록

Shift + End : 커서가 위치한 줄 모두 블록

중요도 : ★★★★★

활용 : 커서 위치가 가장 앞에 있다면 Shift + End를 이용해 그 줄을 블록하고 

         커서 위치가 가장 뒤에 있다면 Shift + Home를 이용해 그 줄을 블록한다.

 

  

Shift + ← or → or ↑ or ↓ : 블록 잡기

중요도 : ★★★★☆

활용 : 여러 줄을 블록할 때 많이 사용한다.

 

 

드래그 + Alt : 현재 커서 위치부터 움직인 커서 위치까지 블록

중요도 : ★★★★☆

활용 : 마우스 드래그 중 Alt를 누르면 드래그하는 영역을 사각형으로 봤을 때 그 영역을 블록하게 된다.

         특정 부분을 선택하고 싶거나, 탭을 먹이고 싶을 때 많이 사용된다.

 

 

Ctrl + ←, → : 구분단위로 커서 이동

중요도 : ★☆☆☆☆

활용 : 현재 줄에서 커서를 좌우로 이동할 때 변수, 공백, 탭, 등의 구분단위로 이동하게된다.

         보다 빠른 커서위치를 조정하고, 블록할 때 사용된다.

 

 

Ctrl + Shift + ← or → : 구분단위로 블록

중요도 : ★☆☆☆☆

활용 : 현재 줄에서 블록을 할 때 변수, 공백, 탭 등의 구분단위로 블록영역을 설정한다.

         보다 빠르게 블록 영역을 설정할 때 편리하다.

 

 

Ctrl + M, L : 전체 + 버튼으로 만들기

중요도 : ★★★☆☆

활용 : 현재 소스 전체를 {}영역 별로 +버튼으로 만들어준다.

         +버튼은 소스가 삭제되는 것은아니라 감춰두는 것으로 볼 수 있다.

         소스가 길어 함수 정의나 클래스 정의 부분을 빨리 찾고 싶을 때 많이 사용된다.

 

 

Ctrl + M, M : 커서 위치가 속한 곳을 + 버튼으로 만들기

중요도 : ★★☆☆☆

활용 : 커서의 위치를 {}단위로 판단하여 커서가 속한 곳을 +버튼으로 만든다.

  

Ctrl + M, L : 선택된 곳을 +버튼으로 만들기

중요도 : ★★☆☆☆

활용 : 블록을 선택된 영역을 +버튼으로 만든다.

 

Shift + Delete : 커서가 위치한 줄 삭제

중요도 : ★★★★☆

활용 : 커서가 위치한 줄을 삭제한다.

         빠르게 현재 줄을 삭제할 때 많이 활용된다. 

 

Ctrl + L : 커서가 위치한 줄 삭제, 선택된 줄단위로 삭제

중요도 : ★★★★☆

활용 : 위 단축키와 비슷하지만 영역을 선택했을 때 여러줄을 줄단위로 삭제 한다.

  

Ctrl + K, C : 선택 영역 주석 달기

중요도 : ★★★★☆

활용 : 선택 영역의 주석을 한 단계씩 추가한다.

  

Ctrl + K, U : 선택 영역 주석 없애기

중요도 : ★★★★☆

활용 : 선택 영역을 주석을 한 단계씩 감소시킨다.

 

Alt + F8 : 선택 영역 코드 탭 정리하기

중요도 : ★★★★☆

활용 : 선택한 영역의 코드들의 탭이 뒤죽박죽일 때 사용하면 편리하다.

 

 


 

디버깅 관련 단축키

 

F7 : 빌드

중요도 : ★★★☆☆

활용 : 이번 빌드 상태와 비교하여 수정된 소스에 대해 다시 빌드한다.

 

 Ctrl + Alt + F7 : 전체 다시 빌드

중요도 : ★★★☆☆

활용 : 현재 솔루션 전체를 다시 빌드한다. 링크가 꼬엿을 때 외엔 잘 사용하지 않는다.

 

 

F5 : 빌드 + 실행

중요도 : ★★★★★

활용 : F7을 누른후 실행한 결과와 같다.

 


Ctrl + F5 빌드 없이 실행

중요도 : ★☆☆☆☆

활용 : 최근에 빌드된 상태의 실행 파일을 실행시킨다.

         소스 수정없이 다시 실행 시키고 싶을 때 빌드 시간 없이 실행 하므로 빠르다

  

 

F9 : 브레이크 포인트 설정

중요도 : ★★★★★

활용 : 현재 커서가 위치한 줄에 중단점을 설정한다.

         중단점이 걸리면 디버그시 해당 코드를 실행하기전에 중지되어 사용자에게 코드 위치를 보여준다.

 


F10 : 줄단위 실행

중요도 : ★★★★★

활용 : 디버깅 모드에서 현재 디버깅하고있는 소스의 줄단위로 진행 시킨다.

 

 

F11 : 코드 단위 실행

중요도 : ★★★★★

활용 : 디버깅 모드에서 현재 진행중인 커서위치의 코드를 실행한다.

         커서위치의 코드내에 함수가 있다면 그 함수의 내부로 들어가게 된다.

  

 

F12 : 정의로 이동

중요도 : ★★★★★

활용 : 변수, 함수, 클래스 등의 선언부로 이동한다.

         눈에 보이는 변수, 함수 등의 정체를 확인하는데 많이 사용된다.

  

 

Ctrl + '-'키 : 이전 커서 위치로

중요도 : ★★★★★

활용 : 이전 커서위치로 이동하게 된다.

         보통 F12로 변수를 탐색한후, 다시 돌아오는데 많이 사용한다. 

 

Ctrl + Shift + '-'키 : 다음 커서 위치로

중요도 : ★☆☆☆☆

활용 : 위의 단축키와 반대 되는 개념이다.

 

Ctrl + F2 : 커서가 위치한 줄에 책갈피 설정

중요도 : ★★★☆☆

활용 : 현재 문서에서 커서가 위치한 줄에 책갈피를 설정한다.

         책갈피는 관심있는 코드를 메모해놓고 쉽게 접근하기 위해 사용한다.

 

 

F2 : 다음 설정된 책갈피로 커서 이동

중요도 : ★★★☆☆

활용 : 현재 문서에서 설정된 책갈피가 있을 때 순차적으로 책갈피를 탐색한다.

 

 

Ctrl + Shift + F2 : 설정된 책갈피 모두 삭제

중요도 : ★★★☆☆

활용 : 현재 문서에 설정되어 있는 책갈피를 모두 삭제한다.


 

Ctrl + F10 : 커서 위치까지 실행

중요도 : ★★☆☆☆

활용 : 현재 커서가 위치한 곳까지 실행하게 된다.

         편집상태라면 빌드 + 커서 위치까지 실행된다.

         한손으로 누르기 힘든 단축키라 우클릭 메뉴를 이용해도 좋다. 

 

 

 

기타

 

마우스 우클릭 - Find All Refrence : 모든참조 찾기

중요도 : ★★★★☆

활용 : 현재 커서가 위치한곳의 변수나 함수등이 사용된 곳을 프로잭트에서 모두 찾아 표시한다.

         LifeCycle 을 알아보는데도 좋다.


 

Alt + P + P : 프로젝트 속성

중요도 : ★☆☆☆☆

활용 : 프로젝트의 속성을 본다. 프로젝트 속성을 보는일은 많이 없으므로 큰 활용도는 없다.

 


마지막으로 지금까지 단축키 목록을 나열하겠다.

 

Ctrl + F : 찾기

Ctrl + Shift + F : 파일에서 찾기

Ctrl + Space : NameSpace

Ctrl + Shift + Space : Parameter

Home : 커서가 위치한 줄의 코드 시작 위치로

End : 커서가 위치한 줄의 코드 끝 위치로

Shift + Home : 커서가 위치한 줄 모두 블록

Shift + End : 커서가 위치한 줄 모두 블록

Shift + ← or → or ↑ or ↓ : 블록 잡기

드래그 + Alt : 현재 커서 위치부터 움직인 커서 위치까지 블록

Ctrl + ←, → : 구분단위로 커서 이동

Ctrl + Shift + ← or → : 구분단위로 블록

Ctrl + M, L : 전체 + 버튼으로 만들기

Ctrl + M, M : 커서 위치가 속한 곳을 + 버튼으로 만들기

Ctrl + M, L : 선택된 곳을 +버튼으로 만들기

Shift + Delete : 커서가 위치한 줄 삭제

Ctrl + L : 커서가 위치한 줄 삭제, 선택된 줄단위로 삭제

Ctrl + K, C : 선택 영역 주석 달기

Ctrl + K, U : 선택 영역 주석 없애기

 

F7 : 빌드

Ctrl + Alt + F7 : 전체 다시 빌드

F5 : 빌드 + 실행

Ctrl + F5 : 빌드 없이 실행

F9 : 브레이크 포인트 설정

F10 : 줄단위 실행

F11 : 코드 단위 실행

F12 : 정의로 이동

Ctrl + '-'키 : 이전 커서 위치로

Ctrl + Shift + '-'키 : 다음 커서 위치로

Ctrl + F2 : 커서가 위치한 줄에 책갈피 설정

F2 : 다음 설정된 책갈피로 커서 이동

Ctrl + Shift + F2 : 설정된 책갈피 모두 삭제

Ctrl + F10 : 커서 위치까지 실행

Alt + F8 : 선택 영역 코드 탭 정리하기

 

마우스 우클릭 - Find All Refrence : 모든참조 찾기

Alt + P + P : 프로젝트 속성



출처 : http://cafe.naver.com/hgclient/77


신고


Posted by injunech
2015.06.11 21:35


윈도우를 사용하시던 분들은 탭이동을 할때 간단하게 Ctrl+Tab 으로 이동을 하게 된다.

탭 다음 이동 : Ctrl+Tab

탭 이전 이동 : Ctrl+Shift+Tab

하지만 이클립스에서는 이런 키를 눌렀을 때 그냥 상단의 도구모음 아이콘의 포커스만 변경된다.


이클립스에서는 위 키에 대한 대응이 다음과 같다.

탭 다음 이동 : Ctrl+Page Up ( Ctrl + F6 )

탭 이전 이동 : Ctrl+Page Down ( Ctrl + Shift + F6 )

이대로 쓰지 않고 원래 윈도우에 맞도록 변경시킬려면


1. [메뉴] Window -> Preferences -> General -> Keys

2. "type filter text" 입력란에 "Next Editor" 입력 후 "Copy Command" 버튼 클릭

3. 복사한 command 를 선택 후 Binding 부분에 사용할 키를 입력(CTRL+TAB)

신고


Posted by injunech
2015.06.08 23:57


리소스 접근시 여러가지 방법이 있겠지만

Bitmap testImg = BitmapFactory.decodeResource(res, R.drawable.testRes0);

이런식으로 파일 ID로 리소스를 읽어와 사용하고 있었습니다.
그런데 리소스가 많을 경우 

testImg = new Bitmap[10];
for(int i = 0; i < 10; i++)
        testImg[i] = BitmapFactory.decodeResource(res, R.drawable.testRes0+i);

이런식으로 ID로 연산을 하여 읽어오다보면 ID가 꼬이는 경우 문제가 발생할 여지가 많더군요.
파일명이 순차적으로 되어 있다고 하더라도 이런식의 접근은 안좋은 방법인것으로 알고 있습니다.

이럴경우

int tmpID;
testImg = new Bitmap[10];
for(int i = 0; i < 10; i++)
{
       tmpID = res.getIdentifier( "testRes"+i, "drawable" , "com.androidpub.android.test");
       testImg[i] = BitmapFactory.decodeResource(res, tmpID);
}

이런식으로 리소스 파일명으로 ID를 알아와 접근하는 방식을 사용할 수 있습니다.

"패키지명 : 타입 / 리소스명", null, null
getIdentifier("com.androidpub.android.test:drawable/testRes", null, null);

또는

"리소스명", "타입", "패키지명"
getIdentifier("testRes", "drawable", "com.androidpub.android.test");

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


문자열로 해당 Resource (혹은 레이아웃에 포함된 View) 의 ID 값을 가져온다;

-----------------------------------------------------------------
getResources().getIdentifier(파일명디렉토리명패키지명);
또는,
getResources().getIdentifier(패키지명:디렉토리/파일명nullnull);
으로도 가능하다.
-----------------------------------------------------------------

String resName = "@drawable/imgEnd";
String packName = this.getPackageName(); // 패키지명
int resID = getResources().getIdentifier(resName, "drawable", packName);

String viewName = "imgViewEnd";
String packName = this.getPackageName(); // 패키지명
int resID = getResources().getIdentifier(resName, "id", packName);


주로 리소스/ 뷰의 이름을 조합형식으로 만들어 가져와야 할 경우에
이 같은 코드를 사용하여 처리할 수 있다.


예를 들어,

for (int i=0; i < 3; i++) {
    String resName = "@drawable/img_" + i;
    // 결론적으로 이미지 리소스 이름은 img_1, img_2, img_3 이 되겠다;
    int resID = getResources().getIdentifier(resName, "drawable", packName);

    ImageView iv = (ImageView)findViewById(R.id.imgView);
    iv.setImageResource(resID); // 이미지뷰의 이미지를 설정한다;
}

이렇게 사용이 가능하다.

신고


Posted by injunech
2015.06.04 17:38


Quick Sort(퀵정렬)

 

알고리즘

 

연속적인 분할에 의한 정렬처음 하나의 축을 정해서 이 축의 값보다 작은 값은 왼쪽에

큰 값은 오른쪽으로 위치시킨다왼쪽과 오른쪽의 수 들은 다시 각각의 축으로 나누어져

축값이 1이 될 때까지 정렬한다

 

특징

 

안정성 없음

 

O(NlogN) : 최선의 경우 log2N (축값이 정확히 가운데를 가질 경우)

O(N^2) : 최악의 경우

 

가장 많이 사용되는 정렬법으로 1960 C.A.R. Hoare에 의해 고안되었다.

 

Code(코드)

 

재귀함수를 사용한다.

 

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
#define SIZE 20
#define SWAP(x,y,t) ( (t)=(x), (x)=(y), (y)=(t) )
 
void QuickSort(int left, int right);
 
int array[SIZE];
 
int main(void){
int i;
srand((unsigned int)time(NULL));
 
for ( i = 0; i < SIZE; i++ )
array[i] = rand() % (SIZE*10) + 1;
 
printf("array for sorting : \n");
 
for ( i = 0; i < SIZE; i++ )
printf("%4d", array[i]);
 
 
printf("\nProcessing : \n");
 
QuickSort(-1, SIZE-1);
 
printf("Soredted array : \n");
 
for ( i = 0; i < SIZE; i++ )
printf("%4d", array[i]);
 
printf("\n");
 
return 0;
}
 
void QuickSort(int left, int right){
int m, p, t;
int i, j;
 
for ( i = 0; i < SIZE; i++ )
printf("%4d", array[i]);
 
printf("\n");
 
if ( left < right ){
p = array[right];
for(i=left-1, j=right; ; ){
while ( array[++i] < p );
while ( array[--j] > p );
 
if ( i > j )
break;
 
SWAP(array[i], array[j], t);
}
 
array[right] = array[i];
array[i] = p;
 
QuickSort(left, j);
QuickSort(i+1, right);
}
}


신고


Posted by injunech
2015.06.02 21:17




Visual Studio Community 2013


아래 경로에서 비주얼스튜디오 2013 무료로 다운하여 사용 가능합니다.


https://www.visualstudio.com/en-us/products/visual-studio-community-vs


신고


Posted by injunech
2015.05.31 21:44


언어 (국가)

폴더 이름

(언어)

폴더 이름

(언어 + 국가)

체코어 (체코)

values-cs

values-cs-rCZ

독일어 (독일)

values-de

values-de-rDE

독일어 (오스트리아)

values-de-rAT

독일어 (스위스)

values-de-rCH

독일어 (리히텐슈타인)

valued-de-rLI

영어 (미국)

values-en

values-en-rUS

영어 (영국)

values-en-rGB

영어 (캐나다)

values-en-rCA

영어 (호주)

values-en-rAU

영어 (뉴질랜드)

values-en-rNZ

영어 (싱가포르)

values-en-rSG

스페인어 (스페인)

values-es

values-es-rES

프랑스어 (프랑스)

values-fr

values-fr-rFR

프랑스어 (벨기에)

values-fr-rBE

프랑스어 (캐나다)

values-fr-rCA

프랑스어 (스위스)

values-fr-rCH

이태리어 (이탈리아)

values-it

values-fr-rIT

이태리어 (스위스)

values-fr-rCH

일본어 (일본)

values-ja

values-ja-rJP

한국어 (대한민국)

values-ko

values-ko-rKR

네덜란드어 (네덜란드)

values-nl

values-nl-rNL

네덜란드어 (벨기에)

values-nl-nBE

폴란드어 (폴란드)

values-pl

values-pl-rPL

러시아어 (러시아)

values-ru

values-ru-rRU

중국어 (중국)

values-zh

values-zh-rCN

중국어 (대만)

values-zh-rTW



신고


Posted by injunech

티스토리 툴바