나도 함 github 써보고자 들어가서 계정 만들고 repository 도 만들고~

 

그러다 push 할 때마다 id, password 넣는게 귀찮아서 ssh 키 연동을 찾아 봄.

 

github 소개랑 ssh 키 생성은 검색하면 많이 나오고 아래는 그 외 사항을 잊지않으려 추가한 정도이다.

(나는 이미 예전에 생성한 ssh 키를 사용하고 있다.)

 

1. clone 시, https 가 아니라 ssh 로 시작하는 주소로 clone 해야 한다.

ssh 주소는 아래 useSSH 키 누르면 확인할 수 있다.

 

 

 

2. ~/.ssh/config 를 설정하고 있다면,

host 를 github.com 으로 바꾸어야 한다.

 

 

3. 아래 명령어로 ssh key 의 연동을 확인할 수 있다.

$ ssh -T git@github.com

Hi hahaite! You've successfully authenticated, but GitHub does not provide shell access

 

와 같이 출력되면 된다.

 

위와 같이 하니 수정 후, push 할 때 바로 서버로 전송되었다.

 

roughTimer_C_170622.zip

roughTimer_CPP_170622.zip

 

 

제목 : Rough Timer

언어 : C, C++

OS : Ubuntu 14.04

컴파일러 : gcc, g++

라이센스 : 누구나, 어디서나 쓸 수 있습니다. (누가 쓰겠냐마는...)

 

usleep() 함수를 이용해 타이머를 만들어 보았다. (첨부파일 참조)

 

예를 들어 2초짜리 타이머를 등록하면,

쓰레드에서 100ms 마다 1씩 카운트하여 2초가 됐을 때 콜백함수를 호출하는 방식이다.

 

고로, 정확도는 떨어지며 100ms 이하 타이머는 사용할 수 없다.

정확도 보다도 "약 몇초 후에" 식으로 운영되는 타이머라면 심플하게 쓸 수 있을 것이다.

 

 

이에 Rough Timer 로 명명하였다.

 

C++ 코드는 STL List 를 사용하였고,

C  코드는 간단히 linked-list 함수를 만들어 사용하였다.

 

코드 안에 main() 함수에서 간단한 테스트 코드를 볼 수 있다.

 

(주의사항 : 타이머 발동 시, 호출되는 콜백함수는 최대한 빨리 빠져나와야 한다.

 그렇지 않으면 전체 타이머 시간과 다른 타이머에 영향을 준다.)

 

 

 

msgQueue_CPP_170616.zip

 

 

컴파일 환경 : Ubuntu 14.04

 

(추후, C 기반 포팅작업 필요함.)

 

모듈의 독립성을 높이기 위해 메시지큐를 사용하여 task 를 처리하는 틀을 작성한다.

 

예를 들어 Core 부분과  UI Display 부분이 있을 때,

Core는 UI의 존재를 모르도록 구성한다.

 

Core 는 자신의 task 를 메시지큐에 전달하면 main 에서 이를 판별하여

이 후 작업(UI 갱신 등)을 진행하도록 한다.

 

이와 같은 작업을 위해 코드를 작성하였으며 추후 투입될 작업에 맞춰

모듈과 task 정의를 추가한다.

select() 함수를 예제보고 가져다 쓰기만 하다가 뭔가 수정만 하면 잘 안되어

이대로는 안되겠다 싶어 개념을 좀 더 파악하기로 하였다.

 

♣ fd_set 구조체

fd_set 구조체는 File Descriptor (이하 FD) 를 저장하는 구조체이다.

안에 내용을 보면 그냥 배열로 여기면 편하다.

 

구조체 내용은 OS마다 조금씩 다른 듯 하다.

내가 쓰는 Ubuntu 14 에선 /usr/include/sys/select.h 에서 위 구조체를 확인할 수 있었다.

 

♣ FD_SET

fd_set 구조체에 2와 5의 FD 를 저장한다고 하면,

두번째 비트와 다섯번째 비트가 1로 변경된다.

값 저장은 FD_SET 매크로를 쓴다.

 

fd_set testFds ;

FD_SET(2, &testFds) ;

FD_SET(5, &testFds) ;

 

위 testFds 구조체의 배열값을 출력해 보면,

