BLOG ARTICLE C++ | 5 ARTICLE FOUND

  1. 2015.01.09 c++ string tokenizer
  2. 2015.01.08 cJSON parsing error using window utf-8 txt file, Remove UTF-8 BOM
  3. 2014.10.16 c++ Easing code
  4. 2014.04.16 c++ Builder 패턴
  5. 2014.04.15 c++ const

c++ string tokenizer

C++ 2015.01.09 22:08

1. Implement

This code use string class instead of strtok included in <string.h>.

void StringTokenize(const string& str, vector<string>& tokens, const string& delimiters)
{
    // Skip delimiters at beginning.
    string::size_type lastPos = str.find_first_not_of(delimiters, 0);
    // Find first "non-delimiter".
    string::size_type pos     = str.find_first_of(delimiters, lastPos);

    while (string::npos != pos || string::npos != lastPos)
    {
        // Found a token, add it to the vector.
        tokens.push_back(str.substr(lastPos, pos - lastPos));
        // Skip delimiters.  Note the "not_of"
        lastPos = str.find_first_not_of(delimiters, pos);
        // Find next "non-delimiter"
        pos = str.find_first_of(delimiters, lastPos);
    }
}

const string& str : target string to be split by delimiters

vector<string>& tokens : split sub strings will be pushed. This parameter is reference type, so It have to be not null.


2. Using Example

void main()
{
	vector<string> quiz_str_list;
	string quiz_str = "abc:def:ghi"        
	StringTokenize(quiz_str, quiz_str_list, ":");

	for(auto token : quiz_str_list)
		printf("%s\n", token.c_str());
}

Token size is 3. Result is

"abc"

"def"

"ghi"



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

c++ string tokenizer  (0) 2015.01.09
cJSON parsing error using window utf-8 txt file, Remove UTF-8 BOM  (0) 2015.01.08
c++ Easing code  (0) 2014.10.16
c++ Builder 패턴  (0) 2014.04.16
c++ const  (0) 2014.04.15

Sometime we get error from cJSON. Window utf-8 txt file attach big-endian information [EF BB BF]. It cause error when we parse json or use setcookie in PHP. I removed this information using Notepad++.

Download Link : http://notepad-plus-plus.org/


1. Save txt file to UTF-8

  File->Save to other -> Set encoding to UTF-8




2. Using Notepad ++

  Open txt file in Notepad++. Select UTF-8 without BOM







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

c++ string tokenizer  (0) 2015.01.09
cJSON parsing error using window utf-8 txt file, Remove UTF-8 BOM  (0) 2015.01.08
c++ Easing code  (0) 2014.10.16
c++ Builder 패턴  (0) 2014.04.16
c++ const  (0) 2014.04.15

c++ Easing code

C++ 2014.10.16 01:44

1. Easing Code

 Many games and App use Easing Algorithm like scrolling, character moving, etc. Blow show c++ code of Easing Algorithm.


start_value : 0 frame's value.

change_value : End frame's value - start_value


inline float easeLinear(float current_frame, float start_value, float end_frame, float change_value)
{
	return change_value*current_frame/end_frame + start_value;
}

inline float easeQuadraticIn(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame;
	return change_value*current_frame*current_frame + start_value;
}

inline float easeQuadraticOut(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame;
	return -change_value * current_frame*(current_frame-2) + start_value;
}

inline float easeQuadraticInOut(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame/2;
	if (current_frame < 1)
		return change_value/2*current_frame*current_frame + start_value;
	current_frame--;
	return -change_value/2 * (current_frame*(current_frame-2) - 1) + start_value;
}

inline float easeCubicIn(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame;
	return change_value*current_frame*current_frame*current_frame + start_value;
}

inline float easeCubicOut(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame;
	current_frame--;
	return change_value*(current_frame*current_frame*current_frame + 1) + start_value;
}

inline float easeCubicInOut(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame/2;
	if (current_frame < 1)
		return change_value/2*current_frame*current_frame*current_frame + start_value;
	current_frame -= 2;
	return change_value/2*(current_frame*current_frame*current_frame + 2) + start_value;
}

inline float easeQuarticIn(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame;
	return change_value*current_frame*current_frame*current_frame*current_frame + start_value;
}

inline float easeQuarticOut(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame;
	current_frame--;
	return -change_value * (current_frame*current_frame*current_frame*current_frame - 1) + start_value;
}

inline float easeQuarticInOut(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame/2;
	if (current_frame < 1)
		return change_value/2*current_frame*current_frame*current_frame*current_frame + start_value;
	current_frame -= 2;
	return -change_value/2 * (current_frame*current_frame*current_frame*current_frame - 2) + start_value;
}

inline float easeQuinticIn(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame;
	return change_value*current_frame*current_frame*current_frame*current_frame*current_frame + start_value;
}

inline float easeQuinticOut(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame;
	current_frame--;
	return change_value*(current_frame*current_frame*current_frame*current_frame*current_frame + 1) + start_value;
}

