소스 가독성 높이는 방법

C++ 2013. 10. 11. 15:29 |

void f() {
TextHandler t;
t.sendText(“Hello, world”, true);
}

class TextHandler {
public:
void sendText(const std::string& msg, bool sendNewLine);
};

 

소스 분석할때 true가 무었인지 찾아보고 의도를 파악해야 하지만, 아래와 같이 처리하면 바로 알아볼 수 있음

 

class TextHandler {
public:
enum NewLineDisposition { sendNewLine, noNewLine };
void sendText(const std::string& msg, NewLineDisposition newLineDisposition);
};

void f(){
TextHandler t;
t.sendText(“Hello, “, TextHandler::noNewLine);
t.sendText(“world”, TextHandler::sendNewLine);
}
이제 f() 함수는 그 자체로 개발자에게 코드의 의미를 전달할 수 있습니다. 즉 self-documenting되어 있습니다.

Refactoring시에 적용함으로써 코드의 readability와 maintainability를 높일 수 있을것입니다.

'C++' 카테고리의 다른 글

문자열 비교는 == 비교연산자 와 strcmp 어떤걸 써야 하는가..  (0) 2013.10.10
자바 객체의 사용 - NDK  (0) 2012.12.27
JNI Basic for NDK -4  (0) 2012.12.27
JNI Basic for NDK -3  (0) 2012.12.27
JNI Basic for NDK -1  (0) 2012.12.27
Posted by maysent
:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define __Text "hello"
 
int main(){
    char *textarr = "hello";
    char text[] = "hello";
    printf("비교대상 : #define __Text \"hello\", 외 스트링 \"hello\"\n");
    printf("textarr = %s, %c\ntext[] = %s, %c\n\n", textarr, *(textarr), text, *text);
 
    // 비교 첫번쨰
    if(textarr == "hello"){
        printf("1. \"hello\"와 textarr 는 같습니다.\n");
        printf("주소값 : %d, %d 로 두 값은 일치 합니다.\n\n", textarr, "hello");
    }
 
    // 비교 두번째
    if(__Text == "hello"){
        printf("2. \"hello\"와 define Text 는 같습니다.\n");
        printf("주소값 : %d, %d\n\n", &__Text, "hello");
    }
 
    // 비교 세번째
    if(__Text == textarr){
        printf("3-1. define Text 와 textarr 는 같습니다. ( 비교연산자 )\n");
        printf("주소값 : %d, %d\n\n", &__Text, &textarr);
    }
 
    // 비교 세번째 2
    if(__Text == text){
        printf("3-2. define Text 와 text 는 같습니다. ( 비교연산자 )\n");
        printf("주소값 : %d, %d\n\n", &__Text, &text);
    } else {
        printf("3-2. define Text 와 text 는 같지 않습니다. ( 비교연산자 )\n");
        printf("주소값 : %d, %d\n\n", &__Text, &text);
    }
 
    // 비교 네번째
    if(strcmp(__Text, text) == 0){
        printf("4. define Text 와 text 는 같습니다. ( strcmp 비교 )\n");
        printf("주소값 : %d, %d\n\n", &__Text, &textarr);
    }
 
    // 비교 다섯번째
    if(strcmp(text, textarr) == 0){
        printf("5. text 와 textarr 는 같습니다. ( strcmp 비교 )\n");
        printf("주소값 : %d, %d\n\n", &__Text, &textarr);
    }
 
    // 비교 여섯번째
    if(text == textarr){
        printf("text 와 textarr 는 같습니다.\n");
        printf("주소값 : %d, %d\n", &text, &textarr);
    } else {
        printf("6. ##### 배열 text 와 배열 textarr 는 같지 않습니다. ##### ( 비교 연산자 ) \n");
        printf("   ##### 이유 : %d, %d\n\n", &text, &textarr);
    }
 
    // 비교 일곱번째
    int __address = (int)&("hello");
    if((int)__Text == __address){
        printf("7. 문자열은 해당 문자열이 저장된 주소값(숫자)를 이용한 비교를 하게 됩니다..\n\n");
    }
 
    system("pause");
    return 0;
}

 

 

