검색결과 리스트
분류 전체보기에 해당되는 글 48건
- 2013.06.13 Image To SWF 1
- 2012.04.04 DLL 함수 호출 시 발생하는 PInvokeStackImbalance Exception 3
- 2011.11.27 AutoHotKey
- 2011.10.31 최소제곱(자승)법(Least Square Method)의 실시간 계산
- 2010.08.06 VC++ DLL 자동 버전 빌드 구성하기 1
- 2009.08.02 다음 영어사전 Ubiquity 명령어 2
- 2009.06.02 jQuery 탭 컨트롤
- 2009.06.01 자꾸만 까먹는 웹 개발 소스 및 링크
- 2009.05.25 너무 더워~ㅠ_ㅠ 1
- 2009.05.23 L-O-V-E 4
글
PPT를 SWF를 변환하는 프로그램은 많지만, 죄다 상용..
쓰고싶니? 그럼 돈내... 깡패들...
찾아보니 괜찮은 프로그램들이 많던데... 안사주므로... 걍 대충 하나 만듦.
근데, 아무래도 이미지로 변환하다보니 품질은 별로임... PDF에서 SWF로 변환하는 것이 가장 품질은 좋긴 한데, Office 2013은 자동으로 지원하지만 그 이하버전에서는 지원하지 않는 것이 단점 아닌 단점. PDF Creator를 설치하면 참 좋은데... 여기다 설명하긴 길고...
또 하나. 이렇게 해서 만들어진 SWF는 자동 슬라이드 방식임. 마우스로 클릭한다고 넘어가는 것이 아니라 자동으로 슬라이드가 넘어가는 방식임. 이벤트나, 돌잔치때, 이미지 슬라이드 하는 것과 같다고 생각하면 됨. 아래는 Sample. (작아서 글자 깨져보이는건 기분탓)
준비물:
http://swftools.org/download.html
노란 부분을 다운 받아, 긍정적인 마인드로 Next를 누르면서 진행한다. GPL라이센스이고 하니, 아마 바이너리는 프리웨어인 듯...
이 친구들이 프로그램은 다양하게 만들어 놓은건 좋은데, 참... 개발자 프렌들리한 친구들인지 UI라곤 눈 씻고 찾으면 한개 있다.
그래서 하나 만듦. 일단은 Jpeg을 SWF로 쉽게 만들기 위해서 짧게 하나 구현함.
이거 다운받아서 실행하면 귀차니즘 이즈 베스트인 프로그램이 하나 뜬다.
저기 위에 있는 흰 사각형에 Jpg 파일을 드래그 & 드롭하면 확장자가 .jpg인 친구들만 리스트에 뜬다. 중간에 이미지 하나 삭제하려면 어떻게 하냐고? 꼈다 키세요.
그리고나서 Run을 누르면 바탕화면에 OutputSWF.swf란 파일이 생성됨. 이를 익스플로러 하나 띄워서 드래그&드롭하면 실행된다.
만약 실행이 안된다면..
http://msdn.microsoft.com/en-us/library/5a4x27ek.aspx
위 링크에 가서
Stand-Alone이라고 되어 있는 저 부분을 다운로드 받아 설치하면... 아마 실행될꺼임.
PS. PPT 이미지로 저장하기
파일 -> 다른 이름으로 저장 -> 파일 형식 -> JPEG 파일 교환 형식
파워 포인트에서 위 순서대로 하면, 폴더에 이미지가 쭉 저장됩니다.
글
오늘 회사에서 아는 형이 코드에서 "PInvokeStackImbalance" Exception이 발생한다고 도와달라고 했다.
사실 여기서 가장 큰 문제는 "왜 되던 코드가 안되는 것일까?" 였다. 이전 프로젝트에서는 DLL을 잘 로드해서 썼는데, 새로 프로젝트를 만들고 똑같이 DLL을 로드했는데 갑자기 위의 Exception이 발생했다고 한다.
그래서 두 프로젝트를 비교해봤더니 사용하던 .Net Framework 버전이 달랐다. 잘 되던 곳은 3.0을 쓰고 있었고, 안되는 곳은 4.0을 쓰는 문제가 있었다.
그래서 찾아봤다. 역시 문제는 CallingConvention 문제.
[DllImport("TestDll.dll")]
public static extern int Test(string text);
위와 같이 작성되었던 것을
[DllImport("TestDll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern int Test(string text);
이렇게 뒤에 CallingConvention을 붙여서 호출하면 된다.
보통 C++에서 DLL을 만들면 cdecl 이란 호출규약으로 만든다. 왜냐면 다들 귀찮으니까 별도의 호출규약을 안써준다. 근데, C#에서 DllImportAttribute의 CallingConvention은 기본값이 stdcall이다. 그래서 에러가 난거다.
호출규약에 대해서 궁금하면 여기! 를 참고하면 좋다.
뭐... 이거야 쉽게 해결했지만 왜 3.0에서는 된걸까?
여러 글을 찾아보다가 결국 해답은 못찾았다. 하지만 StackOverflow에 같은 질문이 올라온 글에 David Hefferman이란 사람이 아래와 같이 적어놓았다.
Don't kid yourself that your code is alright because .net 3.5 doesn't raise this error. The error detection in .net 4 is better which is why you only see the errors there. But your code is broken in all .net versions.
굳이 해석하자면...
"3.5에서 에러가 나지 않았다고 코드에 이상없다고 착각하지 마. 단지 4.0에서 이러한 에러를 잘 찾아내니까 발생한거야. 니 코드는 모든 .net 버전에서 에러야"
음. 명언이다. 에러가 안난건 단지 4.0의 성능이 좋아서다. 내가 봐도 확실히 에러 맞다.
글
keyState_01:=Not keyState_01
if(keyState_01)
{
setTimer, myTimerHandler, 4000 ; 반복 입력 주기를 입력
}else{
setTimer, myTimerHandler, off
}
return
myTimerHandler:
Send, {F7} ; 반복 입력하고 싶은 키
return
글
아무튼 유틸리티가 필요했던 이유는 다름이 아니라 바로 개발자의 최대의 적! 메모리 누수가 일어나는 지를 알아보기 위함이다.
회사 프로젝트 특성상, Operation에 따라 메모리 사용량이 출렁거리는 상황이기 때문에 꾸준히 메모리를 본다고 해서 누수가 나는지, 안나는지를 알 수 없었다. 그래서 단순히 실시간으로 프로그램의 메모리 사용량을 파일로 기록하는 프로그램을 만들었는데...
메모리 사용량의 추세를 알기 위해 다음의 짓을 매번 반복했다.
1. 로그 파일을 열어서
2. Excel에 붙여넣고
3. 2차원 꺽은선 그래프를 그리고
4. 추세선 그리기
근데 너무 이 짓이 귀찮아서, 실시간으로 추세선을 알 수 있는 방법이 있지 않을까 해서 사용한 것이 "최소제곱(자승)법" 이다.
뭐... 이쯤되면 최소 자승법이 뭔지는 네이버, 구글에서 뒤져보면 나올 것이고...귀찮은 분은 위에 링크를 클릭~!
이를 구현하기 위해서 수식을 살펴봤는데, 적용하기엔 무리가 있었다. 왜냐하면 "최소제곱법"을 이용해 추세선을 그리기 위해서는 데이터를 모두 가지고 있어야 한다는 점이였다.
위 수식을 보면, 실시간 데이터기 때문에 평균x, y가 매번 바뀌고, 이를 구하기 위해서는 매번 평균 계산을 다시해야 한다. 물론 평균값을 유지하는 것이 아니라 데이터의 총 합만 유지하면 매번 평균값을 구하는 것은 O(1)시간에 구할 수 있다.
그러나... a 공식의 분자, 분모를 계산할 때도 그럴까?
이를 계산하기 위해서는 O(n)의 계산이 필요한데, 매 초당 이런 계산을 한다는 것은 매우 부담스러운 일이고... 시간이 갈 수록 n이 커지기 때문에 점점 계산량이 많아진다는 부담이 있다.
개선의 시작은 다음과 같은 아이디어에서 시작했다.
"n-1번째의 a를 구하고, 여기에 x,y 평균의 변화량을 이용해서 n번째의 a를 구할 수 있지 않을까?"
그래서 각 식을 n-1번째 식으로 전개해서 풀어보았다.
(수식을 타이핑하기 귀찮으므로... 전개는 생략한다...)
는 페르마드립이고, 첨부파일에 스캔해놓은 발로 쓴 공식을 참조하길 바란다.
결국, 1), 2) 식과 각 x, y의 총합만 매 Tick(데이터가 들어오는 순간)마다 업데이트하면 a를 구할 수 있었다.
다음은 이를 c++로 구현한 소스이다.
[LSM Structure.h]
### cpp
struct LSMData
{
float x, y;
};
struct Linear
{
float a, b;
};
[LeastSquareMethod.h]
### cpp
#include "LSMStructure.h"
class LeastSquareMethod
{
public:
LeastSquareMethod(void);
public:
~LeastSquareMethod(void);
int Count() { return m_nCount; };
void Reset()
{
m_lnResult.a = 0;
m_lnResult.b = 0;
m_nCount = 0;
m_fTotalX = 0.0f;
m_fTotalY = 0.0f;
m_fDeltaX = 0.0f;
m_fDeltaY = 0.0f;
m_fDeltaXX = 0.0f;
m_fDeltaXY = 0.0f;
}
void AddData(const LSMData& data);
Linear GetTrendency();
private:
void Update(const LSMData& data);
Linear m_lnResult;
int m_nCount;
float m_fTotalX, m_fTotalY;
float m_fDeltaX, m_fDeltaY;
float m_fDeltaXX, m_fDeltaXY;
};
[LeastSquareMethod.cpp]
### cpp
#include "LeastSquareMethod.h"
LeastSquareMethod::LeastSquareMethod(void)
{
Reset();
}
LeastSquareMethod::~LeastSquareMethod(void)
{
}
void LeastSquareMethod::AddData(const LSMData& data)
{
m_nCount++;
Update(data);
}
Linear LeastSquareMethod::GetTrendency()
{
return m_lnResult;
}
void LeastSquareMethod::Update(const LSMData& data)
{
if(m_nCount == 1)
{
m_fTotalX = data.x;
m_fTotalY = data.y;
m_lnResult.a = data.x;
m_lnResult.b = data.y;
return;
}
float prevAvrX = m_fTotalX / (m_nCount-1);
float prevAvrY = m_fTotalY / (m_nCount-1);
float curAvrX = (m_fTotalX + data.x) / m_nCount;
float curAvrY = (m_fTotalY + data.y) / m_nCount;
float deltaXavr = curAvrX-prevAvrX;
float deltaYavr = curAvrY-prevAvrY;
// 이전 값을 재활용해 LSM 전개
m_fDeltaXY = m_fDeltaXY - deltaXavr*m_fDeltaY - deltaYavr*m_fDeltaX
+ (m_nCount-1)*deltaXavr*deltaYavr // 상수
+ (data.x-curAvrX)*(data.y-curAvrY); // 상수
m_fDeltaXX = m_fDeltaXX - 2*deltaXavr*m_fDeltaX + deltaXavr*deltaXavr*(m_nCount-1)
+ (data.x-curAvrX)*(data.x-curAvrX);
m_lnResult.a = m_fDeltaXY / m_fDeltaXX;
m_lnResult.b = curAvrY - curAvrX*m_lnResult.a;
// 다음 계산을 위해 변수 Update
m_fTotalX += data.x;
m_fTotalY += data.y;
m_fDeltaX = m_fDeltaX - (curAvrX-prevAvrX)*(m_nCount-1) + data.x - curAvrX;
m_fDeltaY = m_fDeltaY - (curAvrY-prevAvrY)*(m_nCount-1) + data.y - curAvrY;
}
[main.cpp]
### cpp
#include <cmath>
#include "LeastSquareMethod.h"
#define FLOAT_EQ(x, y, t) (abs(x-y) < t)
int _tmain(int argc, _TCHAR* argv[])
{
NLeastSquareMethod nlsm;
LSMData example[] = {
{10, 71}, {20, 45}, {30, 24}, {40, 8}
};
int numOfData = sizeof(example)/sizeof(LSMData);
LeastSquareMethod lsm;
for(int i=0; i<numOfData; i++)
{
lsm.AddData(example[i]);
}
Linear lsmResult = lsm.GetTrendency();
printf("Answer >> \n");
printf("a : %.3f\tb : %.3f\n\n", -2.1f, 89.5f);
printf("Fast LSM >> [%s]\n", (FLOAT_EQ(-2.1f, lsmResult.a, 0.0001f) && FLOAT_EQ(89.5f, lsmResult.b, 0.0001f))?"Success" : "Failed");
printf("a : %.3f\tb : %.3f\n\n", lsmResult.a, lsmResult.b);
return 0;
}
글
들어가면서……
여러 모듈로 나누어진 프로젝트의 각 모듈 담당자라면 누구나 한번쯤은 DLL의 버전관리가 안돼서 곤란한 경우가 있을 것이다. 언제 빌드한 DLL인지 헷갈리곤 한다. 그렇다고 매번 빌드해서 커밋할 때 마다 Version 리소스를 수정하는 것도 귀찮고, 까먹으면 곤란한 일이 꼭 발생한다. 그래서 이 아티클에서는 자동으로 DLL의 버전을 수정하는 방법을 소개한다. 이 아티클에서는 Visual Studio 2005를 기준으로 설명하겠다.
시작!!
Auto Versioning Build는 다음과 같은 단계로 이루어진다.
1. [빌드 전] Version을 정의한 파일을 Update한다.
2. [빌드 중] 정의된 Version을 리소스 파일에 반영한다.
생각보다 단순하다. 지금부터 1번과 2번을 나누어 설명하도록 하겠다.
1. [빌드 전] Version을 정의한 파일을 Update한다.
2번을 가능하게 하려면, Version을 #define 구문을 이용해서 정의해야 한다. 필자는 다음과 같이 정의했다.
#define FILE_VERSION
3,0,806,2 #define PRODUCT_VERSION
3,0,0,0 #define STR_FILE_VERSION
"3,0,806,2\0" #define STR_PRODUCT_VERSION "3,0,0,0\0" |
버전을 나타내는 문자열은 다양한 것들이 있지만, 주로 빈번히 바뀔 파일 버전과 제품 버전만 정의하였다. 그리고 “STR_”로 시작하는 선언은 문자열 형태로 버전을 정의한 항목이다. 나중에 리소스파일을 열어보면 문자열로 주어야 하는 항목이 있기 때문이다.
이와 같이 작성한 파일을 [VersionInfo.h]하고 소스가 있는 프로젝트 폴더에 저장했다.
그 다음은 이 [VersionInfo.h]를 업데이트할 프로그램을 구현해야 한다. 필자는 버전을 다음과 같은 버전 정책을 사용하였다.
제품 버전의 맨 뒤, 두 자리는 0으로 고정.
제품 버전의 앞 두 자리는 파일 버전의 앞 두 자리와 동일
파일 버전의 세 번째 자리는 빌드 날짜
파일 버전의 네 번째 자리는 해당 날짜에 빌드한 횟수
예를 들어, 제품 버전이 3.0.0.0이고 오늘 날짜가 8월 6일이고, 빌드 횟수가 19이면 파일 버전은 3.0.806.19가 되는 것이다. 버전 정책은 사람마다, 회사마다 다르니까 입맛에 맞게 정책을 세우길 바란다.
이제, 본인이 세운 버전 정책에 맞게 [VersionInfo.h]를 업데이트 할 프로그램을 구현해야 한다. DLL의 버전 정책을 고민할 개발자라면 이 정도는 구현할 거라 믿는다. [Annex A]에 필자가 구현한 소스를 첨부한다. 참고하실 분은 참고하길 바란다(매우 단순 무식하게 구현하였음). 필자는 제품 버전과 파일 버전을 먼저 파싱하고, 이를 바탕으로 다음 버전을 업데이트 하도록 하였다. 그래서 개발자가 제품 버전의 앞 두 버전을 수정하면 이것이 자연스럽게 파일 버전에 적용되고, 빌드 횟수는 파일 버전의 맨 뒤 버전 +1을 하여 구하도록 하였다. 만약, 날짜를 나타내는 세 번째 버전 필드가 오늘 날짜와 다르면 네 번째 버전 필드를 1로 초기화 하도록 하였다.
다음은 [VersionInfo.h]가 버전 리소스에 참조가 되게끔 수정해보자.
2. [빌드 중] 정의된 Version을 리소스 파일에 반영한다.
Visual Studio 2005로 개발하면 아마 [(프로젝트명).rc]파일과 [res\(프로젝트명).rc2]라는 파일을 봤을 것이다. 두 파일 모두 리소스를 정의하는 파일이지만 열어보면 많이 다른 것을 알 수 있다.
먼저 [(프로젝트명).rc]를 살펴보자.
// Microsoft Visual C++
generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS //////////////////////////////////////////////////////////////////////////// // // Generated from the
TEXTINCLUDE 2 resource. // #include "afxres.h" … (중간 생략) … #if !defined(AFX_RESOURCE_DLL) ||
defined(AFX_TARG_KOR) #ifdef _WIN32 LANGUAGE 18, 1 #pragma code_page(949) #endif //_WIN32 #include "res\MMLayer.rc2" //
non-Microsoft Visual C++ edited resources #include "l.kor\afxres.rc" // Standard
components #endif /////////////////////////////////////////////////////////////////////////// #endif
// not APSTUDIO_INVOKED |
아마 파일이 이와 다를 수 있다. 어쨌든 맨 위를 보면 자동으로 생성되는 스크립트임을 나타내는 주석이 달려있다. 아래를 보니 “non-Microsoft Visual C++ edited resources” 라는 주석이 [res\(프로젝트명).rc2]에 달려 있는 것을 볼 수 있다. 즉 rc파일은 IDE에 의해서 자동으로 생성되는 파일이므로 수정하면 안되고, 개발자가 원하는 리소스는 rc2파일에 기록하는 것임을 알 수 있다. 그럼 이제 [res\(프로젝트명).rc2]를 열어보자.
// // MMLAYER.RC2 - resources Microsoft Visual C++ does not edit directly // #ifdef APSTUDIO_INVOKED #error this file is not editable by Microsoft
Visual C++ #endif //APSTUDIO_INVOKED ////////////////////////////////////////////////////////////////////////// // Add manually edited resources here... ////////////////////////////////////////////////////////////////////////// |
빙고!! 수동으로 리소스를 추가하려면 여기에 하라고 써있다. 그럼 이제 여기에 Version 리소스를 추가해보자. 가장 쉬운 방법은 rc파일에 있는 VS_VERSION_INFO로 시작하는 섹션을 복사/붙여넣기로 추가하거나 아래 코드를 복사하면 된다.
VS_VERSION_INFO VERSIONINFO FILEVERSION 1.0.0.0 PRODUCTVERSION 1.0.0.0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x4L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN
BLOCK "StringFileInfo"
BEGIN BLOCK "041204b0" BEGIN VALUE "CompanyName",
"Medison" VALUE
"FileDescription", "Version" VALUE "FileVersion",
“1.0.0.0” VALUE "InternalName",
"MMLayer.dll" VALUE "LegalCopyright",
"Copyright (C) 2010" VALUE
"OriginalFilename", "MMLayer.dll" VALUE "ProductName",
"Medison Ultrasound Equipment" VALUE "ProductVersion",
“1.0.0.0” END
END
BLOCK "VarFileInfo"
BEGIN VALUE "Translation", 0x412,
1200
END END |
천천히 읽어보면 대충 감이 올꺼다. 회사 이름, 파일 설명, 파일 버전, 내부 이름, 회사 이름 등등 IDE에서 우리가 삽입했던 이름들이다. 여기서 우리가 눈 여겨 봐야 할 부분은 아래 4가지이다.
FILEVERSION
PRODUCTVERSION
“FileVersion”
“ProductVersion”
이제 위 항목에 1.0.0.0으로 되어 있는 부분을 우리가 정의한 FILE_VERSION, PRODUCT_VERSION, STR_FILE_VERSION, STR_PRODUCT_VERSION을 대입해 주면 된다.
어떻게 하면 좋을까? 눈치 빠른 사람이라면 알 것이다. 자세히 보면, C++에 있는 전처리 명령어들이 있는 것을 볼 수 있다. 즉 맨 위에 우리가 만든 [VersionInfo.h]를 Include하고 1.0.0.0으로 되어 있는 부분을 적절한 define 항목으로 바꾸면 되는 것이다. 아래는 필자의 rc2파일이다.
// // MMLAYER.RC2 - resources Microsoft Visual C++ does not edit
directly // #include
"..\\VersionInfo.h" #ifdef APSTUDIO_INVOKED #error this file is not
editable by Microsoft Visual C++ #endif //APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // Add manually edited resources here... ///////////////////////////////////////////////////////////////////////////// VS_VERSION_INFO VERSIONINFO FILEVERSION FILE_VERSION PRODUCTVERSION PRODUCT_VERSION FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x4L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK
"StringFileInfo" BEGIN BLOCK
"041204b0" BEGIN VALUE
"CompanyName", "Medison" VALUE
"FileDescription", "Version" VALUE "FileVersion", STR_FILE_VERSION VALUE
"InternalName", "MMLayer.dll" VALUE
"LegalCopyright", "Copyright (C) 2010" VALUE "OriginalFilename",
"MMLayer.dll" VALUE
"ProductName", "Medison Ultrasound Equipment" VALUE
"ProductVersion", STR_FILE_VERSION END END BLOCK
"VarFileInfo" BEGIN VALUE
"Translation", 0x412, 1200 END END |
빨간색 부분이 필자가 수정한 부분이다. 이렇게 하면 리소스 파일을 컴파일 할 때, [VersionInfo.h] 파일을 참조해서 컴파일하게 된다.
3. IDE 설정하기
여기까지 했으면, 거의 다 했다. 이제, 빌드 하기 전에 [VersionInfo.h]를 업데이트하도록 우리가 1번에서 구현한 프로그램을 실행시키게끔 IDE에 설정하면 된다.
프로젝트 > 속성 > 구성속성 > 빌드 이벤트에 보면 세가지 이벤트가 있다.
빌드 전 이벤트
링크 전 이벤트
빌드 후 이벤트
각각은 이름만 봐도 언제 일어나는 이벤트인지 알 수 있을 것이다. 각각의 이벤트를 눌러보면 [명령줄]이란 항목이 있는데, 여기에 우리가 개발한 프로그램을 등록시키면 간단히 해결된다. 필자는 [DllVersion.exe]이라고 프로그램을 구현했으며, 소스가 있는 폴더에 함께 넣어놓았다. 다음은 설정하는 곳의 스크린샷이다.
필자는 Release로 빌드 했을 때만 버전 정보를 업데이트 하기 위해서 Release의 [빌드 전 이벤트]에 추가하였다. 이렇게 설정하고 빌드하면 자동으로 [VersionInfo.h]를 업데이트하고 빌드를 시작하게 된다.
끝내며……
비록 중간에 파일을 파싱하고 다시 출력하는 프로그램을 구현해야 하는 귀찮음이 있지만(물론 Annex A의 소스를 가져가면 덜 하겠지만…), 한번 해 놓으면 나중에 발생할 고생을 덜 하게 될 것이다. 한번쯤 해보면, 쉽게 다른 프로젝트에 적용 가능하니 시간 내서 해 보기를 권장한다.
Annex A
#include <stdio.h> #include <time.h> int main() {
FILE* version
= NULL;
fopen_s(&version,
"VersionInfo.h", "r");
if(version
== NULL)
{
printf("File
is not found. : VersionInfo.h\n");
return -1;
}
char bufFileVer[1024];
char bufProductVer[1024];
char bufStrFileVer[1024];
char bufStrProductVer[1024];
fgets(bufFileVer,
1024, version);
fgets(bufProductVer,
1024, version);
fclose(version);
int fileVer[4]
= {0, };
int productVer[4]
= {0, };
sscanf_s(bufFileVer,
"#define FILE_VERSION\t%d,%d,%d,%d",
&fileVer[0],
&fileVer[1], &fileVer[2], &fileVer[3]);
sscanf_s(bufProductVer, "#define
PRODUCT_VERSION\t%d,%d,%d,%d",
&productVer[0],
&productVer[1], &productVer[2], &productVer[3]);
fileVer[0] = productVer[0];
fileVer[1] = productVer[1];
productVer[2] = 0;
productVer[3] = 0;
tm today;
time_t now;
time(&now);
_localtime64_s(&today, &now);
int day
= (today.tm_mon
+ 1) * 100 + today.tm_mday;
if(day
!= fileVer[2])
{
fileVer[2] = day;
fileVer[3] = 1;
}
else
{
fileVer[3]++;
}
printf("
\n \n");
printf("=
MMLayer Version. =====================\n");
printf(" File
Ver.%5d,%5d,%5d,%5d\n",
fileVer[0],
fileVer[1], fileVer[2],
fileVer[3]);
printf(" Product Ver.%5d,%5d,%5d,%5d\n",
productVer[0],
productVer[1], productVer[2],
productVer[3]);
printf("========================================\n");
printf("
\n \n");
fopen_s(&version,
"VersionInfo.h", "w+");
if(version
== NULL)
{
printf("File
is not found. : VersionInfo.h\n");
return -1;
}
sprintf_s(bufFileVer,
"#define FILE_VERSION\t%d,%d,%d,%d\n",
fileVer[0],
fileVer[1], fileVer[2],
fileVer[3]);
sprintf_s(bufStrFileVer,
"#define
STR_FILE_VERSION\t\"%d,%d,%d,%d\\0\"\n",
fileVer[0],
fileVer[1], fileVer[2],
fileVer[3]);
sprintf_s(bufProductVer,
"#define PRODUCT_VERSION\t%d,%d,%d,%d\n",
productVer[0],
productVer[1], productVer[2],
productVer[3]);
sprintf_s(bufStrProductVer,
"#define STR_PRODUCT_VERSION\t\"%d, %d,%d,%d\\0\"\n",
productVer[0],
productVer[1], productVer[2],
productVer[3]);
fprintf_s(version,
"%s", bufFileVer);
fprintf_s(version,
"%s", bufProductVer);
fprintf_s(version,
"%s", bufStrFileVer);
fprintf_s(version,
"%s", bufStrProductVer);
fclose(version);
return 0; } |
글
명령어는 두가지 입니다.
set-daum-dic-key : 다음 오픈 API에 가셔서 사용자 키를 받으셔야 합니다. "오픈 API 사용자 등록" 이라는 메뉴를 누르셔서 사전 API 키를 발급받으시면 됩니다. 그래서 다음과 같이 입력하면 됩니다.
정상적으로 Key를 입력하지 않으면 dic 명령을 이용해 검색할 때 다음과 같이 나옵니다.
dic : 사전 검색은 Preview에서 최대 5개의 검색 결과를 보여주며, 엔터를 치면 검색 결과 화면이 새 탭으로 뜨게 됩니다. 다음 그림은 예제입니다.
버그나 건의사항은 댓글로 남겨주시거나 메일주시면 빠른 시간내에 반영하도록 하겠습니다.
글
글
TIP
1. SELECT에 조인을 잘 쓰자
2. MySQL 의 주요 SQL 문법 [ http://tinyurl.com/mqc7lk ] 참고 굉장히 자세함.
- SELECT
SELECT [테이블별칭].[컬럼] AS [별칭] FROM [테이블] AS [별칭], WHERE [조건] AND [컬럼] (NOT) IN (SELECT 쿼리) ORDER BY [컬럼] GROUP BY [컬럼];
- INSERT
INSERT INTO [테이블]( [컬럼], ) VALUES ( [값], );
- DELETE
DELETE FROM [테이블] WHERE [조건];
- UPDATE
UPDATE [테이블] SET([컬럼]=[값], ) WHERE [조건];
- 테이블 지우기
DROP TABLE [테이블]
- 테이블 만들기
CREATE TABLE sms4_long_send(
no bigint(20) not null auto_increment,
primary key(no),
user varchar(255),
sn_no varchar(100),
c_seq bigint(20),
c_no varchar(100),
time datetime,
msg text
);
- 컬럼 추가하기
ALTER TABLE [테이블] ADD ([컬럼] [자료형] [기본값], )
- 컬럼 삭제하기
ALTER TABLE [테이블] DROP COLUMN [컬럼];
- 컬럼 이름바꾸기
ALTER TABLE [테이블] RENAME COLUMN [OLD_컬럼] [NEW_컬럼];
- 행 개수세기
SELECT COUNT(*) AS [별칭] FROM [테이블] ;
- 결과 개수 제한하기
SELECT * FROM [테이블] LIMIT [시작], [개수];
jQuery로 작업하기 시리즈
jQuery 항목별 정리
jQuery <select>의 <option>바꾸기
스크롤바 색깔
explode("구분자", "문자열") : "문자열"에서 "구분자"가 있는 곳을 나누어 리턴(array)
ereg("정규식", "문자열") : "문자열"에 "정규식"에 해당하는 것이 있는지 리턴(bool)
iconv("from인코딩", "to인코딩", "문자열") : "from인코딩"으로 인코딩된 "문자열"을 "to인코딩"으로 인코딩하여 리턴(string)
str_replace("단어", "치환", "문자열") : "문자열"에서 "단어"를 "치환"으로 바꾸어 리턴(string)
base64_encode("문자열") : "문자열"을 base64로 인코딩하여 리턴(string)
chunk_split("문자열") : 일정한 길이로 문자열을 잘라주어 리턴(string). 폼메일 만들때 사용
urlencode("문자열") : "문자열"을 url 형태로 인코딩하여 리턴(string)
strtotime("문자열") : "문자열"을 날짜로 리턴(sec)
date("형식"[, "날짜"]) : 오늘의 날짜를 "형식"으로 리턴(string)하거나, "날짜"를 "형식"으로 리턴(string)
substr("문자열", "시작", "개수") : "문자열"을 "시작"에서 부터 "개수"만큼 잘라 리턴(string)
글
어휴 연구실 에어콘 고장나서 급히 컴퓨터 쿨러 떼어내서 만든 선풍기-_-
만들고 나니까 더 더워..ㅠ_ㅠ
글
- Natalie Cole
O is for the only one I see.
V is very very extraordinary.
E is even more than anyone that you adore can
Love, it's all that I can give to you.
Love is more that just a game for two.
Two in love can make it
Take my heart but please don't break it.
Love was made for me and you.
ya~ L is for the way you look at me.
and O is for the only one I see.
V is so very very extraordinary.
E is even more than any any any anyone that you adore can
Love, it's all that I can give to you.
oh~ Love is more that just a game for two.
Two in love can make it
Take my heart but please don't break it.
Love was made for me and you.
I'm giving giving ove that's made for me and you,
just Don't you know that love was made for me and you.
영석이형하고 정민이누나가 윤실누나 결혼식때 멋지게 부른 노래!! 완전 빠졌다~ > _<
RECENT COMMENT