inline float easeQuinticInOut(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame/2;
	if (current_frame < 1)
		return change_value/2*current_frame*current_frame*current_frame*current_frame*current_frame + start_value;
	current_frame -= 2;
	return change_value/2 * (current_frame*current_frame*current_frame*current_frame*current_frame + 2) + start_value;
}


inline float easeSinIn(float current_frame, float start_value, float end_frame, float change_value)
{
	return   -change_value * cosf(current_frame/end_frame * (Pi/2)) + change_value + start_value;
}

inline float easeSinOut(float current_frame, float start_value, float end_frame, float change_value)
{
	return   change_value * sinf(current_frame/end_frame * (Pi/2)) + start_value;
}

inline float easeSinInOut(float current_frame, float start_value, float end_frame, float change_value)
{
	return -change_value/2 * (cosf(Pi*current_frame/end_frame) - 1) + start_value;
}

inline float easeExponentialIn(float current_frame, float start_value, float end_frame, float change_value)
{
	return change_value * powf( 2, 10 * (current_frame/end_frame - 1) ) + start_value;
}

inline float easeExponentialOut(float current_frame, float start_value, float end_frame, float change_value)
{
	return change_value * ( -powf( 2, -10 * current_frame/end_frame ) + 1 ) + start_value;
}

inline float easeExponentialInOut(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame/2;
	if (current_frame < 1)
		return change_value/2 * powf( 2, 10 * (current_frame - 1) ) + start_value;
	current_frame --;
	return change_value/2 * ( -powf( 2, -10 * current_frame) + 2 ) + start_value;
}

inline float easeCircularIn(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame;
	return -change_value * (sqrtf(1 - current_frame*current_frame) - 1) + start_value;
}

inline float easeCircularOut(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame;
	current_frame--;
	return change_value * sqrtf(1 - current_frame*current_frame) + start_value;
}

inline float easeCircularInOut(float current_frame, float start_value, float end_frame, float change_value)
{
	current_frame /= end_frame/2;
	if (current_frame < 1)
		return -change_value/2 * (sqrtf(1 - current_frame*current_frame) - 1) + start_value;
	current_frame -= 2;
	return change_value/2 * (sqrtf(1 - current_frame*current_frame) + 1) + start_value;
}


2. Example App

Test each codes.


<Easing Tester>



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

c++ string tokenizer  (0) 2015.01.09
cJSON parsing error using window utf-8 txt file, Remove UTF-8 BOM  (0) 2015.01.08
c++ Easing code  (0) 2014.10.16
c++ Builder 패턴  (0) 2014.04.16
c++ const  (0) 2014.04.15

c++ Builder 패턴

C++ 2014.04.16 10:54


1. 다수의 멤버변수

  보통 UI클래스나, 많은 정보를 가진 데이터 클래스(java의 bean객체 같은)의 경우, 많은 멤버 변수를 가진다. 이런 멤버 변수들을 생성자 파라미터로 초기화하면, 코드가 많이 복잡해 보일 수 있다. 예를 들어, 아래 클래스 처럼 new를 통해 파라미터로 값을 초기화하는 경우, 가독성이 많이 떨어진다(각각의 파라미터가 어떤 의미인지 알기 어렵다). 이런 문제를 해결하기 위해 get, set함수를 만들고 사용하기도 하는데 별로 만족 스럽지 못하다.


class Node
{
protected:
	vec2						m_position;
	vec2						m_draw_position;
	float						m_width;
	float						m_height;
	AlignType					m_child_align_type;
	Margin						m_margin;
	Padding						m_padding;
	Color						m_bg_color;
	AlignType					m_resolution_type;
	bool						m_is_draw_margin_padding;
	float						m_scale;

	int							m_ui_key;
	//------------------------------------------------------------------//
	//.... 기타  생성자 및 get, set함수들
}

main()
{
	//인자가 많아지면서, 보기 안 좋아짐. 각 파라미터가 무엇을 의미하는지 알 수 없음
	new Node(10, 0, 10, ...)

	//가독성은 좋지만, 뭔가 만족스럽지 못함
	Node* node = new Node();
	node->setWidth(10);
	node->setHeight(10);
	node->setPosition(10);
	node->setScale(10);
	....
}


2. Builder 클래스

  이런 문제를 해결하기 위한 방법으로, Builder클래스를 따로 만드는 것이다. 아래 예를 보면, 어디선가 많이 본적이 있는 객체 생성방법일 것이다(안드로이드에서 Notification이나,  AlertDialog 등, 많은 클래스에서 사용). 


