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

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

 

이전에 파일값을 이용한 bisection search 란 글을 작성하였다.
http://hahaite.tistory.com/277

 

이 코드를 클래스화해서 구현해 보았다. (첨부파일 참조)
테스트를 위한 파일이 들어있으며

main.cpp 를 통해 클래스 멤버함수의 사용 예제를 맛볼 수 있다.
자세한 설명은 생략한다.

fileBisection_class.zip

 

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

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


예전에 만들어 본 기억이 있는데 다시 만드니 삽질...
예방차원에서 올려놓는다.

1. test.dat 파일엔 2 ~ 97 사이의 임의의 숫자 34개가 개행문자 없이 저장되어 있다.
->2 bytes 단위로 읽어들이면 저장된 값을 가져올 수 있음.

 

2. 주어진 값(int target ) 이 test.dat 에 존재하는지 찾는 것을 목적으로 한다.

 

* int getCount() : test.dat 파일에 몇개의 값이 있는지 계산하여 반환한다.

* 첨부파일 : main.cpp, Makefile, test.dat

 

fileBisection.zip

 

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
#include <cstdio>
#include <cstdlib>
 
#define FILE_NAME "./test.dat"
 
static FILE* fp ;
 
int getCount(int width)
{
        fp = fopen(FILE_NAME, "rt") ;
        fseek(fp, 0, SEEK_END) ;
        return (ftell(fp) / width ) ;
}
 
int main()
{
        int width = 2 ;
 
        int count ;
        static char szText[128] ;
 
        count = getCount(width) ;
 
        int fileVal, target ;
        int leftPos, midPos, rightPos ;
 
        fp = fopen(FILE_NAME, "rt") ;
 
        for(int ii = 2; ii <= 97; ii++)
        {
                leftPos = 0 ;
                rightPos = count - 1 ;
 
                target = ii ;
 
                // bisection.
                while(1)
                {
                        midPos = (leftPos + rightPos) / 2 ;
 
                        fseek(fp, midPos * width, SEEK_SET) ;
                        fread(szText, width, 1, fp) ;
                        szText[width] = '\0' ;
 
                        fileVal = atoi(szText) ;
 
                        if(fileVal == target)   // find
                                break ;
 
                        if(leftPos == rightPos) // cannot found
                                break ;
 
                        if(rightPos - leftPos == 1)
                        {
                                if(midPos == leftPos)
                                        leftPos++ ;
                                else
                                        rightPos-- ;
                                continue ;
                        }
 
                        leftPos = (target > fileVal) ? midPos : leftPos ;
                        rightPos = (target <= fileVal) ? midPos : rightPos ;
                }
 
                if(fileVal == target)
                        printf("find ; %d\n", target) ;
                else
                        printf("Cannot find ; %d\n", target) ;
 
        }
 
        fclose(fp) ;
 
        return 1 ;
}
 

 

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

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

printf("%4d", a) ;
와 같은 꼴이 있는데 어떨 땐 위와 같이, 어떨땐

printf("%5d", a) ;

와 같이 사용할 일이 생겼다.

이게 되나? 찾아보니 검색이 잘 안되어 KLDP 에 물어보았다.

http://kldp.org/node/142774

그랬더니 두개의 답변이 올라왔다.
헐~ 이런게 가능했구나... @_@


1. sprintf() 를 이용한 방법.

char buf[100];
sprintf(buf,"%%%dd",4);
printf(buf,a) ;

 

2. printf() 를 이용한 방법.

width = 4;
printf("%*d", width, a);
width = 5;
printf("%*d", width, a);

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

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

STL set 컨테이너에 2차원 배열 삽입하기.
set 항목으로 2차원 배열을 넣어보려 했으나 일단 안되는 것 같다. (아래 링크 참조)
http://kuaaan.tistory.com/167 : ( STL의 원소로 배열(Array)을 사용할 수 없는 이유 )
결국 배열을 구조체 변수로 선언함.
배열의 크기를 설정하기 위해 구조체에 static 변수를 두개 선언함.
memcmp() 로 깔끔이 되는 듯 했으나 배열값이 음수일 때
음수값이 더 크다고 판단하므로 memcmp() 를 쓰면 안되었다.
싸이월드 블로그에 코드 깔끔히 올리는 방법 없나... 찾아봐야겠다.

 

 

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
#include <cstdio>
#include <set>
 
using namespace std ;
 
#define ARRAY_ROW 2
#define ARRAY_COL 3
 
typedef int (Array)[ARRAY_ROW][ARRAY_COL] ;
 
struct Data
{
        static int row ;
        static int col ;
 
        Array array ;
};
 
int Data::row = ARRAY_ROW ;
int Data::col = ARRAY_COL ;
 
