0x001 Programming/01. C | C++
[Example] 이진 검색 트리를 이용한 파일 정렬
KimSangLab
2017. 12. 29. 15:06
#include <windows.h> #include <tchar.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <malloc.h> #include <io.h> #include <process.h> #define KEY_SIZE 8 #define EMPTY _T ("") #define YES _T ("y") #define NO _T("n") #define CR 0x0D #define LF 0x0A #define TSIZE sizeof (TCHAR) #ifdef _UNICODE #define _tstrrchr wcsrchr #else #define _tstrrchr strrchr #endif #ifdef _UNICODE #define _tstrstr wcsstr #else #define _tstrstr strstr #endif #ifdef _UNICODE #define _memtchr wmemchr #else #define _memtchr memchr #endif #define GetExceptionCode _exception_code #define exception_code _exception_code #define GetExceptionInformation (struct _EXCEPTION_POINTERS *)_exception_info #define exception_info (struct _EXCEPTION_POINTERS *)_exception_info #define AbnormalTermination _abnormal_termination #define abnormal_termination _abnormal_termination unsigned long __cdecl _exception_code(void); void * __cdecl _exception_info(void); int __cdecl _abnormal_termination(void); typedef struct _TREENODE { struct _TREENODE *Left, *Right; TCHAR key[KEY_SIZE]; LPTSTR pData; } TREENODE, *LPTNODE, **LPPTNODE; #define NODE_SIZE sizeof( TREENODE ) #define NODE_HEAP_ISIZE 0x8000 #define DATA_HEAP_ISIZE 0x8000 #define MAX_DATA_LEN 0x1000 #define TKEY_SIZE KEY_SIZE * sizeof( TCHAR ) #define STATUS_FILE_ERROR 0xE0000001 VOID ReportError (LPCTSTR userMessage, DWORD exitCode, BOOL printErrorMessage); VOID ReportException (LPCTSTR userMessage, DWORD exceptionCode); DWORD Options (int argc, LPCTSTR argv [], LPCTSTR OptStr, ...); LPTNODE FillTree( HANDLE, HANDLE, HANDLE); BOOL Scan( LPTNODE ); int KeyCompare(LPCTSTR, LPCTSTR); BOOL InsertTree( LPPTNODE, LPTNODE ); int _tmain(int argc, LPTSTR argv[]) { HANDLE hIn = INVALID_HANDLE_VALUE, hNode = NULL, hData = NULL; LPTNODE pRoot; BOOL noPrint; CHAR errorMessage[0x100] = {0x0, }; int iFirstFile = Options( argc, argv, _T("n"), &noPrint, NULL); int iFile = 0; for( iFile = iFirstFile; iFile < argc; iFile ++ ) { __try { hIn = CreateFile( argv[iFile], GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if( hIn == INVALID_HANDLE_VALUE ) { RaiseException( STATUS_FILE_ERROR, 0, 0, NULL ); } __try { hNode = HeapCreate( HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE, NODE_HEAP_ISIZE, 0); hData = HeapCreate( HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE, DATA_HEAP_ISIZE, 0); pRoot = FillTree(hIn, hNode, hData); _tprintf(_T("Sorted file : %s \n"), argv[iFile]); Scan( pRoot ); } __finally { if( hNode != NULL ) { HeapDestroy( hNode ); } if( hNode != NULL ) { HeapDestroy( hData ); } hNode = NULL; hData = NULL; if( hIn != INVALID_HANDLE_VALUE ) CloseHandle(hIn); hIn = INVALID_HANDLE_VALUE; } } __except( (GetExceptionCode() == STATUS_FILE_ERROR || GetExceptionCode() == STATUS_NO_MEMORY) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) { _stprintf( errorMessage, _T("\n %s %s "), _T("sortBT error onfile : "), argv[iFile]); ReportError( errorMessage, 0, TRUE ); } } return 0; } LPTNODE FillTree (HANDLE hIn, HANDLE hNode, HANDLE hData) { LPTNODE pRoot = NULL, pNode; DWORD nRead, i; BOOL atCR; TCHAR dataHold[MAX_DATA_LEN]; LPTSTR pString; while (TRUE) { pNode = HeapAlloc (hNode, HEAP_ZERO_MEMORY, NODE_SIZE); pNode->pData = NULL; (pNode->Left) = pNode->Right = NULL; if (!ReadFile (hIn, pNode->key, TKEY_SIZE, &nRead, NULL) || nRead != TKEY_SIZE) return pRoot; atCR = FALSE; for (i = 0; i < MAX_DATA_LEN; i++) { ReadFile (hIn, &dataHold[i], TSIZE, &nRead, NULL); if (atCR && dataHold[i] == LF) break; atCR = (dataHold[i] == CR); } dataHold[i - 1] = _T('\0'); pString = HeapAlloc (hData, HEAP_ZERO_MEMORY, (SIZE_T)(KEY_SIZE + _tcslen (dataHold) + 1) * TSIZE); memcpy (pString, pNode->key, TKEY_SIZE); pString[KEY_SIZE] = _T('\0'); _tcscat (pString, dataHold); pNode->pData = pString; InsertTree (&pRoot, pNode); } return NULL; } BOOL InsertTree (LPPTNODE ppRoot, LPTNODE pNode) { if (*ppRoot == NULL) { *ppRoot = pNode; return TRUE; } if (KeyCompare (pNode->key, (*ppRoot)->key) < 0) InsertTree (&((*ppRoot)->Left), pNode); else InsertTree (&((*ppRoot)->Right), pNode); return TRUE; } int KeyCompare (LPCTSTR pKey1, LPCTSTR pKey2) { return _tcsncmp (pKey1, pKey2, KEY_SIZE); } static BOOL Scan (LPTNODE pNode) { if (pNode == NULL) return TRUE; Scan (pNode->Left); _tprintf (_T ("%s\n"), pNode->pData); Scan (pNode->Right); return TRUE; } DWORD Options (int argc, LPCTSTR argv [], LPCTSTR OptStr, ...) { va_list pFlagList; LPBOOL pFlag; int iFlag = 0, iArg; va_start (pFlagList, OptStr); while ((pFlag = va_arg (pFlagList, LPBOOL)) != NULL && iFlag < (int)_tcslen (OptStr)) { *pFlag = FALSE; for (iArg = 1; !(*pFlag) && iArg < argc && argv [iArg] [0] == _T('-'); iArg++) *pFlag = _memtchr (argv [iArg], OptStr [iFlag], _tcslen (argv [iArg])) != NULL; iFlag++; } va_end (pFlagList); for (iArg = 1; iArg < argc && argv [iArg] [0] == _T('-'); iArg++); return iArg; } VOID ReportException (LPCTSTR userMessage, DWORD exceptionCode) { if (lstrlen (userMessage) > 0) ReportError (userMessage, 0, TRUE); if (exceptionCode != 0) RaiseException ( (0x0FFFFFFF & exceptionCode) | 0xE0000000, 0, 0, NULL); return; } VOID ReportError (LPCTSTR userMessage, DWORD exitCode, BOOL printErrorMessage) { DWORD eMsgLen, errNum = GetLastError (); LPTSTR lpvSysMsg; _ftprintf (stderr, _T("%s\n"), userMessage); if (printErrorMessage) { eMsgLen = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errNum, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpvSysMsg, 0, NULL); if (eMsgLen > 0) { _ftprintf (stderr, _T("%s\n"), lpvSysMsg); } else { _ftprintf (stderr, _T("Last Error Number; %d.\n"), errNum); } if (lpvSysMsg != NULL) LocalFree (lpvSysMsg); } if (exitCode > 0) ExitProcess (exitCode); return; }
출처 : Windows 시스템 프로그래밍 윈도우즈 API 핵심 바이블