0 1 0 0 1 0 0 0 0 ~~~

위와 같이 2번째와 5번째 비트가 1 로 세팅된다.

 

♣ FD_ZERO

언급했듯이 fd_set 구조체의 주요 변수는 배열이다.

fd_set testFds ; 와 같이 선언만 하고 안에 배열값을 찍어보면 쓰레기값이 있을 수 있다.

 

이에 구조체를 초기화 해야 하며 아래와 같이 한다.

FD_ZERO(&testFds) ;

 

위에 FD_SET 예제에서도 변수 선언 후, 초기화를 해 주어야 한다.

 

fd_set testFds ;

FD_ZERO(&testFds)

FD_SET(2, &testFds) ;

FD_SET(5, &testFds) ;

 

♣ FD_CLR

FD_SET(2, &testFds) ;

FD_SET(3, &testFds) ;

FD_SET(5, &testFds) ;

 

위와 같이 입력 후, testFds 는 아래와 같이 세팅된다.

0 1 1 0 1 0 0 0 0 ~~~

 

이 때 만약 3번 FD 를 지우고 싶으면 FD_CLR 매크로를 쓴다.

FD_CLR(3, &testFds) ;

 

결과는 아래와 같다. 세번째 값이 0으로 초기화 되었다.

0 1 0 0 1 0 0 0 0 ~~~~

 

♣ FD_ISSET

이 매크로는 아래 select 함수와 함께 설명한다.

 

 

♣ select()

select 함수는 fd_set 구조체에 할당된 FD 의 이벤트가 발생하면

이를 감지하고 어떤 FD 이벤트가 발생했는지 알려준다.

 

ex)

fd_set testFds ;

FD_SET(2, &testFds) ;

FD_SET(5, &testFds) ;

 

select(6, &testFds, NULL, NULL, NULL) ;

 

이는 FD 이벤트는 6 미만값만 체크하며,

6 미만 중 2와 5 FD 의 이벤트가 발생했을 때만 깨어난다.

 

만약 2번 FD 의 이벤트가 발생하여 select 함수가 깨어나고,

select 함수 이후에 testFds 를 찍어보면,

 

0 1 0 0 0 0 0 0 0 ~~~~~~~

식으로 값이 변경된다. -> 이걸 몰라 한참 헤맸다.

 

즉 testFds 에 2, 5 FD 를 저장한 후,

저장된 FD (2,5) 중 이벤트가 발생하면,

해당 이벤트만 1 로 남기고 모두 0 으로 세팅한다.

 

이제 어떤 FD의 이벤트가 발생했는지 체크하여 FD_ISSET 매크로를 사용한다.

 

if(FD_ISSET(2, &testFds))

{

  // 2번 FD 가 발생했다.

}

 

if(FD_ISSET(5, &testFds))

{

  // 5번 FD 가 발생했다.

}

위와 같이 해당 FD에 대한 후처리를 진행하면 된다.

 

 

♣ 틀 정립

select 함수는 위 예제처럼 testFds 를 변경시킨다.

그럼 select 함수 전이나 후로 매번 testFds 를 다시 세팅해 주어야 한다.

 

이에 아래와 같은 틀이 될 것이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
fd_set readFds ;
FD_ZERO(&readFds) ;
FD_SET(2, &readFds) ;
FD_SET(5, &readFds) ;
 
while(1)
{
      // select 함수에서 fd_set 이 변경되니 원본 대신 복사본을 select 함수에 전달한다.
      checkFds = readFds ;
 
      printf("sleep - select()\n") ;
      select(6, &checkFds, NULL, NULL, NULL) ;
      printf("wake up - select()\n") ;
 
      if(FD_ISSET(2, &checkFds))
      {
          // 2번 FD 이벤트에 대한 사후 처리.
      }
 
      if(FD_ISSET(5, &checkFds))
      {
          // 5번 FD 이벤트에 대한 사후 처리.
      }
}

 

♣ 정리

이런 저런 코드를 보면서 원본 (readFds) 를 checkFds 로 복사하는 이유를 몰랐는데

select() 함수 내에서 fd_set 구조체 값을 변경하기 때문이다.

 

