티스토리 툴바


SQLite ver. 3.6.23.1 : http://www.sqlite.org
SQLiteSpy ver. 1.8.12 : http://www.yunqa.de/delphi/doku.php/products/sqlitespy/index
cppSQLite ver. 3.1 ( SQLite 3.0.8 Wrapper ) : http://www.codeproject.com/kb/database/CppSQLite.aspx




네이버 상에 친절하게 설명해주는 예제를 따라하다가 고생좀 했다.
http://blog.naver.com/elastica/50036176756

다름이 아니라 테이블을 SQLiteSpy에서 생성하고 코드 상에서 insert를 하려니 예외가 발생해버리는 것.
근데 이상하게도 코드상에서 테이블을 생성하고 insert하는건 또 문제가 없더라.

알고보니 SQLiteSpy에서 쓰는 SQLite 버전과 cppSQLite에 동봉되어 있는 lib와 dll의 버전이 하늘과 땅 차이었다.

라이브러리 만들기 귀찮아서 SQLiteSpy 이전 버전을 찾으려고 하니 3.0.8 내장판은 리스트에 없어서 GG.
하지만 소스를 보니 c파일 하나로 되어있어 lib 만드는 과정따윈 버리고 그냥 프로젝트에 c파일을 추가해버렸다.
( SQLite 홈페이지의 다운로드 페이지를 가보면 sqlite-amalgamation-3_6_23_1.zip과 아래부분에 sqlite-source_3_6_23_1.zip를 볼 수 있다. 예전에는 source에 있는 것 처럼 여러 파일로 되어있었던 까닭에 lib로 만들어서 사용했고, 지금은 통합되어 c파일 하나로 묶여 있는 까닭에 굳이 lib로 만들어서 사용할 필요는 없음 )

dll이야 홈페이지에서 제공해주기 때문에 가져다가 쓰면 OK.

다시 말하자면 위의 예제어서 달라지는 부분은

sqlite3.lib를 링커->추가종속성에 추가 -> sqlite.c파일을 프로젝트에 추가
cppSQLite3에서 제공되는 dll 사용 -> 공식 홈페이지에서 제공하는 dll 사용

밖에 없다. 나머지는 위의 예제 그대로 따라하면 된다.



이제 불안해야할 것은 cppSQLite가 이전 버전의 SQLite를 기준으로 만들어졌다는 거... 문제는 안 일으키려나...
저작자 표시 비영리 동일 조건 변경 허락
Posted by 키뤼

개인적으로 좋아하는 남자배우 두명중 한명인 휴 로리.
이번 63회 골든 글로브 시상발표에서도 그의 센스는 죽지 않았다!



수상소감 번역


P.S. 동영상 수정합니다. 직접 올린 뒤 자막 한번 넣어봤습니다.
저작자 표시 비영리 동일 조건 변경 허락
Posted by 키뤼
boost::regex_grep

boost::regex_search의 경우에는 최선(最先)의 결과만을 돌려주는 까닭에 불편함이 많아 파일 전체에서의 일치를 찾는다거나 하는 등의 복수개의 결과를 찾는데는 적합하지 않다. 물론 한줄씩 읽어들여 while로 돌리면서 찾는 것도 가능하지만 boost에서 친절하게도 regex_grep을 제공하는 까닭에 처음 사용해보기로 마음먹었다.

근데, 이놈이 regex_search나 regex_match랑은 조금 사용방법이 다르더라.

Predicate foo
함수의 첫번째 파라미터를 살펴보면 Predicate foo라고 되어있는데, 크게 두가지 방법으로 넘겨주면 된다.

1. 새로운 class를 만들어 operator() 을 오버로딩 해주고 해당 class의 인스턴스를 파라미터로 넘겨주는 방법
2. callback 함수를 만들어 파라미터로 넘겨주는 방법

이때 operator()나 callback 함수나 리턴타입은 bool, 파라미터는 const boost::match_result< iterator_type >& 타입이어야 한다.

const char* str / const std::string& s
함수의 두번째 파라미터로 입력 문자열을 넣어주면 되고, std::string, char* 둘다 가능하다.

const boost::regex& e
함수의 세번째 파라미터로 정규표현식을 넣어주면 된다.


한가지 주의할 점은 입력 문자열의 타입에 따라 세번째 파라미터의 boost::regex 타입도 iterator_type도 맞춰줘야 한다는 것이다. 무슨 말인지는 다음의 코드를 보면서!
#include <fstream>
#include <boost/bind.hpp>
#include <boost/regex.hpp>
#include <boost/smart_ptr.hpp>