struct DataCompare
{
        bool operator() ( const Data& lhs, const Data& rhs) const
        {
                // Don't use memcmp(). It cannot compare between negative number.
                // int ret = memcmp(&lhs.array,&rhs.array, sizeof(lhs.array)) ;
 
                for ( int ii = 0; ii < lhs.row; ii++ )
                {
                        for ( int jj = 0; jj < lhs.col; jj++ )
                        {
                                if(lhs.array[ii][jj] < rhs.array[ii][jj])
                                        return 1 ;
                                else if (lhs.array[ii][jj] > rhs.array[ii][jj] )
                                        return 0 ;
                        }
                }
                return 0 ;
        }
};
 
int main()
{
        set<Data, DataCompare> setData ;
        set<Data, DataCompare> ::const_iterator setDataIter ;
 
        Data data1 = {{{8,7,0}, {8,1,3}}};
        setData.insert(data1) ;
 
        Data data2 = {{{2,3,4}, {4,5,7}}};
        setData.insert(data2) ;
 
        Data data3 = {{{2,3,4} , {4,5,6}}} ;
        setData.insert(data3) ;
 
        Data data4 = {{{ -1,3,4} , {4, -1,6}}} ;
        setData.insert(data4) ;
 
        Data data5 = {{{2,3,4} , {4,5,6}}} ;
        setData.insert(data5) ;
 
        Data data6 = {{{ -1,3,4} , {4,1,6}}} ;
        setData.insert(data6) ;
 
        setDataIter = setData.begin() ;
 
        for ( ; setDataIter != setData.end() ; setDataIter++ )
        {
                printf( "================\n" ) ;
 
                for ( int ii = 0; ii < 2; ii++ )
                {
                        for ( int jj = 0; jj < 3; jj++ )
                                printf( "%d " , setDataIter->array[ii][jj] ) ;
                        printf( "\n" ) ;
                }
        }
 
        Data data7 = {{{ -1,3,4} , {4, -1,6}}} ;
        setDataIter = setData.find(data7) ;
 
        if (setDataIter != setData.end() )
        {
                printf( "find~!!\n" ) ;
        }
 
 
        Data data8 = {{{0,0,4} , {4, -1,6}}} ;
        setDataIter = setData.find(data8) ;
 
        if (setDataIter == setData.end() )
        {
                printf( "cannot Find~!!\n" ) ;
        }
 
        return 1 ;
 
}
 

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

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

 

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
#include <cstdio>
#include <set>
 
using namespace std ;
 
struct Data
{
        int a ;
        int b ;
} ;
 
struct DataCompare
{
        bool operator() ( const Data& lhs, const Data& rhs) const
        {
#if 0
                if (lhs.a < rhs.a)
                        return 1 ;
                else if (lhs.a > rhs.a)
                        return ;
 
                if (lhs.b < rhs.b)
                        return 1 ;
 
                return ;
#endif
                return ( (lhs.a < rhs.a) || ( (lhs.a == rhs.a) && (lhs.b < rhs.b) )) ;
        }
};
 
int main()
{
        set<Data, DataCompare> setData ;
        set<Data, DataCompare>::const_iterator setDataIter ;
 
        Data data;
 
        data.a = 3 ;
        data.b = 5 ;
        setData.insert(data) ;
 
        data.a = 2 ;
        data.b = 5 ;
        setData.insert(data) ;
 
        data.a = 2 ;
        data.b = 2 ;
        setData.insert(data) ;
 
        data.a = 6 ;
        data.b = 8 ;
        setData.insert(data) ;
 
        data.a = 6 ;
        data.b = 7 ;
        setData.insert(data) ;
 
        data.a = 2 ;
        data.b = 2 ;
        setData.insert(data) ;
 
        setDataIter = setData.begin() ;
 
        for ( ; setDataIter != setData.end() ; setDataIter++)
                printf("[%d.%d]\n", setDataIter->a, setDataIter->b) ;
 
        data.a = 6 ;
        data.b = 7 ;
        setDataIter = setData.find(data) ;
 
 
        if (setDataIter != setData.end() )
                printf( "Find~!! - [%d.%d]\n", setDataIter->a, setDataIter->b) ;
 
        data.a = 8 ;
        data.b = 9 ;
        setDataIter = setData.find(data) ;
 
        if (setDataIter == setData.end() )
                printf("No Data~!! - [%d.%d]\n", data.a, data.b) ;
 
 
        return 1;
}
 

 

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

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

최초 작성일 : 2014년 1월 15일.

 

github : https://github.com/hahaite/unblockme_solution


(안풀리는 레벨 댓글에 적어주심 해답 적어드림. ㅋ~~ )
unblockme 몇판 해보다 이걸 내가 왜 풀고 있지? 하는 생각이 들어
풀어주는 코드를 작성함.
코드를 두번 엎은 끝에 그럭저럭 만족스러운 결과를 얻었다.
expert 난이도도 2초 안에 해결.
트리구조 만만히 봤다가 큰코 다침.
linux 환경과 Visual C++ 2010 Express 에서 돌아가는 것 확인함.

