개발/C/C++
- 코드 페이지 정리 2012.03.07
- Visual Studio 6.0에 STLport 설치하기 2012.02.16
- 윈도우에서 컨트롤의 크기 조절 2009.04.22
- SHGetFolderPath()로 얻을 수 있는 특수 폴더 2009.03.04
- 파일 관리 함수들 2008.12.10
- warning 중 참조되지 않은 형식 매개 변수의 처리 2008.11.14
- 구글 C++ 스타일 가이드 2008.11.04
- 폴더에서 파일찾기 2008.11.01
- MAC Address 가져오기 2008.11.01
- 메모리 할당 후의 NULL 체크 2008.10.31
코드 페이지 정리
Visual Studio 6.0에 STLport 설치하기
2. 적당한 위치에 압축을 풀고 커맨드 창을 연다. (설명을 위해 c:\stlport 에 푼 것으로 가정함)
3. Visual C++ 6.0 이 설치된 디렉토리 (C:\Program Files\Microsoft Visual Studio\VC98\Bin) 에서 VCVARS32.BAT 를 입력해서 환경설정을 해준다.
C:\Program Files\Microsoft Visual Studio\VC98\Bin>VCVARS32.BAT
C:\Program Files\Microsoft Visual Studio\VC98\Bin>cd c:\stlport
C:\stlport>configure --help
C:\stlport>configure msvc6
C:\stlport>cd build\lib
C:\stlport\build\lib>nmake clean install
C:\stlport\build\lib>cd ..\test\unit
C:\stlport\build\test\unit>nmake clean install
- test\unit\ctype_facets_test.cpp 파일의 430 라인을 다음과 같이 변경한 후 다시 7을 수행한다.
CPPUNIT_ASSERT( ct.is(ctype_base::mask(ctype_base::print | ctype_base::lower | ctype_base::alpha), '?) );
CPPUNIT_ASSERT( ct.is(ctype_base::mask(ctype_base::print | ctype_base::lower | ctype_base::alpha), '?') );
참고 자료
- STLport의 빠른 설치 가이드
- Visual Studio 6.0에 STLport 5.2.1 설치
- STLport 설치 및 사용 For VC6
- STLport와 boost를 VS.NET 2005에서 사용하기
- Visual C++ 2005에서 STLport 5.1.0 빌드
윈도우에서 컨트롤의 크기 조절
내가 계속 MFC를 만지는 것이라면 항상 기억하겠지만 거의 만질일이 없다보니 계속 까먹어서...
정리해둬야지.
크기를 조절하는 데에는 4개의 함수가 쓰인다.
GetWindowRect() : 전제 화면을 기준으로 하는 위치. 즉 모니터의 좌측 상단이 (0,0) 이 된다.
GetClientRect() : 해당 윈도우의 그릴 수 있는 영역(클라이언트 영역이라고 함). 메모장이라면 텍스트를 입력하는 하얀 부분이 되겠다. 하얀 부분의 좌측 상단이 (0,0) 이 된다.
ScreenToClient() : WindowRect를 ClientRect로 바꿔주는 함수
MoveWindow() : 클라이언트 영역 내에서 윈도우(컨트롤)의 위치와 크기를 변경한다.
이 4가지를 이용하여 다음과 같이 컨트롤의 위치와 크기를 변경할 수 있다. 다음은 에디트 박스를 클라이언트 영역의 오른쪽에서 15, 아래에서 15만큼 떨어진 크기를 갖도록 하는 부분으로 OnSize에서 구현된 내용이다.
{
CFormView::OnSize(nType, cx, cy);
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
if(m_editLog.GetSafeHwnd() != NULL)
{
CRect editLogRect; // 에디트 박스의 영역
m_editLog.GetWindowRect(editLogRect); // 에디트 박스의 스크린 영역을 구함
// 에디트 박스의 스크린 영역을 CMyFormView 객체의 클라이언트 영역을 기준으로 변경
ScreenToClient(editLogRect);
CRect clientRect;
GetClientRect(clientRect); // CMyFormView 객체의 클라이언트 영역을 구함
editLogRect.right = clientRect.right - 15; // 클라이언트 영역의 오른쪽에 15픽셀의 공간을 둔다.
editLogRect.bottom = clientRect.bottom - 15; // 클라이언트 영역의 하단에 15픽셀의 공간을 둔다.
m_editLog.MoveWindow(editLogRect); // 에디트 박스의 수정된 위치를 적용함
}
}
이거 보고 이해가 안된다면 별 수 없다.
그림까지 넣어서 설명하면 훨씬 이해가 잘 되겠지만, 지금은 회사라... ㅡ_ㅡ;;
SHGetFolderPath()로 얻을 수 있는 특수 폴더
"CSIDL_DESKTOP {desktop}"
"CSIDL_INTERNET Internet Explorer (icon on desktop)"
"CSIDL_PROGRAMS Start Menu\Programs"
"CSIDL_CONTROLS My Computer\Control Panel"
"CSIDL_PRINTERS My Computer\Printers"
"CSIDL_PERSONAL My Documents"
"CSIDL_FAVORITES {user name}\Favorites"
"CSIDL_STARTUP Start Menu\Programs\Startup"
"CSIDL_RECENT {user name}\Recent"
"CSIDL_SENDTO {user name}\SendTo"
"CSIDL_BITBUCKET {desktop}\Recycle Bin"
"CSIDL_STARTMENU {user name}\Start Menu"
"CSIDL_DESKTOPDIRECTORY {user name}\Desktop"
"CSIDL_DRIVES My Computer"
"CSIDL_NETWORK Network Neighborhood"
"CSIDL_NETHOOD {user name}\nethood"
"CSIDL_FONTS windows\fonts"
"CSIDL_TEMPLATES"
"CSIDL_COMMON_STARTMENU All Users\Start Menu"
"CSIDL_COMMON_PROGRAMS All Users\Programs"
"CSIDL_COMMON_STARTUP All Users\Startup"
"CSIDL_COMMON_DESKTOPDIRECTORY All Users\Desktop"
"CSIDL_APPDATA {user name}\Application Data"
"CSIDL_PRINTHOOD {user name}\PrintHood"
"CSIDL_LOCAL_APPDATA {user name}\Local Settings\Application Data (non roaming)"
"CSIDL_ALTSTARTUP non localized startup"
"CSIDL_COMMON_ALTSTARTUP non localized common startup"
"CSIDL_COMMON_FAVORITES"
"CSIDL_INTERNET_CACHE"
"CSIDL_COOKIES"
"CSIDL_HISTORY"
"CSIDL_COMMON_APPDATA All Users\Application Data"
"CSIDL_WINDOWS GetWindowsDirectory()"
"CSIDL_SYSTEM GetSystemDirectory()"
"CSIDL_PROGRAM_FILES C:\Program Files"
"CSIDL_MYPICTURES C:\Program Files\My Pictures"
"CSIDL_PROFILE USERPROFILE"
"CSIDL_SYSTEMX86 x86 system directory on RISC"
"CSIDL_PROGRAM_FILESX86 x86 C:\Program Files on RISC"
"CSIDL_PROGRAM_FILES_COMMON C:\Program Files\Common"
"CSIDL_PROGRAM_FILES_COMMONX86 x86 Program Files\Common on RISC"
"CSIDL_COMMON_TEMPLATES All Users\Templates"
"CSIDL_COMMON_DOCUMENTS All Users\Documents"
"CSIDL_COMMON_ADMINTOOLS All Users\Start Menu\Programs\Administrative Tools"
"CSIDL_ADMINTOOLS {user name}\Start Menu\Programs\Administrative Tools" [출처] SHGetFolderPath()로 얻을 수 있는 특수 폴더|작성자 깜찍이
파일 관리 함수들
기본적인 파일 관리함수
int _access( const char *path, int mode );
파일을 엑세스 하기 전에 파일이 실제로 존재하는지 확인하는 함수입니다.
path : 조사할 파일의 경로
mode: 조사할 상태 지정 ( 0 은 존재, 2 는 쓰기, 4 는 읽기 )
return : 요청한 허가 상태를 가지면 0을 리턴, 그렇지 않으면 -1을 리턴
int remove( const char *path );
int _unlink( const char *filename );
위의 두 함수는 파일을 삭제 합니다.
path : 삭제하고자 하는 파일의 경로만 지정
int rename( const char *oldname, const char *newname );
이 함수는 파일의 이름을 변경합니다.
oldname : 변경하고자 하는 파일의 이름
newname : 새로 설정할 파일의 이름
int _chmod( const char *filename, int pmode );
파일의 속성을 변경 합니다.
pmode : _S_IWRITE , _S_IREAD 둘중 하나를 주거나 둘다 줄수도 있음
파일검색 함수
long _findfirst( char *filespec, struct _finddata_t *fileinfo );
위의 함수로 첫번째 파일 검색 합니다.
int _findnext( long handle, struct _finddata_t *fileinfo );
위의 함수로 조건이 일치하는 다음 파일을 찾을수 있습니다.
int _findclose( long handle );
위의 함수로 모든 검색이 완료된 후 검색 핸들을 닫아 줍니다.
디렉토리 관리 함수
int _chdir( const char *dirname );
현제 작업중인 디렉토리의 경로 변경
char *_getcwd( char *buffer, int maxlen );
현재 작업 디렉토리를 조사
int _mkdir( const char *dirname );
디렉토리 생성
int _rmdir( const char *dirname );
디렉토리 제거
void _splitpath( const char *path, char *drive, char *dir, char *fname, char *ext );
경로 관리 함수로서 4개의 구분자로 분리한다.
void _makepath( char *path, const char *drive, const char *dir, const char *fname
, const char *ext );
경로 관리 함수로서 분리되어 있는 구분자를 합친다.
디스크 관리 함수
int _getdrive( void );
int _chdrive( int drive );
위의 두 함수는 작업 드라이브를 조사하거나 변경한다.
출처 : http://kin.naver.com/detail/detail.php?d1id=1&dir_id=10104&eid=4nUPmPpSlArMwqppck/df6nNQlKLaqFi&qb=tfC3usXkuK4gu+jBpiDH1Lz2&pid=fg9d8doi5ThssvOkpoZsss--248289&sid=ST9Q0woyP0kAAEgIOOk
warning 중 참조되지 않은 형식 매개 변수의 처리
C++ 을 하다보면 절대(순수?) 가상함수를 사용하게 되는 경우가 많다.
그런데 절대 가상함수를 상위에 선언은 해놓고 하위에서는 사용하지 않게 되는 인자가 생길 수 있는데, 이 때 컴파일러에서 뿌려주는 warning을 어떻게 처리해야 될까?
먼저 Visual C++에서는 #pragma warning를 통해 처리할 수 있다. (C4100이 사용되지 않은 인자 warning)
#pragma warning(disable:4100)
// warning 생기는 코드
#pragma warning(default:4100)
이것은 상당히 괜찮은 방법이다. 적어도 Visual C++에서 만큼은 이 warning이 생기지 않도록 해준다.
이건 많은 사람들이 잘 알고 있는 방법이고, 검색해도 이것이 주로 나온다.
그런데 구글 C++ 코딩 스타일 가이드를 보니 이 절대 가상함수 인자에 대해 나온 부분이 있었는데, 내가 왜 이런걸 몰랐나 싶은 생각이 들었다 ㅋㅋ
음... 내가 잘못봤나...?
지금 찾아보니까 또 안 보이네... 다른데서 봤나?
여튼 그 내용은 이랬다.(이랬던것 같다... ㅡㅡ;)
"절대 가상함수를 구현한 함수에서 해당 인자가 사용되지 않을 경우 변수 이름을 쓰지 않는다."
변수 이름을 쓰지 않는 이유는 첫째로 떠오르는 게 함수에서 참조되지 않는다는 것을 명시적으로 표현하는 것이다. 인자의 이름이 없으니 쓸 수가 없지!
그리고 확실하지 않은 두번째 이유는 바로 warning!
난 저런 경우에 warning 잡기 위한 노가다를 많이 해봐서 그런지 딱 보니 이게 제일 궁금했다.
"변수 이름이 없으면 warning을 어떻게 출력하지? 출력 안하지 않을까? 구글도 그런것을 고려해서 결정한 내용이 아닐까?"
훗~ 역시 해보니 warning이 뜨지 않는다.
물론 컴파일러마다 다를수도 있겠지만, 적어도 #pragma보다는 더 범용적이고 라인낭비를 줄이는 일일테지.
하나 배웠다.
구글 C++ 스타일 가이드
폴더에서 파일찾기
#include <io.h>
// "C:\\SourceFolder\\*.*" 같은 형식의 pchFind
functionA(char* pchFind)
{
struct _finddata_t findData;
long find_seek = (long)_findfirst(pchFind, &findData );
while(-1 != find_seek)
{
if(strcmp(findData.name, ".") != 0 && strcmp(findData.name, "..") != 0)
{
// findData.name 에 파일이름으로 데이터 처리
}
}while(_findnext(find_seek, &findData) != -1);
_findclose(find_seek);
}
MAC Address 가져오기
정리 차원에서 쓴다.
MAC Address 가져오는 방법.
이것을 사용해서 Ethernet인 경우의 MAC address만 출력하는 소스.
급조한것이긴 하지만 개발중인 소스를 올릴수는 없지 않은가? ㅡㅡ;;
PrintToHex은 당연히 데이터를 HEX 로 찍는 함수다.
#include <IPHlpApi.h>
#pragma comment(lib, "iphlpapi.lib")
IP_ADAPTER_INFO*
GetNetworkAdaptersInfo()
{
DWORD dwBufLen = 0;
DWORD dwStatus = GetAdaptersInfo(NULL, &dwBufLen);
ASSERT(dwStatus == ERROR_BUFFER_OVERFLOW);
IP_ADAPTER_INFO* pAdapterInfo = (IP_ADAPTER_INFO*)malloc(dwBufLen);
dwStatus = GetAdaptersInfo(pAdapterInfo, &dwBufLen);
assert(dwStatus == ERROR_SUCCESS);
if(dwStatus != ERROR_SUCCESS)
{
free(pAdapterInfo);
return NULL;
}
return pAdapterInfo;
}
void main()
{
IP_ADAPTER_INFO* pAdaptersInfoList = GetNetworkAdaptersInfo();
IP_ADAPTER_INFO* pAdapterInfo = pAdaptersInfoList;
while(NULL != pAdapterInfo)
{
if(MIB_IF_TYPE_ETHERNET == pAdapterInfo->Type) // Ethernet == 6
{
PrintToHex(pAdapterInfo->Address, pAdapterInfo->AddressLength);
}
pAdapterInfo = pAdapterInfo->Next;
}
free(pAdaptersInfoList);
}
수정을 여기서 직접 해서 돌려보진 못했는데... 돌아가겠지? ㅡㅡ;
싸이 블로그 백업 [하zi 2008.09.18 14:20]
메모리 할당 후의 NULL 체크
C에서 동적할당은 다음과 같은 방법을 사용한다.
SMyStruct* pObject = (SMyStruct*) malloc(sizeof(SMyStruct));
if(pObject == NULL)
return;
그리고 C에서 C++로 옮긴 프로그래머들은 자연스럽게 다음과 같은 코드를 쓰는 사람이 많다.
CMyClass* pObject = new CMyClass();
if(pObject == NULL)
return;
나도 C를 하다가 C++를 배웠다. 물론 그 전에도 C++를 보긴 했었지만 내가 배우겠다는 의지를 갖고 본 것은 적어도 2년은 C프로그래머였던 때 이후다.
그래서 나 또한 위 코드에 대해 이상하다는 생각은 전혀 하지 못했다.
C++로 시작한 사람들은 왜 위의 코드가 잘못된 것인지 알까?