이를 위와 같이 정리하며 아래 내용이 빠져있다.

  • select() 함수의 리턴값 처리
  • select() 함수의 첫번째 인자 max FD 값의 처리
  • select() 함수의 세번째, 네번째 인자 writeFds, exceptFds 에 대한 처리.
  • select() 함수의 다섯번째 인자 타이머에 대한 처리.

 

도움받은 사이트 : http://blog.naver.com/dolzzo/130131251201

 

뭔가 간단한 프로그램을 짜고 있는데 프로그램 종료할 때마다 segmentation fault 가 뜨길래

디버깅해보니 육안상 이상이 없었다.

 

gdb 로 코어 뜨고 한참을 삽질한 끝에야 원인을 찾을 수 있었다.

 

나처럼 조인시위키 (https://www.joinc.co.kr/w/man/3/pthread_join) 를 통해 쓰레드를 익혔으면

아래 형태를 많이 봤을 것이다.

 

int status ;

pthread_join(thread, (void**)&status) ;

 

이 코드가 32bits OS 에선 이상이 없는데 64 bits OS 로 넘어오면서 문제를 일으킨다.

 

sizeof(void**) 값은 8인데 여기에 4Bytes 짜리 int 타입의 변수를 넣었기 때문에 메모리 충돌을 일으킨 것이다.

(64bits Linux 로 넘어온지 3년쯤 되는데 그동안 왜 아무일 없었던거지?)

 

해결책으론 아래와 같이 int 대신 long 을 쓰거나,

 

long status ;

 

아니면 아예 void* 로 선언하는 경우가 있겠다.

(앞으론 아래처럼 써야겠다.)

 

void* status ;

pthread_join(thread, &status) ;

 

참고로, 정보문화사의 Beginning Linux Programming (3판) 의 예제를 보면

아래와 같이 status 값을 확인하고 있다.

 

printf("status : %s\n", (char*)status) ;

 

 

도움받은 사이트 : https://github.com/scrooloose/nerdtree/issues/85

 

NerdTree 사용할 때 오브젝트 파일과 같이 볼일 없는 파일은

.vimrc 파일에 아래와 같이 설정한다.

 

let NERDTreeIgnore=['.o$','.d$','.lo$']

 

그런데 위와 같이 하면 etc/init.d 와 같은 디렉토리까지 안보인다.

이에 아래와 같이 [[file]] 을 붙여주면 file 만 적용되게 된다.

let NERDTreeIgnore=['.o$','.d$[[file]]','.lo$']

 

만약 디렉토리만 ignore 에 추가하려면 [[dir]] 을 붙여준다.

초딩 1학년인 딸아이가 학교에선 뺄셈 들어가는데 아직 덧셈도 잘하지 못해

안되겠다 싶어 여러 문제를 만들어 봄.

 

 - A+B 가 10보다 작은 경우만 수집함. -> 총 55가지인가 나옴.

 - 결과를 랜덤으로 섞음.

 - 몇장 만들 것인지 설정할 수 있음.

 

 - 추가로 빼기 경우도 만들어봄.

 - 결과가 음수인 경우는 배제. 큰 수의 최대값은 9임.

 

Ubuntu 14.04 에서 컴파일 함.

 

결과물 txt 파일을 MS-Word 로 복사해 출력하여 교재로 활용함.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include <cstdio>
#include <cstdlib>
 
#include <algorithm>
#include <vector>
 
#define SEED_FILE "seedValue.dat"
 
#define PAGE_NUMBER     20    // 생성할 페이지 수
 
#define ADD            // 덧셈 예제를 생성함.
//#define SUB         // 뺄셈 예제를 생성함.
 
// ADD, SUB 둘 다 define 되어있거나, 
// 아무것도 define 되어있지 않은지 체크함.
#if defined(ADD) && defined(SUB)
#error "defined both ADD and SUB."
#endif
 
#if !defined(ADD) && !defined(SUB)
#error "NOT Defined anything."
#endif
 
// srand() 함수에 사용될 seed 값을 증가함.
// 이전값을 기억하여 랜덤 결과가 겹치지 않도록 함.
unsigned int getSeed()
{
        FILE* fp = fopen(SEED_FILE, "rt") ;
        if(!fp)
        {
                FILE* fp = fopen(SEED_FILE, "wt") ;
                fprintf(fp, "1") ;
                fclose(fp) ;
                return 1 ;
        }
 
        unsigned int seed ;
        char szText[128] ;
 
        fgets(szText, sizeof(szText), fp) ;
        seed = atoi(szText) ;
 
        fclose(fp) ;
 
        return seed + 1 ;
}
 
// 예제에 사용될 샘플을 수집하여 vector에 저장함.
int makeList(std::vector<int>* pVecInt)
{
        int result ;
        for(int ii = 0; ii <= 9; ii++)
        {
                for(int jj = 0; jj <= 9; jj++)
                {
#ifdef ADD
                        result = ii + jj ;
 
                        if(result >= 10)
                                continue ;
#elif defined SUB
                        result = ii - jj ;
 
                        if(result < 0)
                                continue ;
#endif
 
                        result  = (ii * 10) + jj ;
                        pVecInt->push_back(result) ;
                }
        }
 
        return 1 ;
}
 
// 수집한 샘플을 파일로 저장함.
int makeFile(std::vector<int>* pVecInt, int seed, FILE* fp)
{
 
        int a, b ;
        int cnt = 0 ;
        const int ROW = 4 ;
        std::vector<int>::iterator      vecIntIter ;
 
 
        fprintf(fp, "Seed Index : %d\r\n", seed - 1 ) ;
 
        vecIntIter = pVecInt->begin() ;
        for(; vecIntIter != pVecInt->end(); vecIntIter++)
        {
                a = *vecIntIter / 10 ;
                b = *vecIntIter % 10 ;
 
 
                if(cnt % ROW != 0)
                        fprintf(fp, "      ") ;
 
#ifdef ADD
                fprintf(fp, "%d + %0d = ", a, b) ;
#elif defined SUB
                fprintf(fp, "%d - %0d = ", a, b) ;
#endif
 
                if(cnt % ROW == ROW - 1)
                        fprintf(fp, "\r\n") ;
 
                cnt++ ;
        }
 
        return 1 ;
}
 
int main()
{
        std::vector<int>                        vecInt ;
        static char szName[128] ;
 
        unsigned int seed = getSeed() ;
        srand(seed) ;
 
#ifdef ADD
        printf("ADD mode : %d\n", seed) ;
        sprintf(szName, "addTest_%d-%d.txt", seed, seed - 1 + PAGE_NUMBER) ;
#elif defined SUB
        printf("SUB mode : %d\n", seed) ;
        sprintf(szName, "subTest_%d-%d.txt", seed, seed - 1 + PAGE_NUMBER) ;
#endif
 
        FILE* fp = fopen(szName, "wt") ;
 
        for(int ii = 1; ii < PAGE_NUMBER; ii++)
        {
                seed++ ;
 
                if(seed == 0x8fffffff)
                        seed = 1  ;
 
                FILE* fpSeed = fopen(SEED_FILE, "wt") ;
                fprintf(fpSeed, "%d", seed) ;
                fclose(fpSeed) ;
 
                vecInt.clear() ;
 
                makeList(&vecInt) ;
 
                // 수집한 샘플을 섞음.
                random_shuffle(vecInt.begin(), vecInt.end()) ;
 
                makeFile(&vecInt, seed, fp) ;
 
                fprintf(fp, "\r\n") ;
                fprintf(fp, "\r\n") ;
 
        }
 
        fclose(fp) ;
 
        return 1 ;
}
 

5년 전, 두바이에서 계속되는 출장연기로 끝내 투표를 못했다.

오후에 법인장, 팀장 두분과 술이랑 먹거리를 바리바리 싸들고

호텔에 모여 노트북으로 개표 현황을 보았다.


그 와중에 본사에선 자꾸 뭐가 안된다고 연락오고,

술한잔 마시니 아파오던 잇몸이 더욱 아파오고,

투표 못해 우울한데 개표 결과는 미쳐가 그냥 술만 마셨다.


좀있다 아내가 괜찮냐고 카톡을 보냈다.

답장하기 위해 고개를 숙이다 울컥해 눈물을 쏟았다.

팀장은 남자놈이 운다고 버럭하시고 법인장은 달래고 얘기들어 주었다.


다음날,

이 엿같은 상황에 그냥 숨이 탁탁 막혔다. 5년... 5년...

후유증은 꽤나 길었던 기억이 있다.


그 억겁같은 5년이 지났다. 내 나이도... ㅠㅠ


저번의 극한 초조함은 살짝 아쉽게도 미미하다.

헌재 탄핵 결정 때 절실히 체감했으니 퉁 친다.



'상사꽃 > 때로는' 카테고리의 다른 글

공단오거리  (0) 2018.01.03
청춘들의 민중가요 뒷풀이 노래  (0) 2017.12.22
PARK OUT  (0) 2017.04.12
오랜만에...  (0) 2017.01.19
[2015.06.23] 이천 용인닭집  (0) 2016.10.09

파일을 정리하다 전에 감동먹고 스샷 찍어놓은 파일이 있어 박제한다.

 

 

'상사꽃 > 때로는' 카테고리의 다른 글

청춘들의 민중가요 뒷풀이 노래  (0) 2017.12.22
억겁의 5년  (0) 2017.05.09
오랜만에...  (0) 2017.01.19
[2015.06.23] 이천 용인닭집  (0) 2016.10.09
[2015.05.20] 지평 막걸리  (0) 2016.10.09

tcpTest_C_170616.zip

tcpTest_CPP_170616.zip

 

**** 수정 이력

* 2017-06-16 : 종료 시, pipe() 함수에서 얻어진 File Descriptor로 처리하도록 함.

********************

 

 

첨부파일 압축을 풀면 server, client 두개의 디렉토리가 생성된다.

각각 디렉토리에서 컴파일 후 실행하여 TCP Server, Client 간 연결을 확인한다.

 

정보문화사의 Beginning Linux Programming 3판에서

15장 소켓, 다중 클라이언트 부분을 크게 참고하였고 적당히 수정하였다.

 

's' + [enter] 를 누르면 상대방에 데이터를 보내고,

'q' + [enter] 를 누르면 프로그램을 종료한다.

(이 부분은 main.cpp 참조)

 

- 종료 시, recv() 함수에서의 행업 이슈가 없다.

- 각 단의 시작 순서에 상관 없이 잘 동작한다. (client 를 먼저 실행해도 상관없다.)

- 연결 후, 서버단을 죽이고 다시 시작해도 재연결이 잘 이루어진다.

- 연결 후, 클라이언트단을 죽이고 다시 시작해도 재연결이 잘 이루어진다.

 

 

개인 보관용 목적의 글이므로,

 

 

이글은 예전 제 싸이월드 블로그에 작성한 글을 티스토리로 옮긴 것입니다.
원문 : http://cy.cyworld.com/home/21147242/post/54A21ECBD6D5739A07C68401
원문 작성일 : 2015.3.12

============================================================

제 PC엔 windows8 이 깔려있습니다.
여기에 VirtualBox를 설치하였고,
VirtualBox 에 리눅스(Fedora)를 설치하였습니다.
한줄요약 : 윈도우에서 VirtualBox를 이용해 리눅스를 돌리고 있음.
위와같이 리눅스를 설치하고 윈도우에서 putty 를 이용해 리눅스에 ssh로 접속하여 작업합니다.
쉬운 브리지 어댑터 먼저 썰을 풉니다~

 


1. 브리지 어댑터 (Bridge Adapter)


Virtualbox 에서 Fedora를 실행하기 전에 아래와 같이 네트워크에서 브리지 어댑터를 선택합니다.
(아래 이미지는 리눅스를 실행한 후에 캡쳐를 한 것인데 실행 전에 선택해야합니다.)

 

 

이 경우, PC가 공유기로부터 IP를 받는 경우,
리눅스 또한 공유기로부터 IP를 받습니다.
윈도우의 IP가 192.168.10.xx 라면, 리눅스의 IP 또한 192.168.10.xx 가 됩니다.
브리지 어댑터로 설정하면 아래와 같은 구조라고 생각하면 됩니다.

 


위에 언급했듯이 전 윈도우에서 putty 를 이용해 리눅스에 접속하는 걸 선호합니다.
브리지 네트워크로 설정할 경우, 공유기가 없다면? 리눅스가 IP를 할당받지 못해
윈도우에서 리눅스로 접속할 방법이 없더군요.
공유기를 함께 챙기면 되겠지만 그러지 못한 상황이라면...
NAT 설정을 통해 이를 극복할 수 있습니다.


 

2. NAT


NAT의 개념은 저도 정확히 이거다 말하기가 애매한데요. 그냥, 경험을 통해 아~ 이렇구나 했습니다.
아니면 댓글로 알려주세요~
NAT 설정은 저 위에 Virtualbox 네트워크 설정에서 브리지 어댑터 대신 NAT를 선택하면 됩니다.
Virtualbox 를 설치하면 dos 에서 VirtualBox Host-Only Network 를 확인할 수 있습니다.
C:\>ipconfig

 

 

결론부터 얘기하면,
윈도우에서 리눅스로 접속하고 싶을 때,
위 주소 192.168.56.1 로 접속하여 리눅스로 접속할 수 있습니다.


(이 개념 찾는게 제일 힘들었네요. 전 계속 리눅스의 10.0.2.15로 접속하려고 시도했거든요.
그런데 막상 검색해도 쉽게 안나오던 정보였습니다.)

이에 몇가지 설정이 필요합니다.
VirtualBox 에서 NAT 로 설정한 후, 리눅스를 설치하고 ifconfig 하면
아래와 같이 10.0.x.15 주소를 확인할 수 있습니다.

 

 

이 주소는 NAT 설정 후 나타나는 주소입니다.
저 위에 윈도우에서 리눅스로 접속하기 위해 192.168.56.1 IP 를 사용한다고 했는데요.
이 192.168.56.1 이 리눅스의 10.0.2.15 IP와 연결되게 됩니다.
그러므로 윈도우에서 192.168.56.1 로 접속을 시도하면 리눅스로 연결 되게 됩니다.

이제 NAT 설정 시, 그림을 다시 그려보면 아래와 같이 됩니다.
(이 개념은 지극히 개인적인... 고로 틀렸을지도 모릅니다. ㅜ.ㅠ )

 

브리지 어댑터의 경우, linux 가 바로 공유기에 연결된 개념이었는데
NAT의 경우, 위와 같은 구조이기에 공유기랑 상관없는 구조입니다.
공유기가 없는 환경에서 리눅스에 접속할 필요가 있을 경우, NAT를 사용하면 되겠지요~
이제 마지막 과정입니다.
192.168.56.1 과 10.0.2.15 사이에 포트포워딩을 해 주어야 합니다.
아래와 같이 포트포워딩을 선택합니다.


 

 

그러면 아래와 같은 그림이 나옵니다.
아래 제가 설정한 경우입니다.
이미지 오른쪽의 + 버튼을 클릭하여 규칙을 추가하시면 됩니다.

 

 

전 putty 를 이용해 리눅스에 접속하여 작업하기에 22번 포트를 포워딩했습니다.
그리고 리눅스에서 인터넷을 사용하기 위해 80번 포트를 포워딩했습니다.
기타 환경에 맞게 추가하여 주시면 됩니다.
위와 같이 설정한 후에 putty에서 192.168.56.1 로 접속시도하면 리눅스로 연결됩니다.

 

이글은 예전 제 싸이월드 블로그에 작성한 글을 티스토리로 옮긴 것입니다.
원문 : http://cy.cyworld.com/home/21147242/post/55078597BC95739A07C68401
원문 작성일 : 2015.3.12

============================================================

 

임베디드 보드에서 유니코드를 처리할 일이 있어
일단 리눅스에서 테스트를 하였습니다.
별 탈 없이 문자열(ex) 한글) 잘 뿌리는 거 확인하고
테스트 보드로 포팅하여 테스트했더니 엇~ 문자열이 안나오는겁니다.
테스트보드에선 유니코드를 지원 안하나봅니다.
그래서 아래와 같이 테스트를 해 보았습니다.
1. 윈도우에서 메모장을 열고 한글을 입력합니다.
2. "다른이름으로 저장" 하게 되면 하단에 아래 그림과 같이 4가지 타입으로 저장할 수 있습니다.
3. 4개의 파일로 따로 저장합니다.
ex) test_ANSI.txt, test_Unicode.txt, test_Unicode_BE.txt, test_UTF-8.txt

 

 