1. main.cpp 의 block 6x6 행렬에 벽돌에 맞게 숫자를 넣어주고,
2. 빨간벽돌에 해당하는 번호를 define MASTER_BLOCK 에 설정해 줌.
3. 컴파일 후 실행하면 끝.

(0 값은 빈공간으로 해야 함.)
경험 상 벽돌이 오른쪽이나 아래로 갈수록 큰 수로,
세로 벽돌은 홀수, 가로 벽돌은 짝수로 두는 게 덜 피곤했음.
마음같아선 Visual C++ 로 GUI 까지 만들어보고 싶으나 윈도우 프로그래밍 손놓은지 어언...
게다가, 일해야한다.
행여 프로그램으로 만들어 배포했다가 unblockme 만든 회사에 고소 같은 거 먹을지도 모르겠고~
짜놓은게 아까워 블로그에 올려 봄.
뭐, 누가 볼까 싶긴하지만 맘대로 갖다 쓰시고 댓글이나 써주심 땡큐임.

########## 수정사항.
** 2014년 1월 21일.
block 의 중복비교를 펑크터 형식으로 교체함.

unblockme_20140121.tar

 

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

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

(아래 Makefile의 CFLAGS 부분은 인터넷 검색을 통해서 구한 정보이나  출처를 남기지 못햇다. )

양산 프로그램을 만들 때이다.

"이선임님, 이거 안되는데요?"
"프로그램 교체하셨나요?"
"네, 교체했어요. 버전 불러드릴까요?"

버전을 알아도 소용이 없었다. 깜빡잊고 버전을 변경하지 않은 탓이다.
버전이 자동으로 생성되게 하면 위와 같은 실수를 피할 수 있다.


내가 선택한 것은 컴파일한 시간이 버전이 되도록 하였다.

Makefile 에 아래와 같이 옵션을 추가하였다.

 

*** Makefile
CFLAGS += -DCOMPILE_DATE=\"`date +'%y.%m.%d'`\"

 

main : main.cpp
        g++ -o $@ $^ $(CFLAGS)


기호에 주의해야 한다. 큰따옴표에 그레이브(Grave, 키보드 숫자 1 왼쪽에 있는 따옴표 비슷한...)에
 어퍼스트로피(Apostrophe, 엔터키 왼쪽에 있는 따옴표...) 까지 쓰였다.

이렇게 Makefile 을 설정하고 아래와 같이 출력하면 컴파일 했을 때의 시간을 출력할 수 있다.
(한마디로 실행파일이 만들어진 시간임.)


*** main.cpp

 

1
2
3
4
5
6
7
8
9
#include <cstdio>
 
int main( )
{
        printf( "Date : %s\n" , COMPILE_DATE) ;
        printf( "__TIME__: %s\n" , __TIME__) ;
 
        return 1 ;
}

 

 

위 값을 적절히 버전처럼 변형하여 화면에 뿌려주면 언제 만들어진 실행파일인지 확인할 수 있다.

나는 아래와 같이 사용하였다.
생성한 시간을 10분단위로 쪼개어 카운트하여 나타내었다. (말 어렵다. ;;;; )
아무튼, 아래와 같이 버전을 생성하여 년월일 + 몇시 몇분(10분단위)에
생성되었는지 작성하였다.

프로그램을 릴리즈했는데 잘 안된다라는 말이 나오는 경우,
제일 먼저 이 버전부터 체크하여 최신 프로그램을 사용하고 있는지 확인하였다.

 

 

*** main.cpp


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
#include <cstdlib>
#include <cstring>
 
int main( )
{
        char szVer[256] ;
        char * pTime ;
        int hour, min ;
 
        printf( "Date : %s\n" , COMPILE_DATE) ;
        printf( "__TIME__: %s\n" , __TIME__) ;
 
        strcpy(szVer, __TIME__) ;
 
        pTime = strtok(szVer, ":" ) ;
        hour = atoi(pTime) ;
 
        pTime = strtok(NULL, ":" ) ;
        min = atoi(pTime) / 10 ;
 
        sprintf(szVer, "%s-%02X" , COMPILE_DATE, (hour * 10) + min) ;
 
 
        printf( "szVer : %s\n" , szVer) ;
        return 1 ;
}
 

 

'삽질미학 > C,C++' 카테고리의 다른 글

STL set 컨테이너에 구조체 삽입하기  (0) 2017.01.09
Unblock me 게임 풀어주는 코드  (0) 2017.01.09
TDES-ECB 암호화 코드  (0) 2016.10.24
리눅스 getch() 모듈화하기  (0) 2016.10.20
C++ 코드를 C에서 사용하기  (0) 2016.10.14

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

----------------------------------------------------------------------------------------

 

첨부파일 : des.zip

 

 

일하다가 스펙 요구사항으로 Triple DES - ECB 방식으로 암호화하기를 요구함.
그러면서 예시를 들었다.

key : 10918C6845AB98EF894C6B57BC6776DC [MSB... LSB]

