천객만래 [千客萬來] (It has an interminable succession of visitors)

[개발/PHP] web php unicode 문자열 urldecode

문자열 : %uXXXX


<?php

function decode_unicode_url($str)
{
  $res = '';

  $i = 0;
  $max = strlen($str) - 6;
  while ($i <= $max)
  {
    $character = $str[$i];
    if ($character == '%' && $str[$i + 1] == 'u')
    {
      $value = hexdec(substr($str, $i + 2, 4));
      $i += 6;

      if ($value < 0x0080) // 1 byte: 0xxxxxxx
        $character = chr($value);
      else if ($value < 0x0800) // 2 bytes: 110xxxxx 10xxxxxx
        $character =
            chr((($value & 0x07c0) >> 6) | 0xc0)
          . chr(($value & 0x3f) | 0x80);
      else // 3 bytes: 1110xxxx 10xxxxxx 10xxxxxx
        $character =
            chr((($value & 0xf000) >> 12) | 0xe0)
          . chr((($value & 0x0fc0) >> 6) | 0x80)
          . chr(($value & 0x3f) | 0x80);
    }
    else
      $i++;

    $res .= $character;
  }

  return $res . substr($str, $i);
}
?>

Simple test with japanese characters,
combined with urldecode:

<?php

$str = decode_unicode_url('%u65E5%u672C%u8A9E');
print(mb_convert_encoding(urldecode($str), "sjis", "euc-jp, utf-8, sjis") . '<br/>');
?>

Posted by SB패밀리
[개발/delphi] string to char array 문자열 복사

Visual C++ 뿐만 아니라 델파이도...
배열 문자열에 string 문자열을 복사해야할 경우가 생긴다.

StrLCopy () 함수를 사용하여 해결해 보자.

var
  ch: array[0..10] of Char;
  c: Char;
  x: Integer;
  st: string;
begin
  st := 'Testing';
  StrLCopy(PChar(@ch[0]), PChar(st), High(ch)); // or StrPLCopy(ch, st, High(ch));
  x := 100;
  for c in ch do
  begin
    Canvas.TextOut(x, 100, c);
    Inc(c, Canvas.TextWidth(c) + 3);
  end;
end;

 
Posted by SB패밀리

[개발/MFC] 스트링 형변환

 

문자관련 함수

MBCS(multi-byte character set) : ASCII 코드 문자열을 쓰는 함수

WCS(wide character string) : 유니코드 문자열을 쓰는 함수

 

함수 제일 뒤에 ASCII를 나타내는 A Wide Character를 나타내는 W를 붙여서 구분함.

)  GetCurrentDirectoryA ...

예외) cout, wcout

LPCTSTR(Long Pointer Constant TCHAR String)

여기서 TCHAR 라는 것은 typedef  유니코드가 설정되어 있으면 2바이트로(wchar_t) 아니면 기존 char 방식인 1바이트로(char) 한다는 것을 의미.

LPSTR : 8비트 윈도우 캐릭터 스트링(string) 포인터 문자.

LPCSTR : LPSTR 와 같고 단지 상수형(Constant )이라는 포인터문자.

참조http://cafe.naver.com/whatvoip.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=225

 

--> MFC CString TCHAR 형이다.

 

ATL 형변환 매크로

종류는 [소스 타입]2[새로운 타입] [소스 타입]2C[새로운 타입] 이 있다.

여기서 2C C const(읽기전용)이라는 뜻이다.

 

ATL 3.0 String Conversion Macros

 

 

여기서 A, W, T, OLE, BSTR이 있는데 그 의미는 다음과 같다.

A : MBCS 스트링, char* (A ANSI를 의미) -> LPSTR

W : Unicode 스트링, wchar_t* (W wide를 의미) -> LPWSTR

T : TCHAR 스트링, TCHAR* -> LPTSTR

OLE : OLECHAR 스트링, OLECHAR* (사실, W와 같은 의미) -> LPOLESTR

BSTR : BSTR

이를 통해 몇가지 매크로를 분석해 보면

 

A2BSTR

OLE2A

T2A

W2A

A2COLE

OLE2BSTR

T2BSTR

W2BSTR

A2CT

OLE2CA

T2CA

W2CA

A2CW

OLE2CT

T2COLE

W2COLE

A2OLE

OLE2CW

T2CW

W2CT

A2T

OLE2T

T2OLE

W2OLE

A2W

OLE2W

T2W

W2T

 

*사용법:

#include <atlconv.h>

void func( LPSTR lpsz )

{

   USES_CONVERSION; //형변환 메크로를 사용하기 위해서.

   ...

   LPWSTR x = A2W(lpsz)

   // Do something with x

   ...

}

 

*사용시 주의점:

이 매크로는 메모리를 스택에 잡음:

1) 과도한 순환문 속에서는 사용하면 안됨.

   - 매크로가 불릴 때마다 스택의 메모리를 잡아먹습니다.

   - 그 메모리는 함수가 끝날 때까지 해제되지 않습니다.

2) 매크로의 결과를 리턴하면 안됨.

   - 결과로 나오는 포인터는 함수가 끝날 때까지만 유효합니다.

참조 :

http://msdn.microsoft.com/en-us/library/87zae4a3(VS.80).aspx

http://jof4002.net/?Unicode

http://eroom.korea.com/post/board.aspx?bid=kmh_19505&mode=read&view=board&pid=189103&page=1

 

LPWSTR to CString

(CString) 으로 캐스팅하면 끝

 

CString to LPWSTR

CString strString = "abcd";

BSTR bstrString = strString.AllocSysString();

LPWSTR pwstr = (LPWSTR)bstrString;

SysFreeString(bstrString);

CString to LPTSTR

CString str = _T("new text");

  LVITEM item = {0};

 

  item.mask = LVIF_TEXT;

  item.iItem = 1;

  item.pszText = (LPTSTR)(LPCTSTR) str; // 잘못된 사용!

  // 올바른 사용.

  /*1)*/ item.pszText = str.GetBuffer();

  // 또는

  /*2)*/ _tcscpy_s(item.pszText, MAX_PATH, str.GetBuffer(str.GetLength()));

  ListView_SetItem ( &item );

  str.ReleaseBuffer();

 

참조http://eroom.korea.com/post/board.aspx?bid=kmh_19505&mode=read&view=board&pid=189103&page=1

 

CString to DWORD

CString str=_T("abcd");

DWORD dw = (DWORD)_ttoi((LPCTSTR)str);

출처 : http://hogwarts.tistory.com/172

 

 

매크로

인자

결과

A2CW

(LPCSTR)

(LPCWSTR)

A2W

(LPCSTR)

(LPWSTR)

W2CA

(LPCWSTR)

(LPCSTR)

W2A

(LPCWSTR)

(LPSTR)

T2COLE

(LPCTSTR)

(LPCOLESTR)

 

Posted by SB패밀리
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char *replaceAll(char *s, const char *olds, const char *news);


void main(void){
  char s[] = "봉숭아 학당! 봉숭아 학당! 봉숭아 학당! 봉숭아 학당!";
  char *s2;

  printf("원본: %s\n", s);

  s2 = replaceAll(s, "봉숭아", "맹구");

  // 에러가 있으면 NULL 을 리턴. 에러가 없으면 결과 출력
  (s2 != NULL) ? printf("치환: %s\n", s2) : fputs("Replace String Error...\n", stderr);
}




char *replaceAll(char *s, const char *olds, const char *news) {
  char *result, *sr;
  size_t i, count = 0;
  size_t oldlen = strlen(olds); if (oldlen < 1) return s;
  size_t newlen = strlen(news);


  if (newlen != oldlen) {
    for (i = 0; s[i] != '\0';) {
      if (memcmp(&s[i], olds, oldlen) == 0) count++, i += oldlen;
      else i++;
    }
  } else i = strlen(s);


  result = (char *) malloc(i + 1 + count * (newlen - oldlen));
  if (result == NULL) return NULL;


  sr = result;
  while (*s) {
    if (memcmp(s, olds, oldlen) == 0) {
      memcpy(sr, news, newlen);
      sr += newlen;
      s  += oldlen;
    } else *sr++ = *s++;
  }
  *sr = '\0';

  return result;
}


출처:  
Posted by SB패밀리
COM/ATL/STL - BSTR과 VARIANT, string, CComBSTR

COM 관련 코드를 작성하려고 보면 여기서만 쓰이는 생소한 데이터 형들이 등장하는데, 그중 문자열관련해서 다음과 같은 것을
볼 수 있다.


BSTR
Pascal-Style(길이값 내장)과 C-Style(널종료문자)을 섞어 놓은 형식으로 기본 구조는 다음과 같다.
-    4Byte(길이정수) + 문자값(2Byte) + 종료문자( 0 2개 )
즉, 최초에 DWORD의 정수데이터가 붙고 그 뒤로 Unicode식의 2Byte Encoding 문자열이 붙는형식이다.
그러나 이 앞쪽의 정수 부분은 C++ 코드 작성시에는 없다고 생각해야 한다.
왜냐하면, typedef OLECHAR* BSTR; 로 선언 되어 있기 때문.
COM을 통해 데이터가 전송될 때 알아서 마샬링 되는 것 같다.
아무튼 실제로 BSTR은 WCHAR과 다름에도 불구하고 내부적으로 같은 형식으로 인식되기 때문에 주의를 해야한다.
함수에 인자로 넘길경우 컴파일 오류가 안지 않더라도 내부적으로 오류가 발생하기 쉽다.

게다가 BSTR 은 COM 라이브러리를 통해 마샬링 되어야 하기 때문에 메모리 관리를 다른 곳에서 해야한다.
즉, 사용할 때 메모리 할당과 해제를 명시적으로 API를 통해서 해야한다.
SysAllocString() : 메모리 할당시 사용
SysFreeString() : 메모리 해제시 사용
BSTR bstr = NULL;

bstr = SysAllocString ( L"Hi Bob!" );

if ( NULL == bstr )
  // out of memory error

// Use bstr here...

SysFreeString ( bstr );

이렇게 사용한다.


_bstr_t
BSTR데이터형을 사용하는게 귀찮은 사람들을 위한 BSTR Wrapper 클래스다.
BSTR대신 함수에 넘겨줄수는 없다 ? 가능하지만 상당히 제약적이다.
직접 내부 BSTR에 접근이 안돼기 때문에 함수에 BSTR대신 넘겨주기 위해서는 ATL에서 지원하는 CComBSTR클래스를
사용하면 된다.
다음과 같이 생성 및 문자열 encoding 변환을 할 수 있다.
// Constructing
_bstr_t bs1 = "char string"; & // construct from a LPCSTR
_bstr_t bs2 = L"wide char string"; // construct from a LPCWSTR
//내부적으로 2Byte Unicode 형식이지만, char / wchar_t 양쪽에서 생성 할 수 있다.

_bstr_t bs3 = bs1;  // copy from another _bstr_t
_variant_t v = "Bob";
_bstr_t bs4 = v;  // construct from a _variant_t that has a string

// Extracting data
LPCSTR psz1 = bs1;  // automatically converts to MBCS string
LPCSTR psz2 = (LPCSTR) bs1;  // cast OK, same as previous line
LPCWSTR pwsz1 = bs1;  // returns the internal Unicode string
LPCWSTR pwsz2 = (LPCWSTR) bs1; // cast OK, same as previous line 변환된다!!
BSTR  bstr = bs1.copy()// copies bs1, returns it as a BSTR

// ...
SysFreeString ( bstr ); // 수동적으로 메모리를 해제해줘야 한다.




_variant_t
COM에서 사용되는 VARIANT의 wrapper 클래스다.
당연히 BSTR과 _bstr_t의 관계처럼 좀더 사용하기 용이하다.
기본적으로 VARIANT는 문자열외에 다양한 데이터를 저장하기 위한 구조체지만, 문자열을 저장할 경우 BSTR형식으로
저장이 된다.
_bstr_t와는 다르게 _variant_t는 VARIANT를 상속받은 클래스로 모든 함수에 VARIANT 대신 넘겨주는 것이 가능하다.
내부의 VARIANT는 감춰져있다.
// Constructing
_variant_t v1 = "char string"// construct from a LPCSTR
_variant_t v2 = L"wide char string"; // construct from a LPCWSTR
_bstr_t bs1 = "Bob";
_variant_t v3 = bs1;  // copy from a _bstr_t object

// Extracting data
_bstr_t bs2 = v1;  // extract BSTR from the VARIANT
_bstr_t bs3 = (_bstr_t) v1; // cast OK, same as previous line
위와 같이 _variant_t와 _bstr_t 사이에 전환이 용이 하다.



basic_string::string / basic_string::wstring
STL의 문자열 클래스 basic_string에는 MBSC/Unicode용으로 각각 string/ wstring이 존재 한다.
string은 char / wstring은 wchar_t를 저장하는데, TCHAR은 존재하지않는다.
TCHAR과 STL을 함께 사용하려면 간단히 다음처럼 직접 만들어주면된다.
// Specializations
typedef basic_string<TCHAR> tstring; // string of TCHARs 새로 정의 해준다.

// Constructing 이렇게 각각 생성할 수 있다.
string str = "char string"// construct from a LPCSTR
wstring wstr = L"wide char string"; // construct from a LPCWSTR
tstring tstr = _T("TCHAR string"); // construct from a LPCTSTR

// Extracting data
// 값을 사용할 때에는 .c_str()을 통해 해당하는 원 데이터형으로 반환된다.
LPCSTR psz = str.c_str()// read-only pointer to str's buffer
LPCWSTR pwsz = wstr.c_str(); // read-only pointer to wstr's buffer
LPCTSTR ptsz = tstr.c_str(); // read-only pointer to tstr's buffer
_bstr_t에 바로 할당하기 위해서는
_bstr_t bs1 = wstr.c_str(); 와 같은 식으로 내부 데이터 값을 받아오면 된다.