그리고 생성한 4개의 txt 파일을 보드에 복사하여 열어봤습니다.
했더니 UTF-8 만 정상으로 나오고 나머지는 다 깨지네요.
아하~ 테스트보드는 UTF-8만 지원하나봅니다.
그럼 Unicode를 UTF-8 로 변환하여 출력하면 되겠군요.
Unicode ->UTF-8 로의 변환을 그림으로 표시하면 아래와 같습니다.
(도움받은 사이트 : http://en.wikipedia.org/wiki/UTF-8 )

 

위 사이트에 들어가보면 unicode 값이 0xffff 값보다 더 큰 경우에도 설명이 되어있는데
일단 그 범위까지 쓸일이 없기에 위 범위만 처리하였습니다.
이에 아래와 같이 변환하는 함수를 만들어 보았습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void UnicodetoUTF8( const wchar_t * pUnicode, char * szText)
{
        int uniLen = wcslen(pUnicode) ;
 
        for ( int ii = 0; ii<uniLen; ii++)
        {
                if ( 0<= pUnicode[ii]&&pUnicode[ii]<= 0x7f)
                {
                        szText[0] = pUnicode[ii]&0xff ;
                        szText++ ;
                }
                else if ( 0x80<= pUnicode[ii]&&pUnicode[ii]<= 0x7ff)
                {
                        szText[0] = ((pUnicode[ii]>>6)&0x1f) | 0xc0 ;
                        szText[1] = (pUnicode[ii]&0x3f) | 0x80 ;
                        szText += 2 ;
                }
                else if ( 0x800<= pUnicode[ii]&&pUnicode[ii]<= 0xffff)
                {
                        szText[0] = ((pUnicode[ii]>>12)&0x0f) | 0xe0 ;
                        szText[1] = ((pUnicode[ii]>>6)&0x3f) | 0x80 ;
                        szText[2] = (pUnicode[ii]&0x3f) | 0x80 ;
                        szText += 3 ;
                }
                else
                {
                        printf( "ERROR~!! pUnicode>0xffff, 0x%x\n" , pUnicode[ii]) ;
                }
        }
        szText[0] = '\0' ;
 
        return ;
}
 

그럼, 즐프하세요~ ^^

 

 

 

 

 

 

 

 

 

 

 

 

 

 

오랜만에 글을 남겨본다.

 

15년 10월 싸이월드 블로그가 폭파되고 나서 방황하다가,

티스토리로 옮기기로 마음먹고 html, css 공부하다가 포기하고

남 스킨 적용해서 글은 어느정도 옮겨놨고...

 

처음으로 글을 남겨본다.

 

뭔가 덜 지어진 집에서 사는 느낌이다.

나이가 들어서인가, 새로운 것도 적응이 안되고~

 

글 제목 옆에 조회수나 나타나면 좋겠다. 그나마 사람이 왔다간 최소한의 흔적인데 말이다.

'상사꽃 > 때로는' 카테고리의 다른 글

억겁의 5년  (0) 2017.05.09
PARK OUT  (0) 2017.04.12
[2015.06.23] 이천 용인닭집  (0) 2016.10.09
[2015.05.20] 지평 막걸리  (0) 2016.10.09
[2015.04.17] 세월호 참사 1주년 추모  (0) 2016.10.09

이글은 예전 제 싸이월드 블로그에 작성한 글을 티스토리로 옮긴 것입니다.
원문 : http://cy.cyworld.com/home/21147242/post/5500EDA6EA95739A07C68401
원문 작성일 : 2015.3.12

============================================================

 

list 컨테이너에서 조건에 맞는 값을 찾고자 할 때 find_if() 함수를 쓴다.
조건값이 특정값이라면 함수객체(펑크터)를 사용해 쉽게 구현이 되지만
조건값을 변수 형태로 취하려면 어댑터 개념을 적용해야 한다.

C++ 기초 플러스, C++ Standard Library 책을 눈알 빠지게 봐도 뭔소린지 모르겠다.
결국 SOEN(http://www.soen.kr) 에서 도움을 받았다.
(SOEN ->C/C++ 강좌 ->4부.C++고급 ->38장 함수객체 ->바인더)
한국인이 쓴 책이 문장도 좋고 이해가 잘 될 때가 분명히 있다.

아래 코드는 보관용 수준으로 작성한 예제이다.
- list 에 4개의 값을 저장하였다.
- 이 중 나는 number 값이 1003인 이터레이터를 가져오고 싶다.
- 1003이 아닌 다른 값을 가져오고 싶다면, filter 변수값을 변경하면 된다.

아래 예제는 number가 1003인 구조체값을 가져와 그 구조체의 major 값을 찍었다.
원하는대로 값을 가져오고 있다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <cstdio>
#include <list>
#include <algorithm>
#include <functional>
 
using namespace std ;
 
 
struct Program
{
        int major ;
        int number ;
        int pid ;
} ;
 
class FindProgram : public binary_function<Program, int , bool >
{
public :
        bool operator() ( const Program& p, int b) const
        {
                return (p.number == b) ;
        }
} ;
 
int main()
{
        list<Program> listProgram ;
        list<Program> ::iterator listProgramIter ;
 
        Program program ;
 
        program.major = 7 ;
        program.number = 1001 ;
        program.pid = 0x20 ;
        listProgram.push_back(program) ;
 
        program.major = 7 ;
        program.number = 1002 ;
        program.pid = 0x21 ;
        listProgram.push_back(program) ;
 
        program.major = 9 ;
        program.number = 1003 ;
        program.pid = 0x22 ;
        listProgram.push_back(program) ;
 
        program.major = 11 ;
        program.number = 1004 ;
        program.pid = 0x23 ;
        listProgram.push_back(program) ;
 
        int filter = 1003 ;
 
        listProgramIter = find_if(listProgram.begin(), listProgram.end(), bind2nd(FindProgram(), filter)) ;
 
        if(listProgramIter != listProgram.end())
        {
                printf("val : %d\n", listProgramIter->major) ;
        }
 
        return 1;
}
 


 

이글은 예전 제 싸이월드 블로그에 작성한 글을 티스토리로 옮긴 것입니다.
원문 : http://cy.cyworld.com/home/21147242/post/5440C0C849D5739A07C68401
원문 작성일 : 2014.10.17

============================================================

 

github : https://github.com/hahaite/Big_Integer

 

File : bigInt_170713.zip

 

오일러 프로젝트 (http://euler.synap.co.kr/) 를 풀다가
엄청나게 큰 수를 계산해야 하는 상황이 발생했다.
이에 제목과 같은 걸 함 짜보자싶어 구현하게 되었다. (첨부파일 참조)
덕분에 자릿수 제약이 없는 정수 계산이 가능하였다. ex) 1000!
큰 수의 계산에 촛점을 두었기에 많은 횟수의 연산은 속도가 느릴 수 있다.

간단한 사용법은 아래와 같다.

CBigInt A, B, C ;
A = 12345 ; // int 형 입력 가능.
B = "111234574734892783" // 매우 큰 수는 string 형으로 입력함.
C = A + B ;
printf("sum : %s\n", C.c_str()) ;

 

기타 사칙연산 증가,감소연산, 크기 비교 등이 가능하다.

 

추가로 Euler Project를 풀면서 몇몇 필요한 아래 기능이 추가되었다.
 - n! (Factorial) 계산.
 - string 뒤집기
 - palindrome 인지 체크
 - string 정렬
 - 조합(combinations) 계산.
 - 분수 계산.
 - 제곱 (pow) 계산.

 

====================================================
기타 예제는 첨부파일의 main.cpp 에 있다.
테스트하고 싶은 부분을 #if 0 ->#if 1 로 바꾸고 컴파일 한 후 결과를 확인할 수 있다.
표준 함수를 사용하였으므로 개발환경의 영향을 받지 않으리라 본다.
테스트는 Fedora13, GCC 4.4.5 기반에서 테스트를 진행하였다.
================================

뭐 누가 사용할까 싶긴 한데요.
혹시나 사용하다 버그 발견이나 수정사항 있으면 댓글로 알려주세요.
참, 이 코드는 FREE~!! 입니다.

+ Recent posts