DATA : 00000000000000000000000012345678 [MSB...LSB]

암호화 결과 :

TDES_ECB(Data) : E904F93AD9C2C3848474DB2740AD6162 [MSB...LSB]

열심히 구글링~~

 

ms-word 파일인데
3DES Source Code.doc

 

인데... 링크를 못가져오겠네... ㅡㅡa

깔끔하게 des.h, des.c 로 되어있음.
아래와 같이 key 값과 Data 값을 넣으니 깔끔하게 결과를 얻을 수 있었다. 오홍~

 

des.h, des.c 코드는 첨부파일을 보세요~

첨부파일의 3DES Source Code.doc 파일을 보면 그냥 des 코드도 확인할 수 있습니다.

 

 

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
#include <stdio.h>
#include "des.h"
 
int main()
{
        des3_context ctx3 ;
 
        unsigned char key1[8] = {0x10, 0x91, 0x8C, 0x68, 0x45, 0xAB, 0x98, 0xEF};
        unsigned char key2[8] = {0x89, 0x4C, 0x6B, 0x57, 0xBC, 0x67, 0x76, 0xDC};
 
        unsigned char plaintext[2][8] = {{0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00},
                                        {0x00, 0x00,0x00,0x00,0x12,0x34,0x56,0x78}};
 
        unsigned char enc[8] ;
 
        int ii, jj ;
        des3_set_2keys(&ctx3, key1, key2) ;
 
        for (ii = 0; ii<2; ii++)
        {
                des3_encrypt(&ctx3, plaintext[ii], enc) ;
 
                for (jj = 0; jj<8; jj++)
                        printf("%02x ", enc[jj]&0xff) ;
        }
        printf("\n") ;
 
        return 1 ;
}

 

이글은 예전 제 싸이월드 블로그에 작성한 글을 티스토리로 옮긴 것입니다.

원문 : http://cy.cyworld.com/home/21147242/post/4FE7CE007255739A07C68401
원문 작성일 : 2012.06.25

 

------------------------------------------------------------------------------------------

 

첨부파일 : getChar.zip

 

 

getchar() 함수를 클래스화 시켜서 좀 편하게 써보자 생각함.
getChar.h 랑 getChar.cpp 두개의 파일을 둠.
쉽게 생각했다가 프로그램 종료 시, getchar() 에서 블럭걸리는 증상 발견됨.
하루종일 방법을 고민하다 못찾고 kldp 에 물어 봄.
http://kldp.org/node/133482
pipe(), select() 함수를 사용하여 어케어케 함. 공부할게 생겼다.
위 답변을 가지고 아래처럼 정리하여 동작함을 확인하였다.
제일 아래 main.cpp 에 클래스 사용 예제가 있다.

 


############ getChar.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef _GETCHAR_H_
#define _GETCHAR_H_
#include "pthread.h"
 
typedef void (*CALLBACK_GETCHAR)(char ) ;
 
class CGetChar
{
public :
        CGetChar() ;
        ~CGetChar() ;
        int init(CALLBACK_GETCHAR callback) ;
        int stop() ;
        int destroy(void) ;
 
        // This only use in callback function.
        CALLBACK_GETCHAR m_callbackGetChar ;
        int m_flagStop ;
private :
        pthread_t m_thGetChar ;
};
#endif
 

 

 

 

############ getChar.cpp

 

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
#include "getChar.h"
#include<stdio.h>
#include<termio.h>
#include<unistd.h>
#include<fcntl.h>
 
static int poll_getch[2] = {-1, -1} ;
 
void* threadGetChar(void* pData)
{
        int fd_cancel, fd_stdin, ch ;
        struct termios org_term, new_term ;
        fd_set rdfds ;
        int max_fd ;
        int r ;
        CGetChar* pGetChar = (CGetChar*)pData ;
 
        while(1)
        {
                fd_cancel = poll_getch[0] ;
                fd_stdin = fileno(stdin) ;
 
                ch = -1 ;
                tcgetattr(fd_stdin,&org_term) ;
                new_term = org_term ;
                new_term.c_lflag&= ~(ICANON | ECHO) ;
                new_term.c_cc[VTIME] = 0 ;
                new_term.c_cc[VMIN] = 1 ;
                tcsetattr(fd_stdin, TCSANOW,&new_term) ;
 
                FD_ZERO(&rdfds) ;
                FD_SET(fd_stdin,&rdfds) ;
                FD_SET(fd_cancel,&rdfds) ;
 
                max_fd = fd_stdin>fd_cancel ? fd_stdin : fd_cancel ;
 
                r = select(max_fd + 1,&rdfds, NULL, NULL, NULL) ;
 
                if( r>0&&FD_ISSET(fd_stdin,&rdfds))
                        ch = getchar() ;
 
                tcsetattr(fd_stdin, TCSANOW,&org_term) ;
                pGetChar->m_callbackGetChar(ch) ;
 
                if(pGetChar->m_flagStop)
                        break ;
 
                usleep(1000) ;
        }
        return 0 ;
}
 