C에서 사용하는 비교 연산자(==)와 스트링 변수속 담겨있는 내용값의 비교를 하는 strcmp가 문자열 비교시 사용될 수 있는데, 각 상황별 비교 연산이 가능한 범위와 비교 일치가 되는 항목별로 나열하였습니다.

 

실행 결과 (http://ideone.com/b653q8)

 

 

비교대상 : #define __Text "hello", 외 스트링 "hello"
textarr = hello, h
text[] = hello, h

1. "hello"와 textarr 는 같습니다.
주소값 : 134514720, 134514720 로 두 값은 일치 합니다.

2. "hello"와 define Text 는 같습니다.
주소값 : 134514720, 134514720

3-1. define Text 와 textarr 는 같습니다. ( 비교연산자 )
주소값 : 134514720, -1077412700

3-2. define Text 와 text 는 같지 않습니다. ( 비교연산자 )
주소값 : 134514720, -1077412694


4. __Text 와 textarr 는 같습니다. ( strcmp 비교 )
주소값 : 134514720, -1077412700

5. text 와 textarr 는 같습니다. ( strcmp 비교 )
주소값 : 134514720, -1077412700

6. ##### 배열 text 와 배열 textarr 는 같지 않습니다. ##### ( 비교 연산자 )
##### 이유 : -1077412694, -1077412700

7. 문자열은 해당 문자열이 저장된 주소값(숫자)를 이용한 비교를 하게 됩니다.. 

 

 

 

 

예시중 3-1, 3-2 는 같은 char 배열 주소값을 놓고 상수형 스트링 __Text 와 비교하게 되는데

 

3-1 은 동일 문자열 판정 3-2는 다른 문자열로 판별 됩니다. 그 이유는 컴파일러의 옵티마이제이션 역할 덕 분이라는데

 

자세한 내용은 http://stackoverflow.com/questions/690176/c-c-optimization-of-pointers-to-string-constants

 

같은 의미로 __Text, *textarr, "hello" 결국은 같은 번지에 저장된 같은 스트링을 일컫게 된다는 이유로 1,2 번

 

또한 위와 같은 결론이 도출됨.

 

결론 : 포인터를 사용하는 상수 타입의 스트링들(동일 값을 가지는 스트링)은 하나의 주소로 관리하기도 한다. 하지만 정확

 

한 자원 관리를 확답 할 수 없다면 strcmp 를 써야 하는게 맞다.

'C++' 카테고리의 다른 글

소스 가독성 높이는 방법  (0) 2013.10.11
자바 객체의 사용 - NDK  (0) 2012.12.27
JNI Basic for NDK -4  (0) 2012.12.27
JNI Basic for NDK -3  (0) 2012.12.27
JNI Basic for NDK -1  (0) 2012.12.27
Posted by maysent
:

pugixml cocos2d-x

Cocos2Dx 2013. 10. 9. 18:32 |

cocos2d-x에서 xml parser를 사용하려고 이것저것 찾아봤는데, 소스코드 내에서 CCSAXParser라는 것을 발견하였지만 어떻게 사용하는지 몰라서 포기! 결국 찾다 찾다 pugixml이 가장 나은 것 같아서 이를 사용하게 되었다.

 

http://www.cocos2d-x.org/boards/6/topics/11313

위 주소를 참고해서 사용하게 되었는데~

 

우선 그냥 pugixml을 사용해서 cygwin을 이용해 빌드하면 에러가 난다!(ndk-r8 기준)

 

에러인 즉슨 g++ 컴파일러를 기본옵션으로 돌릴 때 throw 를 지원하지 않기 때문인듯 하다.

에러 내용은 무슨 -fexception 명령옵션을 사용해서 throw를 멈춰라.. 뭐 이런거였는데..

해결은 pugixml.cpp의 최 상단의 헤더 선언부 바로 아래에 PUGIXML_NO_EXCEPTIONS를 define해줬다.

 

즉, #define PUGIXML_NO_EXCEPTIONS 만 선언해 주면 끝.

내용을 보니까 PUGIXML_NO_EXCEPTIONS가 ifdef돼있는 경우 exception을 사용하지 않게 돼있더라~

 

그리고..

win32환경의 cocos2d-x에서는 load_file로도 xml이 잘 읽히지만, 문제는 android환경에서 돌릴때 이다.

assets에 있는 png나 jpg는 잘 읽으면서 그 외의 리소스는 잘 못 읽더라.

xml을 읽게 하기 위해서는 load_file이 아니고 다른걸 써야 하더라! 이 역시 위의 블로그를 참조했다.

 

길게 설명하면 귀찮으니 소스 한방으로 끝내자면...

 

 


안드로이드는 APK로 압축이 되어서 fopen 을 이용하는 함수가 제대로 안 먹힙니다.


그래서 pugixml을 load_file을 쓰면 안되고,  아래처럼 getFileData과 load_buffer를 이용해야 합니다.

    CCString *strXML = CCString::createWithFormat("data/crosswords/set%02d.xml", stage);
    unsigned long fileSize = 0;
    unsigned char *buffer = CCFileUtils::sharedFileUtils()->getFileData(strXML->getCString(), "r",&fileSize);
    xml_document xmlDoc;
    xml_parse_result result= xmlDoc.load_buffer(buffer, fileSize);

    if(!result) {
        CCLog("Error description: %s", result.description());
        CCLog("FileName: %s", strXML->getCString());
        CCLog("Error offset: %d", result.offset);
        return false;
    }

 

 


C++에서는 boost::serialization을  쓰는게 편한것을 알았고..  C#에서는 XML로 바로 serialization이 되기에 문제가 없지만..

 

그러면 cocos2d-x에서 파일저장을 위해 그 큰 boost::serialization을 쓸수 없진 않은가?

 

결국 XML 을 쓰긴 써야하는데 뒤져보니 아래와 같은 글에서 pugixml 을 사용하고 있당.. 쉬운것 같당...헤헤

http://roter.tistory.com/archive/20120717

 

괜히 tutorial 적당히 읽어보고 바꾸다가 삽질을 더 했지만,

어렵게 static 만들 필요 없이...

 

pugiconfig.hpp 에서

 

 #define PUGIXML_NO_EXCEPTIONS  // cygwin의 빌드를 위해서..

 

 #define PUGIXML_HEADER_ONLY
 #include "pugixml.cpp"

 

이것만 주석해제하고..

 

android.mk에서

LOCAL_CPPFLAGS += -fexceptions

 

한줄 추가했지롱

 

자 다음 문제는....

pugixml 의 예제대로 loadXML, SaveXML을 사용하면.. 안드로이드 기계에서는 경로를 제대로 못찾아 에러가 납니다...

 

1. 내가 저장하는 것이나 내가 런타임에서 저장한 파일 불러오려면

  안드로이드 기계에서 저장가능한 경로를 찾아야 하므로

 

pugi::xml_document doc2;
    doc2.load("<mesh name='Save_HwangJe'/>");
 
 std::string filePath = CCFileUtils::sharedFileUtils()->getWriteablePath();
 filePath.append("save_file_output.xml");

 

이런식으로 getWriteablePath를 불러준다..

 

2. 리소스폴더에 이미 저장된거 불러올 경우

 리소스폴더에서 불러오는 경로는 아래와 같이 이미 스프라이트 로드할때부터 사용

std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathFromRelativePath("XML/save_file_output.xml");

이러면 Resource/Xml/save_file_output.xml  불러온데이

 
Posted by maysent
: