[출처 : http://drcarter.tistory.com/entry/python-dictionary-sorting]


dickeys = dic.keys()
dickeys.sort()
for i in dickeys:
      print i, dic[i]

그러면... value로 sorting 하는 방법은...
diclist = []  
for i in dic.keys():
      diclist.append( (i, dic[i]) )
diclist.sort( key = lambda(x,y):y )

for i in diclist:
      print i[0], i[1]   

음... 이 방법 이외에...
from operator import itemgetter

dict = {}
dict['a'] = 2
dict['b'] = 1
dict['c'] = 5

print sorted(dict.iteritems(), key=itemgetter(1), reverse=True)
[출처 : http://mwultong.blogspot.com/2007/06/c-1-get-bit-read-bit.html]


부호없는 16비트 정수 즉 "unsigned short"형의 숫자에서, 특정 비트가 1인지 0인지를 알아내는 방법입니다. 다음의 getAbit(숫자, 몇번째비트) 함수를 사용하면 0또는 1을 반환합니다. C에는 2진수 출력 기능이 없기에, ushortToBinary() 라는 함수도 만들었습니다.

n번째 비트, 1인지 0인지 여부 판단 함수 예제


소스 파일명: example.cpp
#include <stdio.h>

int getAbit(unsigned short x, int n);
char *ushortToBinary(unsigned short i);


int main(void) {

  unsigned short num = 24761;
  printf("%s\n", ushortToBinary(num)); // 2진수로 출력
  // 출력 결과: 0110000010111001


  // 0번 비트 (맨 우측 비트) 읽기
  printf("%d\n", getAbit(num, 0));
  // 1


  // 1번 비트 (맨 우측에서 2번째 비트) 읽기
  printf("%d\n", getAbit(num, 1));
  // 0



  // num을 1비트씩 읽어, 2진수로 출력하기
  printf("\n[ ");
  for (int i = 15; i >= 0; i--) {
    printf("%d", getAbit(num, i));
  }
  printf(" ]\n");
  // [ 0110000010111001 ]


  return 0;
}




// 지정한 정수에서, 몇번째 비트만 읽어서 반환하는 함수
int getAbit(unsigned short x, int n) { // getbit()
  return (x & (1 << n)) >> n;
}


// 16비트 정수를 2진수 문자열로 변환 함수
char *ushortToBinary(unsigned short i) {
  static char s[16 + 1] = { '0', };
  int count = 16;

  do { s[--count] = '0' + (char) (i & 1);
       i = i >> 1;
  } while (count);

  return s;
}

[출처 : http://mwultong.blogspot.com/2007/06/c-bit-on-off-set-bit-save-bit.html]


부호없는 16비트 정수 즉 "unsigned short"형 숫자에서 특정 비트를 켜고 끄는 방법입니다. 아래의 "setAbit(숫자, 몇번째비트, 1또는0)" 함수를 사용하면 됩니다. 특정 비트를 1또는 0으로 설정한 후, 그 결과를 다시 "unsigned short"으로 반환합니다. 따라서 이 함수로, 어떤 숫자를 비트 단위로 조작할 수 있습니다.

특정 비트 조작, 1 또는 0으로


소스 파일명: example.cpp
#include <stdio.h>

unsigned short setAbit(unsigned short x, int n, int b);
char *ushortToBinary(unsigned short i);


int main(void) {

  unsigned short num = 0;
  printf("%s\n", ushortToBinary(num));
  // 2진수 출력 결과: 0000000000000000


  // 0번 비트 (맨 우측 비트)를 1로 켜기
  printf("%s\n", ushortToBinary( setAbit(num, 0, 1) ));
  // 0000000000000001



  printf("\n\n");
  // 0000000000000000 에서, 차례로 1비트씩 켜기 (1로 ON)
  num = 0;
  for (int i = 15; i >= 0; i--) {
    unsigned short temp = setAbit(num, i, 1);
    printf("%s = %10u\n", ushortToBinary(temp), temp);
  }


  printf("\n\n");
  // 1111111111111111 에서, 차례로 1비트씩 끄기 (0으로 OFF)
  num = 0xFFFF;
  for (int i = 15; i >= 0; i--) {
    unsigned short temp = setAbit(num, i, 0);
    printf("%s = %10u\n", ushortToBinary(temp), temp);
  }


  return 0;
}




// 정수 x 의 n번째 비트를, b로 설정하는 함수
unsigned short setAbit(unsigned short x, int n, int b) { // setbit()

  if (b == 1)
    return (unsigned short) (
                             x | (1 << n)
                             );

  return (unsigned short) (
                           x & (~(1 << n))
                           );

}


// 16비트 정수를 2진수 문자열로 변환 함수
char *ushortToBinary(unsigned short i) {
  static char s[16 + 1] = { '0', };
  int count = 16;

  do { s[--count] = '0' + (char) (i & 1);
       i = i >> 1;
  } while (count);

  return s;
}



컴파일 및 실행 결과 화면:
D:\Z>cl example.cpp && example.exe
example.cpp
0000000000000000
0000000000000001


1000000000000000 =      32768
0100000000000000 =      16384
0010000000000000 =       8192
0001000000000000 =       4096
0000100000000000 =       2048
0000010000000000 =       1024
0000001000000000 =        512
0000000100000000 =        256
0000000010000000 =        128
0000000001000000 =         64
0000000000100000 =         32
0000000000010000 =         16
0000000000001000 =          8
0000000000000100 =          4
0000000000000010 =          2
0000000000000001 =          1


0111111111111111 =      32767
1011111111111111 =      49151
1101111111111111 =      57343
1110111111111111 =      61439
1111011111111111 =      63487
1111101111111111 =      64511
1111110111111111 =      65023
1111111011111111 =      65279
1111111101111111 =      65407
1111111110111111 =      65471
1111111111011111 =      65503
1111111111101111 =      65519
1111111111110111 =      65527
1111111111111011 =      65531
1111111111111101 =      65533
1111111111111110 =      65534
D:\Z>

[출처 : http://kldp.org/node/63623]

코딩은 해당업체에 룰을 따랐습니다. 헤더만을 올려놓습니다. 소스는 쫌...엉망입니다...앞서 이야기 했던 네트워크처리를 위한 부분입니다.

#ifdef __cplusplus
extern "C" {
#endif

/******************************************************************************
 DISPATCHER			: Dispatcher 식별자
 size_t size		: 현재 등록되어 있는 fd 수
 size_t maxfds		: 최대 등록 가능한 fd 수(필요에 따라 수시로 증가)
 pollFDs			: 현재 사용하고 있는 struct pollfd 구조체 포인터
******************************************************************************/
typedef struct
{
	size_t size;
	size_t maxfds;
	struct pollfd *pollFDs;
} DISPATCHER;

/******************************************************************************
 Dispatcher_Create(const size_t maxfds)
 Dispatcher_Create는 calloc를 통해 DISATCHER구조체를 생성하고 생성된 구조체를
 반환한다.
******************************************************************************/
DISPATCHER *Dispatcher_Create();


/******************************************************************************
 Dispatcher_Destroy(DISPATCHER *dispatch)
 Dispatcher_Create를 통해 생성된 구조체를 free를 통해 소멸시킨다.
******************************************************************************/
void Dispatcher_Destroy(DISPATCHER *dispatch);


/******************************************************************************
 Dispatcher_Add(DISPATCHER *dispatch)
 DISPATCHER의 식별자에 fd를 추가함으로써 poll이 fd를 감시할 수 있도록 한다.
******************************************************************************/
int Dispatcher_Add(DISPATCHER *dispatch, const int fd);


/******************************************************************************
 Dispatcher_Del(DISPATCHER *dispatch)
 DISPATCHER의 식별자에 fd를 삭제함으로써 poll이 fd를 감시에서 제거한다.
******************************************************************************/
int Dispatcher_Del(DISPATCHER *dispatch, const int fd);


/******************************************************************************
 Dispatcher_Wait(DISPATCHER *dispatch, const long timeout)
 등록된 fd들을 감시한다. 또 한 이 함수를 사용한 시점에서는 Block되며 이벤트
 가 발생할때까지 대기하게 된다. timeout으로 대기시간을 설정하게 되면 대기시
 간 이후에 함수를 빠져나가게 된다. 대기시간은 밀리세컨드이다.
******************************************************************************/
int Dispatcher_Wait(DISPATCHER *dispatch, const long timeout);


/******************************************************************************
 Dispatcher_CurfdsSize(DISPATCHER *dispatch) 
 DISPATCHER 에 현재까지 추가된 소켓의 수를 반환한다.
******************************************************************************/
size_t Dispatcher_CurfdsSize(DISPATCHER *dispatch);

#ifdef __cplusplus
}

poll을 객체형식으로 만들어 놓은겁니다. poll의 지저분한(?) 고유 코드는 다 빠지고 이것만으로 하니 별 신경쓸께 없었습니다. 위의 함수군을 사용하는 일은 다른 사람은 없었습니다. 이것은 밑의 Reactor을 만들기 위해 만들어 놓은 것이죠. 써도 별상관 없겠지만 이걸 익히려 노력은 안하리라 생각했기 때문입니다.

다음은 Reactor패턴을 C수준에서 응용한겁니다. 더 세밀히 하자면 함수포인터를 사용해야 했으나..그럴만한 시간적..ㅜㅜ..

Client Handler(CHandler)는 접속된 각각의 개별 커넥션을 말합니다. 그리고 이것들의 이벤트를 관리하며 처리하는 Reactor이 존재합니다. 사용자는 CHandler의 이벤트 발생시에 처리할 부분을 작성하게 됩니다. 즉 비지니스 로직이 들어갑니다.

Reactor은 TCPCLIENT 객체를 추가하게 되면 CHANDLER(Client Handler)를 생성하게 됩니다. 그리고 CHandler_*함수를 각 이벤트 분류에 따라 호출하게 해줍니다. '유저가 작성해야할 함수' 가 가상함수부분인데...여하튼 이 부분을 사용자가 작성해야 전체가 완성됩니다. 이 부분은 비지니스 로직이 들어가야할 부분이죠. 이것을 바탕으로 OnPacket(..)함수등을 만들어 패킷 처리를 하고 그랬었습니다.

CHandler 클래스를 상속받고, 가상함수등을 이용하고 Reactor에 등록시에도 그렇게 하여야 겠으나 그냥 어찌어찌 만들어진 코드입니다. 핑계를 데면 급히 만든 코드이니......... 또 관리자가 STL을 모른다른 이유로 또 C라는 한정적인 이유로 그냥 배열로 CHandler들을 관리하게 될 허접 SOCKETBOX를 만들었습니다.

그리 잘 따른 코드는 아니나 프레임웍이라 생각하고 보신다면 비지니스로직과 네트워크단의 분류가 확실히 되었음을 아실겁니다.

비지니스로직단에서는 마치 쓰레드를 사용하는것 마냥 착각하게 됩니다.

#ifdef __cplusplus
extern "C" {
#endif

typedef struct
{
	SOCKETBOX	*socketBox;
	DISPATCHER	*dispatcher;
	void		*mainArg;
} REACTOR;

typedef struct
{
	REACTOR		*reactor;
	TCPCLIENT	*tcpClient;
	TIMESPEC	 timeout;
	TIMESPEC	 lastAccessTime;
} CHANDLER;


//유저가 작성해야 하는 함수==================================================
//연결되었을때 호출
int  CHandler_Open(CHANDLER *cHandler, TCPCLIENT *tcpClient, void *mainArg);
//데이터가 들어왔을때 호출
int  CHandler_Input(CHANDLER *cHandler, TCPCLIENT *tcpClient);
//연결이 끊겼을때 호출
void CHandler_Close(CHANDLER *cHandler, TCPCLIENT *tcpClient);
//예약한 시간설정이 되었을때 호출
int  CHandler_TimeOut(CHANDLER *cHandler, TCPCLIENT *tcpClient);

//  REACTOR 생성시 호출될 함수
void  Reactor_Open(REACTOR *Reactor);
//  REACTOR 타임아웃시 호출될 함수
void  Reactor_TimeOut(REACTOR *Reactor);
//  REACTOR 파괴시 또는 종료시 호출될 함수
void  Reactor_Close(REACTOR *Reactor);
//===========================================================================


//  REACTOR 생성자
REACTOR  *Reactor_Create(REACTOR *mainArg);
//  REACTOR 파괴자
void  Reactor_Destroy(REACTOR *Reactor);
//  REACTOR 실행
void  Reactor_Run(REACTOR *Reactor);

//유저가 사용할 수 있는 함수=================================================
//새로운 tcpClient를 등록
int   Reactor_Add(REACTOR *Reactor, TCPCLIENT *tcpClient);
//tcpClient를 삭제
int   Reactor_Del(REACTOR *Reactor, TCPCLIENT *tcpClient);

//타임아웃 설정
void  CHandler_SetTimeOut(CHANDLER *cHandler const int sec);

//fd값을 돌려줌
int   CHandler_Getfd(CHANDLER *cHandler);

//최근 접근 시간 셋팅함.
int   CHandler_SetAccessTime(CHANDLER *cHandler);

//최근 접근 시간 셋팅후 지난 시간을 밀리세컨드로 반환
long  CHandler_GetPastTime(CHANDLER *cHandler);

//자신의 아규먼트를 저장
int   CHandler_SetUserArg(CHANDLER *cHandler void *userArg);

//해당 핸들러에 저장한 아규먼트를 가져옮
void *CHandler_GetUserArg(CHANDLER *cHandler);

//생성시 저장했던 아규먼트를 가져옮
int   CHandler_GetMainArg(CHandler *cHandler);

//TCPCLIENT객체를 가져옮
TCPCLIENT *CHandler_GetTcpClient(CHandler *cHandler);

#ifdef __cplusplus
}
#endif

편집과정에서 몇가지 빠진함수가 있기도 하네요.

위와같이 작성하고 CHandler에서 사용할 변수도 CHandler_SetUserArg로 구조체를 통해 등록하여 사용했습니다. 따라서 전역변수를 일체 사용하지 않아도 되는 코드를 생성할 수 있었으며 연결당 개별관리를 Reactor가 CHandler이란것을 통해 해주었으며 CHandler_Open등에서 -1을 리턴하면 무조건 CHandler_Close를 호출하도록 하여 Close함수를 쓸 이유도 없게 되었구요.

특히나 편리했던 부분은 TimeOut부분을 Reactor에서 관리하고 이벤트처리하여 주므로 프로토콜 문서에 따라 복잡해질 로직이 아주 심하게 편해졌다고 말씀 드릴 수 있네요..TimeOut은 커넥트당 개별관리를 Reactor에서 해줍니다. 일반적으로 처리하는 방식인 일정 시간마다 전체 루프를 돌며 하는것이 아니기 때문에 좀 더 안정적이라고 할 수 있겠죠.

이것을 사용한 결과...다른사람이 사용함으로써 생기는 문제에 있어서 제가 그 사람의 비지니스 로직까지 알 필요 없이 이 부분에 대해서만 점검하거나 버그 수정정도에서 마무리 됩니다. 전 이에 관련된 문서나 알고리즘(?) 정도만 철저히 하면 제가 맡은 소켓 라이브러리 부분은 완료 되는 것이었죠.

다른 사람들은 커넥트되는것을 또 데이터가 들어오는것을, 타임아웃되는것을 직접 코드로 작성할 이유가 없었습니다. 그냥 이벤트가 들어오는 데로 처리하면 되는거니까요. 최소한의 지식은 커넥트와 센드, 서버로 띄우는것인데요. 이것들도 랩핑하여 라이브러리화 했습니다.

아마도 C만 하신 분들은 아주 심하게 생소하리라 추측됩니다. 이의가 있으신분은 언제든지요.....

실력자분들이 엄청 많을텐데...허접한 코드....마니 챙피하네요... :(



[출처 : http://kldp.org/node/63623]

# -*- coding: cp949 -*-
#!/usr/bin/python

# commondialogs.py

import wx
import os, sys


class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title)
        
        self.CreateStatusBar()
        # 메뉴바 생성
        menuBar = wx.MenuBar()
        # 메뉴 추가
        menu = wx.Menu()
        menu.Append(99,  "&Message Dialog", "Shows a Message Dialog")
        menu.Append(100, "&Color Dialog", "Shows a Color Dialog")
        menu.Append(101, "&File Dialog", "Shows a File Dialog")
        menu.Append(102, "&Page Setup Dialog", "Shows a Page Setup Dialog")
        menu.Append(103, "&Font Dialog", "Shows a Font Dialog")
        menu.Append(104, "&Directory Dialog", "Shows a Directory Dialog")
        menu.Append(105, "&SingleChoice Dialog", "Shows a SingleChoice Dialog")
        menu.Append(106, "&TextEntry Dialog", "Shows a TextEntry Dialog")
        menuBar.Append(menu, "&Dialogs")
        # 프레임에 메뉴 셋팅
        self.SetMenuBar(menuBar)
        
        # 메뉴별 이벤트 함수 연결
        self.Bind(wx.EVT_MENU, self.message, id=99)
        self.Bind(wx.EVT_MENU, self.choosecolor, id=100)
        self.Bind(wx.EVT_MENU, self.openfile, id=101)
        self.Bind(wx.EVT_MENU, self.pagesetup, id=102)
        self.Bind(wx.EVT_MENU, self.choosefont, id=103)
        self.Bind(wx.EVT_MENU, self.opendir, id=104)
        self.Bind(wx.EVT_MENU, self.singlechoice, id=105)
        self.Bind(wx.EVT_MENU, self.textentry, id=106)


    # 메세지 다이얼 로그 띄우기
    def message(self, event):
        # 메시지 다이얼로그 생성(이벤트 처리기)
        dlg = wx.MessageDialog(self, 'To save one life is as if you have saved the world.', 'Talmud', wx.OK|wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()


    # 색상 다이얼 로그 띄우기(이벤트 처리기)
    def choosecolor(self, event):
        # 생상 다이얼로그 생성
        dlg = wx.ColourDialog(self)
        # 풀 색상 선택창 사용 유무 지정(True : 사용 / False : 미사용)
        dlg.GetColourData().SetChooseFull(False)
        # 색상 다이얼로그에서 색상을 선택후 ok 버튼을 누르면
        if dlg.ShowModal() == wx.ID_OK:
            # 선택한 색상값을 얻엄
            data = dlg.GetColourData()
            # 선택한 색상 값을 Frame의 상태바에 출력함
            self.SetStatusText('You selected: %s\n' % str(data.GetColour().Get()))
       # 색상 다이얼로그 파괴
        dlg.Destroy()


   # 파일 오픈 다이얼로그 띄우기(이벤트 처리기)
    def openfile(self, event):
        # 파일 오픈 다이얼로그 생성
        dlg = wx.FileDialog(self, "Choose a file", os.getcwd(), "", "*.*", wx.OPEN)
       # 파일 다이얼로그에서 파일을 선택후 ok 버튼을 누르면
        if dlg.ShowModal() == wx.ID_OK:
                # 파일의 경로를 구함
                path = dlg.GetPath()
                # 파일 경로에서 파일명만 추출함
                mypath = os.path.basename(path)
               # 선택한 파일의 이름을 Frame의 상태바에 출력함
                self.SetStatusText("You selected: %s" % mypath)
       # 파일 오픈 다이얼로그 파괴
        dlg.Destroy()


    # 페이지 설정 다이얼로그 띄우기(이벤트 처리기)    
    def pagesetup(self, event):
        # 페이지 설정 다이얼로그 생성
        dlg = wx.PageSetupDialog(self)
       # 페이지  다이얼로그에서 페이지 설정 후 ok 버튼을 누르면        
        if dlg.ShowModal() == wx.ID_OK:
           # 페이지 설정 데이타 클래스 구함
            data = dlg.GetPageSetupData()
            # (상단, 왼쪽) 여백을 구함
            tl = data.GetMarginTopLeft()
            # (하단, 오른쪽) 여백을 구함
            br = data.GetMarginBottomRight()
            # 설정한 페이지 설정값을 Frame의 상태바에 출력함
            self.SetStatusText('Margins are: %s %s' % (str(tl), str(br)))
        # 페이지 설정 다이얼로그 파괴
        dlg.Destroy()


   # 폰트 선택 다이얼로그 띄우기(이벤트 처리기)
    def choosefont(self, event):
        # 기본 폰트 생성
        default_font = wx.Font(10, wx.SWISS , wx.NORMAL, wx.NORMAL, False, "Verdana")
        # 폰트정보 클래스 생성
        data = wx.FontData()
        # 시스템의 플랫폼이 Win32라면
        if sys.platform == 'win32':
            #폰트 이펙트 표시함.(False : 표시하지 않음)
            data.EnableEffects(True)
       # 심볼 폰트 선택 할수 없음
        data.SetAllowSymbols(False)
       # 기본 폰트로 초기화함
        data.SetInitialFont(default_font)
       # 폰트 크기 지정 범위
        data.SetRange(10, 30)
       # 폰트 다이얼로그 생성
        dlg = wx.FontDialog(self, data)
       # 폰트  다이얼로그에서 폰트 설정 후 ok 버튼을 누르면
        if dlg.ShowModal() == wx.ID_OK:
           # 설정한 폰트 정보를 얻음
            data = dlg.GetFontData()
            # 설정한 폰트를 구함
            font = data.GetChosenFont()
            # 설정한 폰트 색상을 구함
            color = data.GetColour()
           # 설정한 페이지 설정값을 Frame의 상태바에 출력함
            text = 'Face: %s, Size: %d, Color: %s' % (font.GetFaceName(), font.GetPointSize(),  color.Get())
            self.SetStatusText(text)
       # 폰트 다이얼로그 파괴            
        dlg.Destroy()

   # 디렉토리 다이얼로그 띄우기    

    def opendir(self, event):
        # 디렉토리 다이얼로그 생성
        dlg = wx.DirDialog(self, "Choose a directory:", style=wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON)
       # 디렉토리   다이얼로그에서 디렉토리 선택 후 ok 버튼을 누르면 
        if dlg.ShowModal() == wx.ID_OK:
           # 선택한 디렉토리의 경로를 Frame의 상태바에 출력함
            self.SetStatusText('You selected: %s\n' % dlg.GetPath())
        # 디렉토리 다이얼로그 파괴
        dlg.Destroy()

   # 선택 다이얼로그 띄우기

    def singlechoice(self, event):
        # 리스트
        sins = ['Greed', 'Lust', 'Gluttony', 'Pride', 'Sloth', 'Envy', 'Wrath']
       # 선택 다이얼로그 띄우기
        dlg = wx.SingleChoiceDialog(self, 'Seven deadly sins', 'Which one?', sins, wx.CHOICEDLG_STYLE)
       # 선택   다이얼로그에서 항목 하나를  선택 후 ok 버튼을 누르면
        if dlg.ShowModal() == wx.ID_OK:
           # 선택한 항목을 Frame의 상태바에 출력함            
            self.SetStatusText('You chose: %s\n' % dlg.GetStringSelection())
        # 선택5 다이얼로그 파괴
        dlg.Destroy()

   # 텍스트 입력 다이얼로그 띄우기

    def textentry(self, event):
       # 텍스트 다이얼로그 생성
        dlg = wx.TextEntryDialog(self, 'Enter some text','Text Entry')
        # "Default" 글자를 텍스트 상자에 입력함.
        dlg.SetValue("Default")
        # 텍스트 입력  다이얼로그에서 항목 하나를  선택 후 ok 버튼을 누르면
        if dlg.ShowModal() == wx.ID_OK:
            # 입력한 항목을 Frame의 상태바에 출력함
            self.SetStatusText('You entered: %s\n' % dlg.GetValue())
       # 텍스트 입력 다이얼로그 파괴
        dlg.Destroy()

class MyApp(wx.App):
    def OnInit(self):
        myframe = MyFrame(None, -1, "commondialogs.py")
        myframe.CenterOnScreen()
        myframe.Show(True)
        return True


app = MyApp(0)
app.MainLoop()

[실행 화면]

<< 메인 윈도우 >>

















<< 메시지 다이얼로그 (wx.MessageDialog ) >>












<< 색상 다이얼로그 (wx.ColourDialog ) >>





















<< 파일 다이얼로그 (wx.FileDialog ) >>





















<< 페이지 다이얼로그 (wx.PageSetupDialog ) >>





















<< 폰트 다이얼로그 (wx.FontDialog ) >>


















<< 디렉토리 다이얼로그 (wx.DirDialog ) >>





















<< 선택 다이얼로그 (wx.SingleChoiceDialog ) >>























<< 텍스트입력 다이얼로그 (wx.TextEntryDialog) >>











[출처 : http://pythondev.egloos.com/tag/wx.MessageDialog/page/1]
특정 글자의 "유니코드 값"을 구하는 방법입니다. 유니코드 값이란, 유니코드 번호, 즉 "유니코드 코드 포인트(Code Point)"입니다. 1바이트(8비트)인 아스키 코드와 달리, 2바이트(16비트)입니다.

우선 울트라에디트 등의 편집기를 사용하여, 펄 소스 자체를 "UTF-8 유니코드"로 변환해 주어야 합니다.

그런 후 펄 소스에

use utf8;

이런 프라그마를 삽입합니다. 그러면 이제 유니코드 문자열을 펄 소스에 쓸 수 있고, 펄의 내장 함수들도 유니코드 모드로 작동합니다.

이렇게 해 주지 않으면, ord() 함수가, 유니코드 값이 아닌 그냥 아스키 코드 값을 출력합니다.

ord() 함수로, "유니코드 문자 번호" 알아내기 예제


(UTF-8 유니코드로 다음 예제 소스를 저장해야 함)
#!/usr/bin/perl
use strict; use warnings;

use utf8;


  my $s = "가";
  printf("%04X\n", ord($s));
  # 출력 결과: AC00

  printf("%04X\n", ord("天"));
  # 출력 결과: 5929

  printf("%04X\n", ord("Z"));
  # 출력 결과: 005A



한글 낱자 "가"의 유니코드 값은, 즉 유니코드 코드 번호는 16진수로 0xAC00 입니다.

한자 "天"의 유니코드 값은 0x5929 입니다.


1바이트 알파벳 Z 는, 유니코드에서도, 아스키 코드와 같은 값인 0x5A 가 나옵니다.


[출처 : http://mwultong.blogspot.com/2007/01/perl-hangul-unicode-code-value.html]
>>> a = u'\uAC00'
>>> print a

>>> print a.encode('unicode-escape')
\uac00
>>> print ord(a)
44032
>>> print hex(44032)
0xac00

#!/usr/bin/perl
use strict; use warnings;


while (<>) {                    # 파일 열어, 한 줄씩 읽기
    chomp;                        # 개행 문자 제거
    s/^\s+//;                     # 좌측에 공백 있으면 제거
    s/\s+$//;                     # 우측에 공백 있으면 제거
    push @_, $_ unless $_ eq "";  # (빈 문자열이 아닌 이상) 배열에 추가
}

@_ = sort {$a <=> $b} @_;       # 숫자 크기순으로 소트

print "$_\n" foreach (@_);      # 화면에 결과 출력

+ Recent posts