CGetChar::CGetChar() :
m_flagStop(0)
{
}
 
CGetChar::~CGetChar()
{
}
 
int CGetChar::init(CALLBACK_GETCHAR callback)
{
        if(pipe(poll_getch)<0)
        {
                perror("pipe") ;
                return 1 ;
        }
 
        m_callbackGetChar = callback;
        pthread_create(&m_thGetChar, NULL,&threadGetChar, (void*)this) ;
        return 1 ;
}
 
int CGetChar::stop()
{
        m_flagStop = 1 ;
        int fd = poll_getch[0] ;
 
        if( fd>= 0)
                write(poll_getch[1],&fd, 1) ;
        return 1 ;
}
 
int CGetChar::destroy(void)
{
        int nStatus ;
        m_flagStop = 0 ;
 
        if(!m_flagStop)
        {
                int fd = poll_getch[0] ;
                if( fd>= 0)
                        write(poll_getch[1],&fd, 1) ;
                m_flagStop = 1 ;
        }
 
        pthread_join(m_thGetChar, (void**)&nStatus) ;
        return 1 ;
}
 

 

############# main.cpp

 

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
#include<cstdio>
#include<unistd.h>
#include "getChar.h"
#include<termio.h>
 
typedef void (*CALLBACK_GETCHAR)(char ) ;
static char m_char ;
 
void cbGetChar(char ch)
{
        m_char = ch ;
        printf("ch : %c\n", m_char) ;
}
 
int main()
{
        CGetChar getChar ;
        getChar.init(&cbGetChar) ;
 
        while(1)
        {
                if(m_char == 'q')
                {
                        getChar.stop() ;
                        break ;
                }
                usleep(1000) ;
        }
 
        getChar.destroy() ;
        usleep(1000) ;
        return 1 ;
}
 

첨부파일 : getChar.zip

이글은 예전 제 싸이월드 블로그에 작성한 글을 티스토리로 옮긴 것입니다.

원문 : http://cy.cyworld.com/home/21147242/post/4E4A12146415739A07C68401
원문 작성일 : 2011.08.16

------------------------------------------------------------------------

 

아래 테스트는 리눅스 환경에서 테스트하였습니다.
C++ 에서 작성된 myList.h, myList.cpp 라는 파일이 있다고 가정합니다.
c 로 작성된 main.c 파일이 있습니다.

main.c 가 myList.h 파일을 include 하여 해당 기능을 수행할 수 있도록 함이 목적입니다.
어떤 C++ 코드를 하나 만들어 봅니다.
C 에서의 사용을 고려하지 않은 C++ 코드는 아래와 같습니다.

 

=================================== myList.h

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef _MYLIST_H_
#define _MYLIST_H_
 
#include<list>
using namespace std ;
 
typedef list<int>MyList ;
typedef list<int>::iterator MyListIter ;
 
class CMyList
{
public :
        int addList(int val) ;
        int getSize() ;
 
 
private :
        MyList m_list ;
        MyListIter m_listIter ;
};
 
#endif // _MYLIST_H_
 

 

======================================= myList.cpp

 
1
2
3
4
5
6
7
8
9
10
11
12
#include "myList.h"
 
int CMyList::addList(int val)
{
        m_list.push_back(val) ;
        return 1 ;
}
 
int CMyList::getSize()
{
        return m_list.size() ;
}

 

위 코드를 gcc로 컴파일하면 당연히 에러가 나겠죠.

아래와 같이 C 에서 컴파일할 수 있도록 작업을 해 줍니다.

 

1. C++ 전용(?) 코드는 #ifdef __cplusplus 로 막아줍니다.
   위 코드에선 STL 선언부랑 클래스 선언부가 해당될 겁니다.

2. C 에서 호출할 수 있도록 함수를 추가하여줍니다.
   int MyList_addList(int val) ;
   int MyList_getSize() ;

3. 구현부에서 name magling 이 안일어나도록 extern "C" 를 선언해 줍니다.
   위 조건대로 수정하면 아래와 같이 수정될 것입니다.

=============================================== myList.h

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
#ifndef _MYLIST_H_
#define _MYLIST_H_
 
#ifdef __cplusplus
 
#include<list>
 
using namespace std ;
 
typedef list<int>               MyList ;
typedef list<int>::iterator     MyListIter ;
 
class CMyList
{
public :
        int addList(int val) ;
        int getSize() ;
 
private :
        MyList m_list ;
        MyListIter m_listIter ;
};
 
#else
 
void* MyList_getInstance() ;
 
int MyList_addList(void* instance, int val) ;
int MyList_getSize(void* instance ) ;
 
void TEST_destory(void* instance) ;
 
#endif
#endif // _MYLIST_H_

 

================================================= myList.cpp

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
#include "myList.h"
 