class ImageView : public Node
{
public:
	class Builder
	{
		friend class ImageView;
	private:
		// 선택적으로 초기화 해도 되는 멤버
		vec2						m_position;			//logical position
		vec2						m_draw_position; 	//real position of screen
		float						m_width;
		float						m_height;
		AlignType					m_child_align_type;
		Margin						m_margin;
		Padding						m_padding;
		Color						m_bg_color;
		AlignType					m_resolution_type;	//vbox and hbox children don't need this member
		bool						m_is_draw_margin_padding;
		float						m_scale;
		//반드시 초기화 돼야 하는 멤버
		int							m_ui_key;
	public:
		Builder(shared_ptr& parent, int ui_key)
		:m_width(0), m_height(0), m_scale(GLManager::getInstance()->jd_scale), m_child_align_type(NONE),
		  m_position(0, 0), m_bg_color(1.0f, 0.452f, 0.834f, 1.0f), m_parent(parent), m_ui_key(ui_key),
		  m_resolution_type(NONE), m_is_draw_margin_padding(true)
		{}
		ImageView* build()
		{
			return new ImageView(*this);
		}

		Builder& position(vec2 value)					{ m_position = value;					return (*this);}
		Builder& drawPosition(vec2 value)				{ m_draw_position = value;				return (*this);}
		Builder& width(float value)						{ m_width = value;						return (*this);}
		Builder& height(float value)					{ m_height = value;						return (*this);}
		Builder& childAlignType(AlignType value)		{ m_child_align_type = value;			return (*this);}
		Builder& margin(Margin value)					{ m_margin = value;						return (*this);}
		Builder& padding(Padding value)					{ m_padding = value;					return (*this);}
		Builder& bgColor(Color value)					{ m_bg_color = value;					return (*this);}
		Builder& resolutionType(AlignType value)		{ m_resolution_type = value;			return (*this);}
		Builder& isDrawMarginPadding(bool value)		{ m_is_draw_margin_padding = value;		return (*this);}
		Builder& scale(float value)						{ m_scale = value;						return (*this);}
	};

public:
	ImageView(Builder& build)
	{
		m_position = build.m_position;
		m_draw_position = build.m_draw_position;
		m_width = build.m_width;
		m_height = build.m_height;
		m_child_align_type = build.m_child_align_type;
		m_margin = build.m_margin;
		m_padding = build.m_padding;
		m_bg_color = build.m_bg_color;
		m_resolution_type = build.m_resolution_type;
		m_is_draw_margin_padding = build.m_is_draw_margin_padding;
		m_scale = build.m_scale;
		m_parent = build.m_parent;
		m_ui_key = build.m_ui_key;
	}
};

//사용
main()
{
	ImageView* view = ImageView::Builder(m_root_anchor_pane, getUIKey())
							.width(100)
							.height(100)
							.position(image_view_pos)
							.resolutionType(CENTER_MIDDLE)
							.build();
}


  - 장점 : 코드 가독성이 좋다(초기화하는 값이 어떤 것을 의미하는지 알기 쉽다).

  - 단점 : 객체 생성 비용이 2배 정도 든다. 때문에 매 프레임마다 자주 생성과 소멸을 반복하는 클래스에서는 사용하지 않는 것이 좋다.



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

c++ string tokenizer  (0) 2015.01.09
cJSON parsing error using window utf-8 txt file, Remove UTF-8 BOM  (0) 2015.01.08
c++ Easing code  (0) 2014.10.16
c++ Builder 패턴  (0) 2014.04.16
c++ const  (0) 2014.04.15

c++ const

C++ 2014.04.15 13:41


1. 변수 const : 변수 값을 변경하지 못하게 한다.

const int n = 5;
n = 10 // 에러

1-2 const int& n2 = n; : n2가 참조하는 곳의 값을 바꿀 수 없다.
int n = 5;
const int& n2 = n;
n2 = 10; //에러
n = 10 ; //가능. 


2. 포인터 변수 const : 포인터가 가르키는 곳의 값을 변경하지 못하게 한다.
int n = 5; 
const int* ap = &n; (int const* ap도 똑같다.)
*ap = 10; //에러

int n2 = 10;
ap = &n2; //가능함. 포인터 변경은 가능

int * ap2 = ap; //에러. 포인터가 가르키는 곳을 다른 포인터가 값을 변경할 수도 있기 때문에, 허용하지 않는다.
const int *ap2 = ap; //가능함

2-1. int* const ap = &n;
  이 경우는 포인터가 가르키는 곳의 값은 변경가능하나, 포인터에 저장된 주소는 변경할 수 없다.
*ap = 10; //가능함
ap = &n2; //에러

3. 클래서 멤버 함수 const : 해당 객체의 멤버 필드들의 값을 함수 내에서 변경하지 못한다.
(물론 필드에 mutable 키워드를 사용하면 변경 가능하다.)
class A{
int n = 5;
void abc() const{
n = 10//에러
}
}

4. const 객체는 const멤버 함수가 아닌 것을 호출 할 수 없다.
class B{
void toString(){
cout<< "call B to string" << endl;
}
}
int main(){
const B b;
b.toString; //에러
}


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

c++ string tokenizer  (0) 2015.01.09
cJSON parsing error using window utf-8 txt file, Remove UTF-8 BOM  (0) 2015.01.08
c++ Easing code  (0) 2014.10.16
c++ Builder 패턴  (0) 2014.04.16
c++ const  (0) 2014.04.15