C++2010. 3. 22. 10:58

print(), sprintf(), fprintf(), 함수 속의 퍼센트(%) 기호들은 "Format Specifier"라고 하는데, 출력 형식을 지정하는 것이다. Format-specifier는 따옴표("")에 의해 둘러싸인 문자열 상수이다. Format-specifier의 내용 중에 %와 한 개의 문자로 이루어진 부분은 두 번째 이후의 인자들이 출력될 자리를 나타내고 그 나머지는 Format-specifier내에 적힌 내용을 한 문자도 변경하지 않고 그대로 출력한다.

Format-specifier 내에서 % 뒤에 따라오는 문자의 종류에 따라서 출력될 변수의 값을 표현하는 방식이 결정된다. 예를 들어, %d라고 표기하면 해당되는 인자는 정수로 출력되고, %c라고 표기하면 문자로 출력되는 식이다.(해당 변수의 갑을 1바이트 값으로 읽고 이를 ASCII값으로 해석한다.) 이에 대해 간단히 정리해 보자.


출처 : 몽키몽키님의 네이버 블로그

Posted by 쿵캉켕
C++2010. 3. 22. 10:55

프로그램을 하다보면 문자열 처리시 문자열에 포함된 특정 문자를 제거해야하는 경우가 종종있습니다.
예를들어, 어떤 명칭을 입력받으면서 공백없이 입력해달라고 했는데 사용자의 실수로 공백이 같이 입력되면
처리하는쪽에서 문자열에 공백이 있는지 여부를 체크하고 공백이 있다면 해당 공백을 제거해야합니다.
MFC를 사용하다보면 문자열 처리시에 CString 클래스를 많이 사용하는데, CString 클래스의 멤버함수중에
Remove 라는 함수가 있고 이 함수가 CString이 관리하는 문자열에서 특정 문자를 제거하는 기능입니다.
예를들면, 아래와 같습니다.
 
CString str = "Hello World!!";
str.Remove(' ');
AfxMessageBox(str);
 
이렇게 하면 결과가 아래와 같이 문자열에 공백이 제거된 상태로 메시지박스에 출력됩니다.
 
HelloWorld
 
하지만, 여기에 문제가 있습니다. 이 CString 클래스자체가 한글을 기준으로 제작된 클래스가 아니라서
한글이 포함된 문자열인 경우 Remove 함수를 사용하면 원하지 않는 결과가 발생합니다.
 
한글코드가 "한글여부(1bit) + 초성(5bit) + 중성(5bit) + 종성(5bit) = 총 2바이트(16비트)"로 구성되기
때문에 영문기준으로 1바이트씩 문자열을 비교하다보면 "디", "바"와 같이 종성이 없거나 종과 같이 종성이
존재하는 경우라도 한글문자가 공백다음에 놓이면 문자열값이 변형되는 문제가 발생합니다.
 
변경전        CString::Remove(' ')를 이용하여 변경한 후...
"다 다"    -->    "다도"
"다 바"    -->    "다뭐"
"다 종"    -->    "다좋"
 
결국 조금 불편하더라도 한글이 포함된 문자열에서 특정 문자를 제거하는 경우에는 한글을 고려해서
문자열 처리가 될수 있도록 아래와 같이 함수를 구성해서 사용하는것이 좋습니다.
 
void www_tipssoft_com_RemoveCharFromString(CString &parm_string, char parm_remove_char)
{
    int count = parm_string.GetLength(), index = 0;

    if(count > 0){
        // 문자열 제거에 사용할 버퍼를 생성한다. 이 버퍼는 기준 문자열보다 클 필요가 없다.
        char *p_data = new char[count + 1];
 
        for(int i = 0; i < count; i++){
            if(parm_string[i] & 0x80){
                // 한글인 경우는 2바이트로 구성되기 때문에 1바이트 정보인 parm_remove_char와 비교할
                // 필요가 없다. 따라서 그냥 2바이트 정보를 모두 복사해주면 된다.
                p_data[index++] = parm_string[i++];
                p_data[index++] = parm_string[i];
            } else {
                // 한글이 아닌 경우는 정보가 1바이트씩 구성되기 때문에 parm_remove_char에 지정된
                // 문자와 비교하여 다른 경우에만 복사한다.
                if(parm_remove_char != parm_string[i]) p_data[index++] = parm_string[i];
            }
        }
        // parm_remove_char를 뺀 나머지 문자가 복사된 문자열의 끝에 '\0'을 추가한다.
        p_data[index] = 0;
 
        // parm_remove_char가 제거된 문자열을 원본 문자열에 저장한다.
        parm_string = p_data;
 
        // 문자열 제거에 사용한 버퍼를 제거한다.
        delete[] p_data;
    }
}
 

사용방법 :
 
CString str = "이동 디스크";
 
www_tipssoft_com_RemoveCharFromString(str, ' ');
AfxMessageBox(str);
 
이렇게 하면 결과가 아래와 같이 문자열에 공백이 제거된 상태로 메시지박스에 출력됩니다.
( CString::Remove 함수를 사용하면 "이동도슬탤" 라고 출력됩니다. )
 
이동디스크

출처 : 팁스 소프트
http://www.tipssoft.com/bulletin/tb.php/FAQ/253

Posted by 쿵캉켕
C++2010. 3. 22. 10:51

