블로그 이미지
게임개발자 그건일

카테고리

분류 전체보기 (236)
개발 (139)
취미생활 (75)
기타 (20)
Total105,982
Today30
Yesterday14

소스 :  

xlsreader.zip



csv 파일로 뽑으면 읽기 편리하지만 그러면 xls 을 csv 로 변환하는 과정을 거쳐야 하므로 불편합니다.
엑셀파일을 읽기 위해 ado 를 사용해야하는데 엑셀파일을 읽기위해서는 드라이버가 필요합니다.
(office 가 설치되어있어야 한다는 의미)

의도하지 않았지만 수식의 결과값을 읽어올 수 있습니다. (그래서 csv 변환 과정이 필요 없습니다.)
예: =sum(A1:A4)


//-------------------------------- 
// C++ 코드
//--------------------------------

BAdoExcel excel;

xlsreader.zip


excel.Open("sample.xlsx", "Sheet1");
for(int r=0; r<excel.m_row; r++)
{
for(int c=0; c<excel.m_col; c++)
{
printf_s("%d,%d = %s\n", r, c, excel.GetValue(r, c));
}
}

이런 형식으로 사용합니다.

수식으로 작성된 값도 읽을 수 있으며 여러모로 좋으나 단점이 있습니다.
ADO 가 DB 를 읽는 방식으로 되어있어서 생기는 문제로 추측됩니다.

단점


첫줄은 읽을 수 없음
  첫번째 라인은 컬럼명으로 인식합니다. 그래서 값으로 읽어올 수 없습니다.

두번째 줄의 값이 기준 타입이 됩니다
 1개의 컬럼은 동일의 타입 값만 들어갈 수 있습니다. (DB 에서 그렇쵸)
 그래서 엑셀 역시 그런식으로 추측됩니다.
 만약 A 열에 글자를 쓰게 되면 읽을 수 없게 됩니다.


추가
lua_tinker 관련 코드를 추가합니다.
스크립트에서 사용할 수 있도록 만들어서 제공하기 위해 제작하였습니다.

//------------------------------------------------
// lua_tinker bind code
//------------------------------------------------
lua_State* L = lua_open();
luaopen_base(L);
luaopen_string(L);

lua_tinker::class_add<BAdoExcel>(L, "Excel");
lua_tinker::class_con<BAdoExcel>(L, lua_tinker::constructor<>());
lua_tinker::class_def<BAdoExcel>(L, "Open", &BAdoExcel::Open);
lua_tinker::class_def<BAdoExcel>(L, "Val", &BAdoExcel::GetValue);
lua_tinker::class_mem<BAdoExcel>(L, "row", &BAdoExcel::m_row);
lua_tinker::class_mem<BAdoExcel>(L, "col", &BAdoExcel::m_col);

//------------------------------------------------
// lua code
//------------------------------------------------
e = Excel()
e:Open("sample.xls", "Sheet1");
print("row:" .. e.row);
print("col:" .. e.col);
for r=0, e.row-1, 1 do
for c=0, e.col-1, 1 do
  print("[" .. r .. "][" .. c .. "][" .. e:Val(r,c) .. "]");
end
end
 


저작자 표시
신고
Posted by 그건일
TAG ADO, C++, xls, xlsx
웹서버의 파일을 다운로드하는 코드
(패치시스템을 만들때 기본이죠)
  
 
#include 
#include 
#pragma comment(lib, "wininet.lib")