int CMyList::addList(int val)
{
        m_list.push_back(val) ;
        return 1 ;
}
 
int CMyList::getSize()
{
        return m_list.size() ;
}
 
extern "C"
{
 
void* MyList_getInstance()
{
        CMyList* myList= new CMyList ;
        return (void*)myList ;
}
 
int MyList_addList(void* instance, int val)
{
        CMyList * myList = (CMyList*)instance ;
        myList->addList(val) ;
 
        return 1 ;
}
 
int MyList_getSize(void* instance )
{
        CMyList* myList = (CMyList*)instance ;
        return myList->getSize() ;
}
 
int MyList_destroy(void* instance)
{
        CMyList* myList = (CMyList*)instance ;
        delete myList ;
}
 
}

 

이제 C 전용(?)으로 선언된 아래 함수를 가지고 main.c 에서 써먹어 봅니다.

void* MyList_getInstance() ;
int MyList_addList(void* instance, int val) ;
int MyList_getSize(void* instance ) ;
void TEST_destory(void* instance) ;

=============================================== main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
#include "myList.h"
 
int main()
{
        void* myList = MyList_getInstance() ;
        int size = 0;
 
        MyList_addList(myList, 3) ;
        MyList_addList(myList, 8) ;
 
        size = MyList_getSize(myList) ;
 
        printf("size : %d\n", size) ;
 
        MyList_destroy(myList) ;
        return 1 ;
}

 

C++ 의 클래스 객체를 void* 로 대체하였습니다. 핸들처럼요.
C 나 C++ 컴파일러는 object 파일을 생성하는데 이 object 파일은 C, C++ 모두 공통으로 사용할 수 있습니다.
그래서 위와같이 살짝 수정하여 서로 호출이 가능할 수 있습니다.

정리하면,

1. 헤더파일의 C++ 코드는 C 컴파일러가 안보이도록 막고,
막은 부분을 대처할 수 있는 함수를 만들어줍니다.
#ifdef __cplusplus 부분이 이에 해당합니다.

2. C++ 컴파일러는 함수 오버로딩 때문에 함수 이름을 변경하여 object 파일을 생성합니다.
(Name mangling 관련 부분은 여기서 자세히 언급하지 않겠습니다.)
하지만 C 컴파일러는 함수 오버로딩을 지원하지 않습니다.

예들 들어,

test()

란 함수가 있다고 하면,
이를 C++ 컴파일러로 컴파일하면


testzx6e()

->이런식으로 변경되어 object 파일에 저장됩니다.

C 컴파일러로 컴파일하면

test()

그대로 저장됩니다.

즉, C 컴파일러는 사용자가

test()

라고 호출하면 object 파일에서 직관적으로

test()

를 찾습니다.

그런데 만약 object 파일을 C++ 컴파일러로 컴파일했다면...

test()

함수가

testzx6e()

로 저장되어있기에 C 컴파일러는


testzx6e()

->이 함수를 못찾겠죠.

이 때 사용하는 방법이, C++ 컴파일러에게, 이 파일들은 C 에서 사용될 예정이니
name mangling 을 수행하지 마라, 즉 object 파일 생성 시,


test()

test()

로 저장하라고 알려주는거죠.

이게 myList.cpp 의

extern "C"

부분입니다.

C++ 코드는 object 로 먼저 생성을 해야 C 에서 사용할 수 있습니다.
이제 마지막으로 Makefile 을 작성합니다.
최종 실행파일 생성 시, -lstdc++ 하는 부분에 주의합니다.
================================================= Makefile


main : myList.o main.c

        gcc -o $@ $^ -lstdc++


myList.o : myList.cpp

        g++ -c -o $@ $^


clean :
        rm -rf *.so *.o


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

-lstdc++ 부분은 아래 홈페이지에서 정보를 얻었습니다.
아래 분께서는 저와는 다른 방법 (구조체를 클래스처럼 쓰셨네요.) 으로
C에서 C++ 을 호출하고 계시니 참고하여 읽어보시기 바랍니다.


http://ospace.tistory.com/215

 

이글은 예전 제 싸이월드 블로그에 작성한 글을 가져온 것입니다.

원문 : http://cy.cyworld.com/home/21147242/post/4DE5F25DCB15739A07C68401
원문 작성일 : 2011.06.01
------------------------------------------------------------------------

 

Only C 로 코딩하다 보면 STL 의 컨테이너가 그리울 때가 있습니다.
C++ 로 컴파일해서 오브젝트 파일만 C 에서 갖다 써도 되긴 하지만...

그래서 검색해 봤더니...
역시나 나같은 사람이 있더군요. ㅋㅋ

http://kldp.org/node/112635 - "C++ 에서의<map>을 c 에서 사용하는 방법이 있나요?"
위 글을 통해 SCL (Small Container Library ) 이란 라이브러리를 알게 되었습니다.

홈페이지는 아래와 같습니다.
http://sourceforge.net/projects/libscl/

파일을 받아 압축을 풀면 안에 User Guide 를 통해 자세한 정보를 얻을 수 있습니다.
Hash, List, Map, Queue, Stack, Symbol (이건 뭐지? ), Tree, Vector 등의 함수를 제공합니다.
형식은 STL 의 그것과 꽤 흡사합니다.
예제도 풍부하니 쓰기에 어려움이 없을 것입니다.
그럼, 즐거운 하루 되세요.

 

이글은 예전 제 싸이월드 블로그에 작성한 글을 가져온 것입니다.

원문 : http://cy.cyworld.com/home/21147242/post/4DE5EF53C715739A07C68401
원문 작성일 : 2011.06.01
------------------------------------------------------------------------

 

첨부파일 : abstractFactory_by_c.zip

 

이게 다형성이라는 의미가 맞는건지 모르겠습니다.
차라리 디자인 패턴의 abstract factory 에 더 가까운 것 같기도 하고...
둘 다인가? ㅡㅡa

암튼, 제 의도는 아래와 같습니다.
제품을 만들다보면 어떨 땐 Intel 칩을 쓰기도 하고 어떨 땐 Broadcom 칩을 사용할 때도 있습니다.
비록 칩은 다르더라도 Chip_open(), Chip_read(), Chip_write(), Chip_close() 라는 공통 분모가 있습니다.

다시 얘기하면,
UI 개발자는 Intel 칩이든 Broadcom 칩이든 신경 안쓰고 저 4개 함수만 호출하면 되도록 짜고싶은거지요.

UI 에서 Chip_open(), Chip_read(), Chip_write(), Chip_close() 를 호출했을 경우,

Intel칩이라면 최종적으로 아래 함수가 호출되고,
INTEL_Chip_open(), INTEL_Chip_read(), INTEL_Chip_write(), INTEL_Chip_close() 가 호출되고,

Broadcom 칩이라면 최종적으로 아래 함수가 호출되도록 하는겁니다.
BROADCOM_Chip_open(), BROADCOM_Chip_read(), BROADCOM_Chip_write(),BROADCOM_Chip_close()

C++ 에서는 순수가상함수와 다형성을 이용하여 구현할 수 있습니다.
C 에선 함수포인터를 이용하여 비슷하게 구현할 수 있더군요. 형태 기록차원에서 초 간단하게~~
main.c 에서 Chip_open(), Chip_read(), Chip_write(), Chip_close() 가 호출되어집니다.
또한 main.c 가 바라보는 건 chip.h 만 바라봅니다.
chip.c 에서 어떤 칩을 사용할 것인지 결정하고, 그 결정에 따라 Intel 또는 Broadcom 의 함수포인터를
넘겨줍니다.

 

코드 분량을 최소화 했으니 보시는데 어려움이 없을 겁니다.

첨부파일 : abstractFactory_by_c.zip

 

map 컨테이너를 이용해 클래스 멤버함수의 콜백함수 등록과 호출하기.

이글은 예전 제 싸이월드 블로그에 작성한 글을 가져온 것입니다.

 

원문 : http://cy.cyworld.com/home/21147242/post/4D75C4B98555739A07C68401
원문 작성일 : 2011.03.08

--------------------------------------------------------------------------------------------------------------


제목 참 거창하네...
일하다가 번뜩 떠올라 짜봤습니다.
map 컨테이너를 이용해 등록된 콜백함수를 좀 더 빠르게 찾지 않을까 하는 기대감입니다.
등록되는 콜백함수는 일반함수가 될 수도 있으나 클래스 멤버함수도 등록될 수 있음을 보였습니다.
클래스 멤버함수와 함수포인터의 관계는 데브피아 강의에 잘 나와있습니다. (아래 링크 참조)


http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNo=20&no=7431&ref=7431


아래와 같이 구상하고 흐믓해하며 자만심에 잠깐 빠져있다가
누군가도 나와같은 생각을 했을텐데.... 하고 검색해 봤습니다.
역시나... 기는 놈 위에 나는 분 계시더군요.
template 을 이용해 일반화까지 구현하여 블로그에 올리신 분이 계시더군요.
클래스 멤버함수 콜백 : http://blog.naver.com/yiyousung?Redirect=Log&logNo=80113313235
아래는 허접한 제 코드입니다.

 

 

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
#include<cstdio>
#include<map>
 
using namespace std ;
 
enum Psi
{
        eDescVideo,
        eDescAudio,
        eDescSubtitle
};
 
class CPsiDescriptor
{
public :
        int switchDesc(Psi psi) ;
 
 
private :
        int descVideo(int a, int b) ;
        int descAudio(int a, int b) ;
        int descSubtitle(int a, int b) ;
};
 
typedef int (CPsiDescriptor::*FUNC_DESC)(int a, int b) ;
 
