<

STL에 포함되어 있는 다양한 컨테이너(Vector, Map, List etc...)들은 Iterator를 기본 제공한다.


Iterator를 쉽게 설명하자면 컨테이너의 각각의 Index를 탐색 or 순환 할 수 있는 일종의 포인터 개념이다.


STL의 컨테이너에 Iterator를 붙여서 사용하면 일반 배열 탐색할때 인덱스를 반복문으로 훓으면서 쓰던것처럼 할 수 있다.


근데 문제는 이 Iterator를 쓰기 좀 번거롭다.


for (std::map<std::string, bool>::iterator iter = m_mapItemFlag.begin(); iter != m_mapItemFlag.end(); iter++)
{
	(*iter).second = bCheckFlag;
}

위의 코드처럼 Map이든 Vector든 내부의 각 원소를 전부 탐색해서 원소를 초기화 하거나 조건식을 추가하여 조건에 맞는 원소들의 값을 이용하는 것으로 많이 사용한다.



기존의 배열을 반복문과 함께 이용하는 것과 매우 흡사하다.



위처럼 Iterator를 컨테이너의 처음부터 끝까지 탐색할 경우 아래와 같은 방법으로 하면 쉽게 해결된다.


for (auto item : m_mapItemFlag)
{
	item.second = bCheckFlag;
}

C#보다 C++에 익숙한 사람은 auto 키워드에 낯설수도 있다. 나도 그랬다.


C#의 var 키워드 처럼 뒤에 대입받는 자료형에 따라 자동으로 해당 변수의 자료형을 선택해주는 아주 편한 키워드이다. 


하지만 남용하면 가독성이 떨어지므로 위와 같이 Range-based. 범위기반 반복문에서나 사용하자.



요약하자면 STL 컨테이너든, 일반 배열이든, 전체를 순차적으로 탐색할 때에는 위와 같은 범위기반 반복문을 사용하면 훨씬 편하다는 거다.


복잡하게 Iterator 생성해서 형식 맞춰주고 할 필요가 없다. 






윈도우 API에서 제공하는 RECT는 구조체이다. 멤버로는 left, top, right, bottom 밖에 없다.

단순 사각형을 그리거나 위치 계산을 위한 구조체로 이용해 왔다.


RECT구조체와 비슷하게 MFC에서 제공하는 CRect 클래스가 있다.


RECT와 CRect 둘다 마찬가지로 사각형 영역의 위치를 처리하기 위한 타입이다.


CRect에 좀 더 다양하고 편리한 함수가 제공된다. 


예를 들어 위 두 사각형이 겹치는 영역을 구할때 사용하면 편리한 함수가 바로 IntersectRect이다.

CRect overlapRect = CRect(0, 0, 0, 0);
overlapRect.IntersectRect(rect1, rect2);
if (overlapRect.IsRectEmpty() || overlapRect.IsRectNull())
	//Do not overlap
 

중첩된 영역을 지정할 overlapRect를 선언후 IntersectRect 함수를 통해 rect1과 rect2를 피라메터로 넘겨주면


겹치는 영역이 overlapRect에 저장된다.


이후 IsRectEmpty() 나 .IsRectNull()로 겹치지 않았을 때 처리를 해주고 겹쳐진 영역을 이용하면 된다.




심심해서 로또 번호 생성 코드를 짜봤다.


일단 로또번호는 1부터 45까지의 수에서 중복없이 6개로 이뤄진다.


그래서 rand함수로 번호를 뽑은다음, 중복값인지 체크하는 루틴도 있어야 한다.


배열 이용하는 방법이 가장 쉽고 간편하지만, 여기서는 STL 리스트를 이용해 본다.


#define LOTTONUM 6

	std::list listNum;
	srand((unsigned)time(NULL));
	int nNum = 0;
	listNum.clear();
	for (int i = 0; i < LOTTONUM; i++)
	{
		nNum = rand() % 45 + 1;

		if (std::find(listNum.begin(), listNum.end(), nNum) == listNum.end())
			listNum.push_back(nNum);
	}


프로그램을 짜다 보면 하드코딩이 아닌 사용자가 입력한 텍스트로 수식을 계산해야 하는 경우가 종종 있다.