void download()
{
	HINTERNET hInternet = InternetOpenA("HTTPFILE", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
	HINTERNET hURL = InternetConnectA(hInternet, "www.gamecodi.com", 80, "", "", INTERNET_SERVICE_HTTP, 0, 0);
	HINTERNET hRequest = HttpOpenRequestA(hURL, "GET", "/top_logo_main.gif", NULL, NULL, NULL, 0, 0);
	BOOL bRet = HttpSendRequest(hRequest, NULL, 0, NULL, 0);
	DWORD dwContentLen = 0;
    DWORD dwBufLen = sizeof(dwContentLen);
    BOOL bRet2 = HttpQueryInfo(
		hRequest,
		HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER,
		(LPVOID)&dwContentLen,
		&dwBufLen,
		0
		);

	FILE* f = NULL;
	fopen_s(&f, "a.png", "w+b");

	CHAR buf[1024*10];
	DWORD dwRecvLen = 0;
	DWORD dwBytesRead = 0;
	while(dwContentLen > dwRecvLen)
	{		
		BOOL bRet3 = InternetReadFile(hRequest, buf, sizeof(buf), &dwBytesRead);
		if(!bRet3 || dwBytesRead == 0)
		{
			DWORD dwErr = GetLastError();
			dwErr = 0;
			break;
		}

		dwRecvLen += dwBytesRead;

		fwrite(buf, 1 , dwBytesRead, f);
		printf_s("size: %10d / %10d (%3.2f)\n", dwRecvLen, dwContentLen, float(dwRecvLen)/float(dwContentLen) * 100.0f);
	}

	fclose(f);

	InternetCloseHandle(hRequest);
	InternetCloseHandle(hURL);
	InternetCloseHandle(hInternet);

	return 0;
}

 
 
 
 
 
저작자 표시
신고
Posted by 그건일



책읽을 시간이 얼마 없어 날림으로 빠르게 정리해볼 생각입니다.

  - 포인터와 레퍼런스 구분
    1. 주관적인생각 : 레퍼런스와 포인터는 동일하다 다만 코딩에서 -> 이걸 빼고 싶었기에 만들어낸것
    2. char* p = 0;   
       char& rp = *p;
      이런 예제가 나옵니다. 
      실제로 심각한 코드 이며 레퍼런스가 안전을 위해 나온게 아니라는 점을 알 수 있습니다.
 
  - c++ 용 케스트를 써라
    1. reinterpret_cast : c 의 캐스팅 입니다. 만능이죠
    2. static_cast : 산술 적으로 캐스팅이 가능한 것만 캐스팅됩니다.  
       double -> int   (o)
       int    -> void* (x)
    3. const_cast : const 를 벋겨내려고 할때 사용합니다.
       const char* -> char*
    4. dynamic_cast : RTTI 기능을 이용합니다.
       상속으로 구현된 클래스를 변환 가능한 경우에는 캐스팅이 성공하고
       캐스팅이 안되는 경우에는 null 을 반환합니다.
       기본 RTTI 는 느리기 때문에 2년이상차 분들은 직접 구현하십니다.

  - 배열과 다형성은 같은 수준으로 놓고 볼 것이 아니다.
    - 이건 패스

  - 쓸데 없는 기본 생성자는 그냥 두지 말자
    1. 기본생성자를 정의 하면 배열 형식으로 선언 가능하다.
       class A
       {
       public:
         A();  
       };
       A* pa = new a[3];  // 성공

       class B
       {
       public:
         B(int i);  
       };
       B* pb = new b[3];  // 이젠 안됨

       배열 선언을 막고 싶다면 코딩으로 막을 수 있습니다.
    2. 스택할당은 그래도 가능하군요
       B* pb[3] = { B(0), B(1), B(2), };
    3. 억지 생성 과 억지 소멸 코드 설명
       raw 메모리에 강제로 할당해버리는 기능인데 메모리 관리 모듈(혹은 메모리 풀)에 사용할 수 있지만
       평방한 기능으 아니니 다른 개발자에게 노출시킬 용도라면 쓰지 않는게 맞습니다.

챕터1은 여기서 끝났군요 30분정도 걸리네요




저작자 표시
신고
Posted by 그건일

class A 
{
public: 
    void memberA() { 
        //do something
    } 

    void memberB() { 
        //do something
    }
};
typedef void (A::*LPF_A_MEMBER_FUNC)();
 
void test()
{
	//맵버 함수 포인터 뽑기
	LPF_A_MEMBER_FUNC f1 = A::memberA;
	LPF_A_MEMBER_FUNC f2 = A::memberB;

	A a;
	//그냥 호출도 되고
	(a.*f1)();
	(a.*f2)();

	A* pa = &a;
	//포인터의 호출도 되고
	(pa->*f1)();
	(pa->*f2)();
}

보통 맴버 함수 포인터는 보통 이럴때 사용한다.
1. switch 의 case 가 너무 커질 경우 빠르게 돌리기 위해 정적배열이나 map 에 넣어 찾기를 한다.
2. switch 로 넣을 수 없는 case 를 돌릴때(if ~ else 가 주렁주렁 생기는 경우)

해시를 만들어 정적배열에 넣으면 switch 보다 성능도 괜찮다.

너무 까먹으면 한번씩 꺼내 보는 그 코딩~


저작자 표시
신고
Posted by 그건일

최근에 달린 댓글

최근에 받은 트랙백

글 보관함