CComBSTR
ATL의 BSTR wrapper 클래스로 _bstr_t보다 좀더 유용한 기능들이 있다.
우선 COM함수에 BSTR대신 넘겨줄 수 있고, BSTR 메모리 관리를 자동으로 해준다.
내부에 MBCS 변환 기능은 없다.
문자열 변환에는 ATL 변환 Macro를 사용하면 된다. <- 매우 편리하다
// Constructing
CComBSTR bs1 = "char string"// construct from a LPCSTR
CComBSTR bs2 = L"wide char string"; // construct from a LPCWSTR
CComBSTR bs3 = bs1;  // copy from another CComBSTR
CComBSTR bs4;

bs4.LoadString ( IDS_SOME_STR ); // load string from string table

// Extracting data
BSTR bstr1 = bs1;  // returns internal BSTR, but don't modify it!
BSTR bstr2 = (BSTR) bs1; // cast ok, same as previous line
BSTR bstr3 = bs1.Copy(); // copies bs1, returns it as a BSTR
BSTR bstr4;

// CComBSTR의 메모리 관리를 꺼버릴 수 있다.
bstr4 = bs1.Detach(); // bs1 no longer manages its BSTR, 메모리 관리는 수동으로 해야한다.

// ...
SysFreeString ( bstr3 );
SysFreeString ( bstr4 );


추가로, 연산자&는 내부의 BSTR*를 리턴하도록 오버로딩 되어있기 때문에 사용상 고려할점이 존재한다.
STL의 list같은 컬렉션에서 CComBSTR을 사용하기 위해서는 &연산자 오버로딩으로 일반 데이터타입과는 다르게,
CAdapt 를 사용해야 한다. 즉 다음과 같다.
std::list< CAdapt<CComBSTR> > bstr_list;



CComVariant
ATL의 VARIANT wrapper 클래스다. _variant_t와는 다르게 내부의 VARIANT가 감춰져 있지 않아서 직접 접근이 가능.
게다가 CComBSTR과 간단히 형 변환되지는 않기 때문에 값을 넣기 위해서는 검사를 해야한다.
CComVariant v4 = ... // Init v4 from somewhere
CComBSTR bs3;
// 검사하고 변환이 가능하면 넣는다.
if ( SUCCEEDED( v4.ChangeType ( VT_BSTR ) ))
bs3 = v4.bstrVal;



ATL Conversion Macros ? MBCS / Unicode / BSTR 간의 Encoding 변환
Macro 함수의 이름은 다음과 같은 구조로 돼어있다.
[원본 타입]2[새 타입] / [원본타입]2C[새 타입]
2는 그냥 변환 / 2C는 constant pointer를 말하는 C이다.

A : MBCS 문자열 char*
W : Unicode 문자열 wchar_t*
T : TCHAR 문자열 TCHAR*
OLE : OLECHAR 문자열 OLECHAR*
BSTR : BSTR

예를 들어, W2A() 매크로는 Unicode문자열을 MBCS문자열로 변환한다.
매크로를 사용하기 위해서는 atlconv.h 헤더를 포함해야 하는데, 해당 헤더파일만 포함하면 굳이 ATL프로젝트가 아니라도
사용이 가능하다.

사용시에는 우선 USES_CONVERSION 이라는 매크로를 사용전에 호출해주어 변환에 필요한 기본 변수들을 정의 한뒤,
실제 변환 매크로를 사용하면 된다.
// Functions taking various strings:
void Foo ( LPCWSTR wstr );
void Bar ( BSTR bstr );
// Functions returning strings:
void Baz ( BSTR* pbstr );

#include &lt;atlconv.h&gt;

main()
{
using std::string;
USES_CONVERSION;  // declare locals used by the ATL macros

// Example 1: Send an MBCS string to Foo()
LPCSTR psz1 = "Bob";
string str1 = "Bob";

Foo ( A2CW(psz1) );
Foo ( A2CW(str1.c_str()) );

// Example 2: Send a MBCS and Unicode string to Bar()
LPCSTR psz2 = "Bob";
LPCWSTR wsz = L"Bob";
BSTR bs1;
CComBSTR bs2;

bs1 = A2BSTR(psz2)// create a BSTR
bs2.Attach ( W2BSTR(wsz) ); // ditto, assign to a CComBSTR

Bar ( bs1 );
Bar ( bs2 );

SysFreeString ( bs1 )// free bs1 memory
// No need to free bs2 since CComBSTR will do it for us.

// Example 3: Convert the BSTR returned by Baz()
BSTR bs3 = NULL;
string str2;

Baz ( &bs3 ); // Baz() fills in bs3

str2 = W2CA(bs3); // convert to an MBCS string
SysFreeString ( bs3 ); // free bs3 memory
}
Posted by SB패밀리