bool Match( const boost::match_results<std::string::const_iterator>& match, std::vector< std::string >* pList )
{
	pList->push_back( match.str(1) );
	return true;
}

bool LoadFromFile( const std::string& filePath )
{
	std::ifstream ifs( filePath.c_str() );
	if( !ifs.is_open() || !ifs.good() )
		return false;

	// 텍스트 파일을 전부 읽어들여 문자열에 저장하기
	ifs.seekg( 0, std::ios::end );
	int length = ifs.tellg();
	ifs.seekg( 0, std::ios::beg );	
	boost::scoped_ptr< char > buf( new char[length] );
	ifs.read( buf.get(), length );

	std::vector< std::string > pList;
	boost::regex ex("\\s*(?<=technique)\\s(\\w+)");
	// 여기서는 bind를 썼지만, bind를 쓰지 않고 pList를 전역으로 만들어도 무관함.
	boost::regex_grep( boost::bind( Match, _1, &pList ), buf.get(), ex );

	ifs.close();
	return true;
}


여기서 regex_grep에 넘겨주는 입력 문자열은 char* 형이다. pList가 std::string의 vector이므로 iterator_type도 std::string::const_iterator일거라고 생각하고 넣었지만 에러! 나오는 결과는 아래와 같다.


에러 내용만 봐서는 잘못된게 없어보여 callback함수를 전역으로 만들어도 해보고, bind도 써보고, 멤버함수로도 만들어보고 3시간동안 뻘짓하였지만 결국 GG치고 iterator로 구현. 구현하다 보니 무엇을 잘못했는지 발견! 알고보니 iterator_type은 입력 문자열의 타입을 따라가야 하더라... std::string::const_iterator를 const char*로 바꾸니 컴파일 성공!

결국 입력 문자열에 따라 정규표현식의 타입도, iterator_type도 결정된다. 원래대로라면 입력 문자열이 std::string인 경우 operator()의 파라미터 타입은 std::boost::match_result< const std::string::const_iterator >이 될테고, 정규표현식의 타입은 basic_regex< std::string >이 되야하나, boost는 친절하게도 syntax sugar로 boost::smatch, boost::regex가 주어진다. 아래의 표는 입력 문자열의 타입에 대응하는 연산자 오버로딩 파라미터 타입과 정규표현식의 타입이다.

 input string type   iterator_type  match_results  basic_regex
 char*  const char*  boost::cmatch  boost::regex
 std::string  std::string::const_iterator  boost::smatch  boost::regex
 wchar*  const wchar*  boost::wcmatch  boost::wregex
 std::wstring  std::wstring::const_iterator  boost::wsmatch  boost::wregex



boost::regex_iterator

boost::regex_iterator를 사용하면 boost::regex_grep를 사용할 때 보다 코드가 조금 더 깔끔해진다. 기본적인 내용은 boost::regex_grep과 유사하므로 크게 언급하진 않고 몇가지 유의할 점만 적어보자면...

1. boost::regex_iterator도 입력 문자열 타입에 따라 적절한 iterator를 선택해줘야 한다.
2. boost::regex_iterator의 끝은 기본생성자로 생성한 regex_iterator와 비교하면 된다.

#include <fstream>
#include <boost/regex.hpp>
#include <boost/smart_ptr.hpp>

bool LoadFromFile( const std::string& filePath )
{
	std::ifstream ifs( filePath.c_str() );
	if( !ifs.is_open() || !ifs.good() )
		return false;

	// 텍스트 파일을 전부 읽어들여 문자열에 저장하기
	ifs.seekg( 0, std::ios::end );
	int length = ifs.tellg();
	ifs.seekg( 0, std::ios::beg );	
	boost::scoped_ptr< char > buf( new char[length] );
	ifs.read( buf.get(), length );

	std::vector< std::string > pList;
	boost::regex ex("\\s*(?<=technique)\\s(\\w+)", boost::regex::grep );
	std::vector< std::string > pList;
	boost::regex_iterator< const char* > it( buf.get(), buf.get()+length, rx );
	//boost::cregex_iterator는 boost::regex_iterator< const char* >의 syntax sugar
	boost::cregex_iterator end;
	boost::cmatch match;

	while( it != end )
	{
		match = *it;
		pList.push_back( match.str(1) );
		++it;	
	}

	ifs.close();
	return true;
}

이상한데서 한참동안 헤매는 바람에 시간은 좀 날렸을지는 몰라도 덕분에 regex_grep와 regex_iterator는 확실하게 배운듯 하다.
저작자 표시 비영리 동일 조건 변경 허락
Posted by 키뤼