#. 설명.
 - 다른 STL의 컨테이너 처럼 map은 많은 장점을 가진 유익한 컨테이너입니다. 빠른 Indexing을 위해서라면 STL의 컨테이너중 map을 가장 먼저 생각할 수 있겠습니다.
 - map은 Associative Container (연관컨테이너)에 속하는데 Associative Container란 키를 가지고 sort된 후에 적재되는 컨테이너로 검색속도를 빠르게 하기 위한 목적을 가진 컨테이너 입니다. map은 정렬 연관 컨테이너이며, key와 value의 쌍으로 이루어진 자료구조입니다.
 - 대부분 균형 이진 탐색 트리(balanced binary search tree)를 사용해 구현하며 추가/삭제에 O(log n)이 걸리며 검색에 있어서 탁월한 성능을 발휘합니다.

#. map의 특징에 대해서 간단히 살펴 보면 다음과 같습니다.

1. key와 value로 element를 관리할 수 있다.
2. key는 숫자 이외에도 문자열 순서를 가질 수 있는 (즉, 비교 연산자를 가지고 있는) 데이터 타입이면 모두 key가 될 수 있다.
3. key는 순서 (order)를 가지고 관리되기 때문에 검색이 빠르다.
4. key는 unique해야 한다.
5. aMapkey = value 와 같이 [] 연산자를 제공해준다.
6. Element가 추가/삭제 될 때 크기도 같이 확장 축소 된다.


#. 아래는 MSDN에 나와있는 샘플코드입니다. 참고하세요^^

Sample Code:

//////////////////////////////////////////////////////////////////////
//
// Compile options needed: None
//
// <filename> :  main.cpp
//
// Functions:
//
//      end
//      find
//      insert
//////////////////////////////////////////////////////////////////////

#pragma warning(disable:4786)

#include <iostream>
#include <string>
#include <map>

using namespace std;


typedef map<int, string, less<int> > INT2STRING;

void main()
{
// 1. Create a map of ints to strings
    INT2STRING theMap;
    INT2STRING::iterator theIterator;
    string theString = "";
    int index;

// Fill it with the digits 0 - 9, each mapped to its string counterpart
// Note: value_type is a pair for maps...
    theMap.insert(INT2STRING::value_type(0,"Zero"));
    theMap.insert(INT2STRING::value_type(1,"One"));
    theMap.insert(INT2STRING::value_type(2,"Two"));
    theMap.insert(INT2STRING::value_type(3,"Three"));
    theMap.insert(INT2STRING::value_type(4,"Four"));
    theMap.insert(INT2STRING::value_type(5,"Five"));
    theMap.insert(INT2STRING::value_type(6,"Six"));
    theMap.insert(INT2STRING::value_type(7,"Seven"));
    theMap.insert(INT2STRING::value_type(8,"Eight"));
    theMap.insert(INT2STRING::value_type(9,"Nine"));

// Read a Number from the user and print it back as words
    for( ; ; )
    {
        cout << "Enter \"q\" to quit, or enter a Number: ";
        cin >> theString;
        if(theString == "q")
            break;
        // extract each digit from the string, find its corresponding
        // entry in the map (the word equivalent) and print it
        for(index = 0; index < theString.length(); index++){
            theIterator = theMap.find(theString[index] - '0');
            if(theIterator != theMap.end() )    // is 0 - 9
                cout << (*theIterator).second << " ";
            else    // some character other than 0 - 9
                cout << "[err] ";
        }
        cout << endl;
    }
}


#. 위 소스의 출력화면 입니다.

Program Output is:

Enter "q" to quit, or enter a Number: 22
Two Two
Enter "q" to quit, or enter a Number: 33
Three Three
Enter "q" to quit, or enter a Number: 456
Four Five Six
Enter "q" to quit, or enter a Number: q

Posted by 쿵캉켕
C++2010. 3. 22. 10:45

다이얼로그 박스가 띄워질 때 원하는 컨트롤에 커서가 깜빡이게 하고 싶은 경우 주로 사용합니다.

다이얼로그 리소스 편집 창에서 각 컨트롤들의 탭 순서를 변경하고 싶은 경우.
1. [Ctrl]+D를 누른다.
2. 각 컨트롤들의 탭 순서가 표시된다.
3. 첫번째 순서가 될 컨트롤부터 차례대로 마우스로 클릭한다.
4. 순서를 모두 변경했으면 다시한번 [Ctrl]+D를 누른다.

OnInitDialog()에서 컨트롤에 SetFocus를 주거나 PostMessage(WM_SETFOCUS)를 주는 방법도 있지만 이 방법이 가장 손쉬운 듯 합니다. 거의다 아시겠지만 뭐..약간의 팁이랄까요?^^;; 참고로 VS 6.0에서 활용할 수 있습니다.

VS2005에서는 다이얼로그 박스에서 해당 컨트롤의 속성창에서 TabIndex의 숫자를 변경하면 됩니다.^^

Posted by 쿵캉켕
C++2010. 3. 22. 10:41

#. 각 자료형 별 Bytes와 들어갈 수 있는 값의 최소.최대치 입니다. 다 외울 필요는 없지만, 알아 두시면 편리합니다.



단, int와 unsigned int의 경우 2bytes로 인식하는 경우는 다음과 같습니다.

2bytes
unsigned int 0 ~ 65535
int -32768 ~ +32767

Posted by 쿵캉켕
C++2010. 3. 22. 10:38

#. 코딩시 변수 타입별로 알아보기 쉽게 하기 위해 작성된 헝가리안 표기법...
왠만한 코드에는 적용되어 있으므로 알아두면 편리하고 숙달되면 작성하기에도 편리합니다.



Posted by 쿵캉켕