int CPsiDescriptor::switchDesc(Psi psi)
{
        static int flagSwitchDesc = 0 ;
 
 
        static map<Psi, FUNC_DESC>mapDesc ;
        static map<Psi, FUNC_DESC>::iterator mapDescIter ;
 
 
        static FUNC_DESC funcDesc ;
 
        if(!flagSwitchDesc)
        {
                mapDesc.insert(make_pair(eDescVideo,&CPsiDescriptor::descVideo)) ;
                mapDesc.insert(make_pair(eDescAudio,&CPsiDescriptor::descAudio)) ;
                mapDesc.insert(make_pair(eDescSubtitle,&CPsiDescriptor::descSubtitle)) ;
 
 
                flagSwitchDesc = 1 ;
        }
 
 
        mapDescIter = mapDesc.find(psi) ;
 
 
        if(mapDescIter != mapDesc.end())
        {
                funcDesc = mapDescIter->second ;
                (this->*funcDesc)(2, 3) ;
        }
        else
        {
                printf("cannot find PSI tags\n") ;
        }
 
 
        return 1 ;
}
 
int CPsiDescriptor::descVideo(int a, int b)
{
        printf("callback : descVideo()\n") ;
        return 1 ;
}
 
 
int CPsiDescriptor::descAudio(int a, int b)
{
        printf("callback : descAudio()\n") ;
        return 1 ;
}
 
int CPsiDescriptor::descSubtitle(int a, int b)
{
        printf("callback : Subtitle()\n") ;
        return 1 ;
}
 
int main()
{
        CPsiDescriptor psiDesc ;
 
        psiDesc.switchDesc(eDescVideo) ;
        psiDesc.switchDesc(eDescAudio) ;
        psiDesc.switchDesc(eDescSubtitle) ;
 
        return 1;
}
 

 

이글은 예전 싸이월드 블로그에 작성한 글을 가져온 것입니다.


원문 : http://cy.cyworld.com/home/21147242/post/4D75C4B98555739A07C68401

작성일 : 2011.03.08 

------------------------------------------------------------------------

아래 코드를 돌리면 무한루프에 빠집니다.

 #include<stdio.h>


int main()
{
     FILE* fp = fopen("FacotryStream.trp", "rb")
     unsigned char szBuff[1024] ;
     while(!feof(fp))
    {
          fread(szBuff, 4, 1, fp) ;
          fseek(fp, 184, SEEK_CUR) ;
     }
     printf("test finnish~~!!\n") ;
     return 1 ;
}



언뜻 보기엔 FILE 핸들을 받아 4Bytes 읽고 184Bytes 점프~

그러다 파일 끝에 도달하면 while() 문을 빠져나오는 것 같은데 말이죠.
핵심은 fseek() 함수입니다.
man fseek 해서 나오는 문구를 그대로 인용해보면,
"
fseek 함수의 연속적인 호출은 스트림을 위한 EOF 지정자를 지우고
.....블라블라블라~~"
그러므로 fseek() 함수 이후에 호출되는 feof() 함수는 무용지물이 된다는거죠.
위 코드의 while() 문은 아래와 같이 fseek 이전에 feof() 를 호출하도록 수정되어야 합니다.

while(1)
{
    fread(szBuff, 4, 1, fp) ;
    if(feof(fp))
        break ;
    fseek(fp, 184, SEEK_CUR) ;
}
그럼, 즐거운 하루 되세요.



이글은 예전 싸이월드 블로그에 작성한 글을 가져온 것입니다.


원문 : http://cy.cyworld.com/home/21147242/post/4C7DB9A7C7D5739A07C68401

작성일 : 2010.09.01 11:25


-----------------------------------------------------------------------

어떤 문자열이나 데이터에서 특정 비트열을 가지고 오고 싶을 때 사용하는
매크로 함수를 만들어 보았습니다.

PSI 데이터 parsing 하다가 만들게 되었네요.

buf 에 데이터를,
x, y 에 시작 비트열과 끝 비트열을 넣어주시면 됩니다.

맘대로 갖다 쓰셔도 되며 출처나 적어주심 감사하고~~
혹시나 버그 있을지 모르니 조심히... =_=;;

#define GETBIT_16(buf, x, y) (((unsigned short)(((0xFFFF>>((x) - 1)) \
                                                 ^ (0xFFFF>>(y))) \
                                                 &((unsigned short)(buf<<8) | ( *(&buf + 1))))) \
                                                 >>(16 - (y)))

#define GETBIT_8(buf, x, y) (((unsigned char)(((0xFF>>((x) - 1)) \
                                               ^ (0xFF>>(y)))&(unsigned char)(buf))) \
                                               >>(8 - (y)))

사용법.

unsigned char* szDATA ; // 데이터가 들어있는 변수.

11110011 01101100

위와같이 16개의 비트가 있을 때,

왼쪽에서 5번째부터 10번째까지 가져오고 싶다면~

GETBIT_16(*szDATA, 5, 10) ; // GETBIT_16(szDATA, 5, 10) 아님.

이렇게 사용하시면 됩니다.

+ Recent posts