계산식이 하드코딩(hard coding)으로 짜면 매우 편하지만 계산식이 하나로 정해져있지 않거나 상황에 따라서 변경되는 경우에는 한계가 있다.


사용자가 정의한 수식은 텍스트 형태로 저장되므로 이를 파싱(parsing)하는 작업은 그리 어려운 작업은 아니다. 물론 4칙연산의 경우엔..



사용자가 입력한 수식에 x^2꼴이나 제곱근(√), 로그함수, 지수함수 등이 들어있으면 모두 대응하기가 어렵다.


따라서 개발 시간 단축과 스트레스 감소를 위해 관련 라이브러리를 사용하기로 한다.


관련된 라이브러리는 구글링하면 다양하게 나온다.


내가 선택한 라이브러리는 바로 muparser이다. 무엇보다 MIT라이센스로 사용에 별도의 제한이 없기 때문이다.


사용법은 여타 외부 라이브러리와 같다.


VS 프로젝트에 추가하고, include로 땡겨서 사용하면 된다.


예제에 나온 코드도 매우 심플하다.


#include 
#include "muParser.h"

// Function callback
double MySqr(double a_fVal) 
{ 
  return a_fVal*a_fVal; 
}

// main program
int main(int argc, char* argv[])
{
  using namespace mu;

  try
  {
    double fVal = 1;
    Parser p;
    p.DefineVar("a", &fVal); 
    p.DefineFun("MySqr", MySqr); 
    p.SetExpr("MySqr(a)*_pi+min(10,a)");

    for (std::size_t a=0; a<100; ++a)
    {
      fVal = a;  // Change value of variable a
      std::cout << p.Eval() << std::endl;
    }
  }
  catch (Parser::exception_type &e)
  {
    std::cout << e.GetMsg() << std::endl;
  }
  return 0;
}

DefineVar : 수식에 존재하는 a라는 문자를 fVal 값으로 정의

DefineFun : 수식에 존재하는 MySqr이라는 문자를 위에 정의한 Mysqr함수로 정의

SetExpr : 텍스트 형태의 수식. 여기에 수식을 입력하면 된다.

Eval() : 수식 계산


예제코드 조금만 보면 금방 응용이 가능하다.


그리고 반드시 try ~ catch 구문을 추가하여 올바르지 않은 수식이 들어왔을 경우 예외처리를 해주자.

MFC의 트리메뉴 컨트롤의 아이템 선택 이벤트 후 해당 선택된 아이템의 인덱스를 리턴하는 메소드가 없다.


편법으로 아이템 이름으로 찾는 방법도 있지만 코드가 길어지고 추가/수정이 복잡해진다.


구글링 결과 index를 구하는 방법을 찾았다.


OnTvnSelchanged 이벤트 메소드에서 child 아이템을 루프 태우면서 현재 선택된 item인지 체크하면서 증가 시키는 것이다.


이생각을 왜 못했는지..


코드의 일부는 아래와 같다. 전체는 출처로 이동해서 확인하길 바란다.


 
    int index = 0;
    HTREEITEM hItem = m_treeCtrl.GetSelectedItem();
    HTREEITEM hChild = m_treeCtrl.GetChildItem(NULL);
    while (hChild)
    {
        if (hChild == hItem) break;
        hChild = m_treeCtrl.GetNextItem(hChild, TVGN_NEXT);
        ++index;
    }
출처 : C++/(MFC)트리 컨트롤 몇 번째 아이템인지 조회


isalpha()

 함수형태 

 isalpha(int c)

 파라미터

 c − 확인할 문자(ASCII)

 리턴

 0 != c가 알파벳, 0 = c는 알파벳이 아님




isdigit()

 함수형태 

 isdigit(int c)

 파라미터

 c − 확인할 문자(ASCII)

 리턴

 0 != c가 숫자, 0 = c는 숫자가 아님




	CString strTest = _T("ABCDEFG01234");
	if (isalpha(strTest[2]))
	{
		// true
		// ...
	}
	else
	{
		// false
		// ...
	}
	if (isdigit(strTest[7]))
	{
		// true
		// ...
	}
	else
	{
		// false
		// ...
	}


+ Recent posts