매일매일 개발하는 소스코드를 올리고 있습니다. 원래는 프로젝트가 끝나고 올리려고 했으나, 그러다 보니 까먹는 경우가 있어서 이렇게 매일매일 올리는 소스코드 입니다. 제가 쓴 소스코드의 문제 혹은 개선점이 있으면 언제든지 댓글 달아 주세요
뿌리깊은 나무를 본 영향인지 모르겠지만, 아무튼 최근에 소스분석을 하면서 느낀점은 한글인지 여부를 &0x80으로 if 문에 바로 쓰시는 분들이 계신데,그렇게 쓰면 코드가 clean 하지가 않고 해당 코드에 대한 의미를 알지 못하는 다른 분들이 볼때는 창피한 코드가 될수 있습니다. 조금은 번거로울수 있지만, 함수로 빼서 명확한 이름을 할당 함으로써 다른 개발자로 하여금 의미 혼동이 없게 하는 방법을 사용합니다. 보기좋은 떡이 먹기도 좋은것 처럼, 깨끗한 코드가 당신이 어떤 프로그래머인지를 말합니다.
현재 시간을 가져오는 소스코드. 물론 시간관련 헤더파일이 #include <time.h>가 추가 되어 있어야 한다. 좀더 유용하게 쓰기 위해서 현재 시간에 대한 정보를 리턴하고 있으며, 최근에 하는 프로젝트에서 프로그램 시작에서 시간 변수에 저장하고, 끝날때 또 다른 시간변수에 저장해서 차이를 구해서 성능 및 시간에 대한 측정을 하는데 사용했다.
사실 블로그에 이런 소스를 올려야 하나 하는 생각도 들었다. 나만의 좀더 특색있는 코드를 올리고 싶었지만, 너무 기초적인 것 이기에 별로 안 올릴려고 했는데, 그래두 많은 내용이 많이 공유되면 더 좋은 거니까 .. ^^ 그리고 나도 가끔 정작 쓸때가 되면 생각이 안난다능.
문자열의 갯수를 구하는 함수만큼 공통적으로 여러 언어에서 구현되어 있는 기능도 드문것 같습니다. 오늘 소개할 내용은 C++ 의 <string.h> 내에 있는 char * 형의 문자열의 갯수를 세어주는 strlen() 함수에 대해서 이야기 하려고 합니다. 제목처럼 일반적인 객체지향의 언어 자바나 C#의 String 클래스에서 사용하는 lenght() 함수와 어떻게 다른지 이야기 하려고 합니다. 물론 아시는 분들도 있겠지만.^^
먼저 C++ 에서 사용하는 경우를 살펴볼까요? 대부분 다음과 같이 사용하겠지요.
C++
include <string.h>
char * name = "tom";
int count = strlen(name);
count 는 얼마일까요?
당연히 3입니다. 그러면 자바에서 문자열의 길이를 가져오는 함수를 사용하는 경우를 볼까요?
JAVA
String name = "tom";
System.out.println(name.length());
이 경우에도 3이 나옵니다. 그러면 도데체 무엇이 다를까요? 여러분도 아시다 시피 영문자와 숫자는 각각 1byte를 소비하는것으로 알고 있습니다. 그러나 한글의 경우에 달라지지요. 즉 1byte 가 아니라, 2byte를 차지합니다.
그러기 때문에,
C++
char * name = "김문수";
int count = strlen(tom);
JAVA
String name = "김문수"; System.out.println(name.length());
이 둘의 결과는 다르게 나옵니다. 위의 strlen() 함수의 경우에는 한글 3글자기 때문에 6byte. 즉 6이 나오게 되는 것입니다. 그러나, 자바의 경우에는 한글의 경우에도 영어와 마찬가지로 3이 나오게 됩니다.
그 이유는 개념이 조금 다른것인데요, C++에서 사용하기 strlen() 함수의 경우에는 현재 검사 대상인 char * 포인트가 가리키는 곳의 사용 바이트 수를 체크합니다. 때문에 한글의 경우, 2byte 이기 때문에 길이가 다르게 나오는 것이고, 자바에서는 length() 함수에서 하는 일은 말 그대로 글자수를 체크해 주는 것입니다.
최근에 알게된 사실은 외국의 문자에서는 3바이트 짜리 문자도 있다고 하더군요. 사실 자바 개발자 분들이나 혹은 다른 개발자 분들이 strlen()을 쓰실때 그렇게 길이라고 생각하고 쓰실수도 있지만, 더 큰 문제는 다양한 개발자들이 개발해 놓은 소스코드 내에서 strlen() 함수가 랩핑되어져서 length() 처럼 표현되었을 경우, 혼란을 가져올수 있다는 것입니다.
또 다른 문제는 사실상 다국어에 대한 처리가 없다면 상관이 없지만 혼합되 문자열의 처리의 경우 strlen()만으로 글자수를 체크한 다는 것은 조금은 버거운 일이 아닌가 하는 생각이 들었습니다.
매일매일 개발하는 소스코드를 올리고 있습니다. 원래는 프로젝트가 끝나고 올리려고 했으나, 그러다 보니 까먹는 경우가 있어서 이렇게 매일매일 올리는 소스코드 입니다. 제가 쓴 소스코드의 문제 혹은 개선점이 있으면 언제든지 댓글 달아 주세요
strlwr() 이라는 함수는 <string.h> 에 있는 함수로 대문자를 소문자로 바꿔주는 함수이다. 그런데 사실 string.h 에 있는 모든 함수들이 모든 환경에서 작동하는 것이 아니다. 본인이 확인할 결과, AIX 서버에서는 몇몇의 함수들이 개발자가 의도하는 대로 움직여 주지 않는다.
예를 들면, strcasecmp() 함수는 비교를 대소문자 구별없이 해 주는 함수인데, 그 부분은 작동을 하지만, 한글의 경우 간간히 작동하지 않는 현상을 발견했다. 사실 아래의 함수는 그로 인해서 만들게 되었다. strlwr() 함수가 안되기 떄문에 대문자를 소문자로 바꿔주는 함수를 만들었고 사실은 이 다음에 strcmp()함수를 호출함으로써 strcasecmp() 함수의 의도를 풀어 놓은 것이다.
이번 프로젝트를 하면서 허벌나게 CSplitterWnd 와 함께 동거동락을 하고 있는데요. MainFrame 에서 CSplitterWnd 에 대해서 구획 나누어 주고 뷰 배치하는 작업 그리고 CSplitterWnd 재정의 해서 굵기 조정하는 부분까지. 다 했는데 하나의 고비가 남아 있더군요. 그것은 바로. 런타임에서 CSplitterWnd 에 배치된 뷰를 바꾸는 일입니다.
I used CSplitterWnd in this project. In MainFrame, I was coding the Work placing view, dividing region using CSplitterWnd. Also override CSplitterWnd and then adjust the thickness. But, One obstacle remains. It's just. In RunTime environment, change View in CSplitterWnd.
일단 MainFrame 을 가져오고 나서 CCreateContext 를 생성합니다. 위의 코드는 뷰에 도큐먼트가 없는 뷰를 대상으로 하고 있기때문에 Doc 연결을 가져오지 않는데요, 만약 도큐먼트가 있는 뷰라면 해당 부분을 넣어 주어야 할것 입니다. 그리고 CSplitterWnd 의 해당 위치에 DeleteView 를 통해서 해당 뷰를 지우고, 다시 CreateView 를 통해서 전환할 뷰를 생성해 주면 됩니다. 매우 간단하지요?
Once, Get pointer of MainFrame, Create CCreateContext. In the above code, Do not get Document Connection becauseof the view without document. But if the view get Document, insert document connection part. And erase the view using DeleteView fuction of CSplitterWnd, Create changing view using CreateVIew Fucntion. It is very Simple.
그런데 만약 전환하려는 뷰의 OnInitalUpdate() 함수에서 뷰 안에 있는 컨트롤들을 배치하고 있다면?
Butif youwant toswitchthe viewOnInitalUpdate ()functionin thecontrolofthe viewif you areplaced?
아쉽게도 CreateVIew 를 통해서 런타임 상에서 배치를 하게 되면 OnInitalUpdate() 함수가 호출되지가 않습니다. 만약 어떤 정의하는 부분이나 초기화 하는 부분이 있다면 초기화가 되지 않겠지요. 때문에 명시적으로 호출해 주어야 합니다. 그래서 CView 클래스의 인스턴스를 만들어서 생성된 View 를 가져와서 명시적으로 OnInitialUpdate() 를 호출해 주고 있는 것입니다.
Unfortunately, if placedonthe runtime throughCreateVIew, OnInitalUpdate () functionis notcalled. If you have any part of definition or initiation, do not define or init. so you must call init. So that call explicitly OnInitialUpdate() function using the point of created view.
런타임 상에서 OnInitialUpdate() 함수를 사용하기 때문에 그에 관련해서 오류가 생길수도 있으니 조심하세요.^^
매일매일 개발하는 소스코드를 올리고 있습니다. 원래는 프로젝트가 끝나고 올리려고 했으나, 그러다 보니 까먹는 경우가 있어서 이렇게 매일매일 올리는 소스코드 입니다. 제가 쓴 소스코드의 문제 혹은 개선점이 있으면 언제든지 댓글 달아 주세요
PNG를 쓰는 이유는 단 하나다. 배경의 투명처리 때문. 하지만 DC로 그릴경우에는 MFC의 리소스에 등록해서 그러야 하는 불편함이 있고, PNG 리소스 등록도 번거롭다. 가장 큰 문제는 리소스를 많이 쓰면 팀 작업간의 SVN Conflict가 자주 날수 있기에. 아래와 같이 png의 경우 파일로 보여주는 것도 나쁘지 않다.
The reason of using PNG image file is one. becauseof Transparent. But you draw any grpahic using DC, you have to register Resource of MFC. It is very inconvenient. The important problem of using resource is that you may experience SVN Confilict in team works. so it is not bad that load png file:
요즘 계속 배포작업을 하고 있습니다. 처음 배포 한 msi 파일이 배포오류가 생겼었는데, 그 오류를 자세히 들여가 보면 fileloadException 에 의해서 발생된 오류였다. 처음에는 기본적으로 ini 파일이나, 폰트파일 혹은 외부 dll 파일을 못 읽어서 문제가 생겼나 해서 예외처리를 한 상태에서 해 봤더니, 걸리지 않았다. 그래서 혹시나 해서 devpia에 찾아볼 결과 다음과 같은 결과가 나왔다.
C++/CLI는 C#과는 달리 런타임 라이브러리를 사용하곤 합니다. (msvcm80.dll)
이 라이브러리는 닷넷 프레임워크와 함께 설치됩니다.
하지만 개발시에 Debug 빌드와 함게 사용되는 라이브러리는 Visual Studio 내에만 포함되어 있습니다.
(msvcm80d.dll)
따라서 Debug 빌드로 작성된 exe를 사용하면 이들 디버그용 라이브러리를 찾으려고 할 것이고
이 라이브러리는 달랑 닷넷 프레임워크만 설치된 곳에는 존재하지 않기 때문에
오류가 발생합니다.
배포에 사용하시려면
Release 빌드를 배포하시거나 Debug용 런타임 라이브러리를 배포하셔야 합니다.
도움이 되셨기를...
즉, 원 C# 으로 만든 프로젝트에 MixString 이라는 C++ 외부 라이브러리를 붙였는데, 빌드 형태의 Debug로 해서 빌드를 한후에 Click Once 프로젝트에서 해당 .exe 파일을 대상으로 빌드를 하고, 다른 컴퓨터에서 실행 시켰을 경우, 위와 같은 이유로 에러가 난다는 것이다.
실제로 Release 로 빌드 형태를 바꾸어서 빌드하고, 배포프로젝트에 넣어서 빌드하니 다른 컴퓨터에서도 잘 되었다.
원래 다른 분 블로그에 있었던 것인데, 퍼왔습니다. 출처를 표시해야 하는데, 프로젝트 코드에 넣은지 꽤 돼서 출처 찾기가 힘드네요. ㅠ 혹시 보시다가 본인이 쓴 글이라고 하시면 출처표시 해 드리겠습니다.
일단 설명을 드리자면, 윈폼에서 최소화, 최대화, 닫기 및 상단의 텍스트 표시를 없애고 이미지만 나오게 윈폼을 개발하는 경우가 있지요. 사실 ControlBox 를 마우스로 드래그앤 드롭하면 움직이는데, 전체를 이미지로 덮어 버리는 경우에는 그런 부분을 만들어 줘야 합니다.