《Windows系统编程》读后感(一)

简介:
 读了前5章,感触最深的是作者在例子程序中对UNICODE的考虑,另外就是将windows的API和UNIX进行对比,结合前段时间在看的《UNIX网络编程 卷2》,感觉对比性很强。
      印象最深刻的就是第5章的3个排序示例,将外部文件排序用内存来实现,堆,内存映射文件以及基准指针的使用让人大开眼见,不过比之《windows核心编程》还是有差距
#include "EvryThng.h"

#define KEY_SIZE 8

    /* Structure definition for a tree node. */

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)

LPTNODE FillTree (HANDLE, HANDLE, HANDLE);
BOOL Scan (LPTNODE);
int KeyCompare (LPCTSTR, LPCTSTR); iFile; /* for access in exception handler */
BOOL InsertTree (LPPTNODE, LPTNODE);

int _tmain (int argc, LPTSTR argv [])
{
    HANDLE hIn, hNode = NULL, hData = NULL;
    LPTNODE pRoot;
    BOOL NoPrint;
    CHAR ErrorMessage[256];
    int iFirstFile = Options (argc, argv, _T ("n"), &NoPrint, NULL);

    if (argc <= iFirstFile)
        ReportError (_T ("Usage: sortBT [options] files"), 1, FALSE);
                    /* Process all files on the command line. */
    for (iFile = iFirstFile; iFile < argc; iFile++) __try {
                    /* Open the input file. */
        hIn = CreateFile (argv [iFile], GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
        if (hIn == INVALID_HANDLE_VALUE)
            RaiseException (0, 0, 0, NULL);
                    /* Allocate the two heaps. */
        __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);
                    /* Process the input file, creating the tree. */
            pRoot = FillTree (hIn, hNode, hData);
                    /* Display the tree in Key order. */
            if (!NoPrint) {
                _tprintf (_T ("Sorted file: %s\n"), argv [iFile]);
                Scan (pRoot);
            } 
        } __finally { /* Heaps and file handle are always closed */
            /* Destroy the two heaps and data structures. */
            if (hNode != NULL) HeapDestroy (hNode);
            if (hNode != NULL) HeapDestroy (hData);
            hNode = NULL; hData = NULL;
            if (hIn != INVALID_HANDLE_VALUE) CloseHandle (hIn);
        }
    } /* End of main file processing loop and try block. */

    __except (EXCEPTION_EXECUTE_HANDLER) {
        _stprintf (ErrorMessage, _T("\n%s %s"), _T("sortBT error on file:"), argv[iFile]);
        ReportError (ErrorMessage, 0, TRUE);
    }
    return 0;
}

LPTNODE FillTree (HANDLE hIn, HANDLE hNode, HANDLE hData)

/* Scan the input file, creating a binary search tree in the
    hNode heap with data pointers to the hData heap. */
/* Use the calling program's exception handler. */
{
    LPTNODE pRoot = NULL, pNode;
    DWORD nRead, i;
    BOOL AtCR;
    TCHAR DataHold [MAX_DATA_LEN];
    LPTSTR pString;
                    /* Open the input file. */
    while (TRUE) {
        pNode = HeapAlloc (hNode, HEAP_ZERO_MEMORY, NODE_SIZE);
        pNode->pData = NULL;
        (pNode->Left) = pNode->Right = NULL;
                    /* Read the key. Return if done. */
        if (!ReadFile (hIn, pNode->Key, TKEY_SIZE,
                &nRead, NULL) || nRead != TKEY_SIZE)
                    /* Assume end of file on error. */
            return pRoot;    /* Read the data until the end of line. */
        AtCR = FALSE;         /* Last character was not a CR. */

        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] = '\0';

        /* DataHold contains the data without the key.
            Combine the Key and the Data. */

        pString = HeapAlloc (hData, HEAP_ZERO_MEMORY,
                (SIZE_T)(KEY_SIZE + _tcslen (DataHold) + 1) * TSIZE);
        memcpy (pString, pNode->Key, TKEY_SIZE);
        pString [KEY_SIZE] = '\0';
        _tcscat (pString, DataHold);
        pNode->pData = pString;
                /* Insert the new node into the search tree. */
        InsertTree (&pRoot, pNode);

    } /* End of while (TRUE) loop */
    return NULL; /* Failure */
}

BOOL InsertTree (LPPTNODE ppRoot, LPTNODE pNode)

/* Insert the new node, pNode, into the binary search tree, pRoot. */
{
    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)

/* Compare two records of generic characters.
    The key position and length are global variables. */
{
    return _tcsncmp (pKey1, pKey2, KEY_SIZE);
}

static BOOL Scan (LPTNODE pNode)

/* Scan and print the contents of a binary tree. */
{
    if (pNode == NULL)
        return TRUE;
    Scan (pNode->Left);
    _tprintf (_T ("%s\n"), pNode->pData);
    Scan (pNode->Right);
    return TRUE;
}


#include "EvryThng.h"

/* Definitions of the record structure in the sort file. */

#define DATALEN 56
#define KEY_SIZE 8

typedef struct _RECORD {
    TCHAR Key [KEY_SIZE];
    TCHAR Data [DATALEN];
} RECORD;

#define RECSIZE sizeof (RECORD)
typedef RECORD * LPRECORD;
int KeyCompare (LPCTSTR, LPCTSTR);

int _tmain (int argc, LPTSTR argv [])
{
    /* The file is the first argument. Sorting is done in place. */
    /* Sorting is done by file memory mapping. */

    HANDLE hFile = INVALID_HANDLE_VALUE, hMap = NULL;
    HANDLE hStdOut = GetStdHandle (STD_OUTPUT_HANDLE);
    LPVOID pFile = NULL;
    DWORD FsLow, Result = 2;
    TCHAR TempFile [MAX_PATH];
    LPTSTR pTFile;

    BOOL NoPrint;
    int iFirstFile;

    iFirstFile = Options (argc, argv, _T ("n"), &NoPrint, NULL);

    if (argc <= iFirstFile)
        ReportError (_T ("Usage: sortFL [options] files"), 1, FALSE);

_try {    /* try-except */
        /* Copy the input file to a temp output file that will be sorted.
            Do not alter the input file. */

    _stprintf (TempFile, _T ("%s%s"), argv [iFirstFile], _T (".tmp"));

    CopyFile (argv [iFirstFile], TempFile, TRUE);

    Result = 1;     /* tmp file is new and should be deleted. */

        /* Open the file (use the temporary copy). */

    hFile = CreateFile (TempFile, GENERIC_READ
            | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

    if (hFile ==INVALID_HANDLE_VALUE)
        ReportException (_T ("File open failed."), 2);

        /* Get file size.
            If the file is too large, catch that when it is mapped. */

    FsLow = GetFileSize (hFile, NULL);

    if (FsLow == 0) { /* There is nothing to sort */
        CloseHandle (hFile);
        return 0;    /* You might want to put out an informational message */
    }
        /* Create a file mapping object.
            Use the file size but add space for the null character. */

    hMap = CreateFileMapping (hFile, NULL, PAGE_READWRITE, 0, FsLow + TSIZE, NULL);
    if (hMap == NULL)
        ReportException (_T ("Create File map failed."), 3);

    pFile = MapViewOfFile (hMap, FILE_MAP_ALL_ACCESS, 0, 0 /* FsLow + TSIZE */, 0);
    if (pFile == NULL) 
        ReportException (_T ("MapView failed"), 4);

        /* Now sort the file.
            Perform the sort with the C library - in mapped memory. */

    qsort (pFile, FsLow / RECSIZE, RECSIZE, KeyCompare);

        /* Print out the entire sorted file. Treat it as one single string. */

    pTFile = (LPTSTR) pFile;
    pTFile [FsLow/TSIZE] = '\0';
    if (!NoPrint)
        PrintMsg (hStdOut, pFile);

        /* Indicate successful completion. */

    Result = 0;              
    ReportException (EMPTY, 5); /* Force an exception to clean up. */
    return 0;
} /* End of inner try-except. */

_except (EXCEPTION_EXECUTE_HANDLER) {

    /* Catch any exception here. Indicate any error.
        This is the normal termination. Delete the temporary
        file and Free all the resources. */

    if (pFile != NULL)
        UnmapViewOfFile (pFile);
    if (hMap != NULL)
        CloseHandle (hMap);
    if (hFile != INVALID_HANDLE_VALUE)
        CloseHandle (hFile);
    if (Result != 2)
        DeleteFile (TempFile);
    return Result;
}
} /* End of _tmain */

/*  CODE FROM HERE TO END IS NOT INCLUDED IN TEXT. */

int KeyCompare (LPCTSTR pKey1, LPCTSTR pKey2)

/* Compare two records of generic characters.
    The key position and length are global variables. */
{
    return _tcsncmp (pKey1, pKey2, KEY_SIZE);
}



#include "EvryThng.h"

int KeyCompare (LPCTSTR, LPCTSTR);
DWORD CreateIndexFile (DWORD, LPCTSTR, LPTSTR);
DWORD_PTR KStart, KSize;    /* Key start position & size (TCHAR). */
BOOL Revrs;

int _tmain (int argc, LPTSTR argv [])
{
    /* The file is the first argument. Sorting is done in place. */
    /* Sorting is done by file memory mapping. */

    HANDLE hInFile, hInMap;    /* Input file handles. */
    HANDLE hXFile, hXMap;    /* Index file handles. */
    HANDLE hStdOut = GetStdHandle (STD_OUTPUT_HANDLE);
    BOOL IdxExists, NoPrint;
    DWORD FsIn, FsX, RSize, iKey, nWrite, *pSizes;
    LPTSTR pInFile = NULL;
    LPBYTE pXFile = NULL, pX; 
    TCHAR _based (pInFile) *pIn;
    TCHAR IdxFlNam [MAX_PATH], ChNewLine = '\n';
    int FlIdx;

        /* Determine the options. */

     FlIdx = Options (argc, argv, _T ("rIn"), &Revrs, &IdxExists, &NoPrint, NULL);
    if (FlIdx >= argc)
        ReportError (_T ("No file name on command line."), 1, FALSE);

/* Step 1: Open and Map the Input File. */

    hInFile = CreateFile (argv [FlIdx], GENERIC_READ | GENERIC_WRITE,
            0, NULL, OPEN_EXISTING, 0, NULL);
    if (hInFile == INVALID_HANDLE_VALUE)
        ReportError (_T ("Failed to open input file."), 2, TRUE);

        /* Create a file mapping object. Use the file size. */

    hInMap = CreateFileMapping (hInFile, NULL, PAGE_READWRITE, 0, 0, NULL);
    if (hInMap == NULL)
        ReportError (_T ("Failed to create input file mapping."), 3, TRUE);
    pInFile = MapViewOfFile (hInMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    if (pInFile == NULL)
        ReportError (_T ("Failed to map input file."), 4, TRUE);

        /* Get the file size.
            As the mapping succeeded, the file size is less than 2 GB. */

    FsIn = GetFileSize (hInFile, NULL);

        /* Create the index file name. */

    _stprintf (IdxFlNam, _T ("%s%s"), argv [FlIdx], _T (".idx"));

/* Steps 2 and 3, if necessary. */

    if (!IdxExists)
        RSize = CreateIndexFile (FsIn, IdxFlNam, pInFile);

/* Step 4. Map the index file. */

    hXFile = CreateFile (IdxFlNam, GENERIC_READ | GENERIC_WRITE,
            0, NULL, OPEN_EXISTING, 0, NULL);
    if (hXFile == INVALID_HANDLE_VALUE)
        ReportError (_T ("Failed to open existing index file."), 5, TRUE);

        /* Create a file mapping object. Use the file size. */

    hXMap = CreateFileMapping (hXFile, NULL, PAGE_READWRITE, 0, 0, NULL);
    if (hXMap == NULL)
        ReportError (_T ("Failed to create index file mapping."), 6, TRUE);
    pXFile = MapViewOfFile (hXMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);    
    if (pXFile == NULL)
        ReportError (_T ("Failed to map index file."), 7, TRUE);
    FsX = GetFileSize (hXFile, NULL);

    /* Get the key size/key start and adjust the file size for the
        KeySize/KeyStart fields. Compute the record size from the key size. */

    pSizes = (LPDWORD)pXFile; KSize = *pSizes; 
    KStart = *(pSizes + 1);
    FsX -= 2 * sizeof (DWORD); 

/* Step 5. Sort the index file using qsort. */

    if (!IdxExists)
        qsort (pXFile + 2 * sizeof (DWORD), FsX / RSize, RSize, KeyCompare);

/* Step 6. Output the input file in sorted order. */

        /* Point to the address of the input file string.
            Start in the Input file. */

    pX = pXFile + 2 * sizeof (DWORD) + RSize - sizeof (LPTSTR);

    if (!NoPrint)
    for (iKey = 0; iKey < FsX / RSize; iKey++) {        
        WriteFile (hStdOut, &ChNewLine, TSIZE, &nWrite, NULL);

            /* The cast on pX is important, as it is a pointer to a
                byte and we need the four bytes of a based pointer. */
        pIn = (TCHAR _based (pInFile)*) *(DWORD_PTR *) pX;
        
        while ((*pIn != CR || *(pIn + 1) != LF) && (SIZE_T) pIn < (SIZE_T)FsIn) {
            WriteFile (hStdOut, pIn, TSIZE, &nWrite, NULL);
            pIn++;
        }
        pX += RSize;
     }

    /* Done. Free all the handles and maps. */

    UnmapViewOfFile (pInFile);
    CloseHandle (hInMap);
    CloseHandle (hInFile);
    UnmapViewOfFile (pXFile);
    CloseHandle (hXMap);
    CloseHandle (hXFile);
    return 0;
}
    
DWORD CreateIndexFile (DWORD FsIn, LPCTSTR IdxFlNam, LPTSTR pInFile)

/* Perform Steps 2-3 as defined in program description. */
/* This step will be skipped if the options specify use of an existing index file. */
{
    HANDLE hXFile;
    TCHAR _based (pInFile) *pInScan = 0;
    DWORD nWrite;

    /* Step 2a: Create an index file.
        Do not map it yet as its length is not known. */

    hXFile = CreateFile (IdxFlNam, GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
    if (hXFile == INVALID_HANDLE_VALUE)
        ReportError (_T ("Failure to create index file."), 8, TRUE);
    
    /* Step 2b: Get the first key and determine key size and start. */

    KStart = (DWORD_PTR) pInScan;
                /* Computed start of key field. */
    while (*pInScan != ' ' && *pInScan != '\t') pInScan++;
                /* Computed end of key field */

    KSize = ((DWORD_PTR) pInScan - KStart) / TSIZE;

        /* Computed key field size in characters. */

    /* Step 2c. Step 3. Scan the complete file, writing keys
        and record pointers to the key file. */
    /* The eight bytes contain the Key Size/Key Start.
        This is necessary so that we can re-use the index file. */

    WriteFile (hXFile, &KSize, sizeof (DWORD), &nWrite, NULL);
    WriteFile (hXFile, &KStart, sizeof (DWORD), &nWrite, NULL);
    pInScan = /*(TCHAR _based (pInFile)*)*/0;
    while ((DWORD_PTR) pInScan < FsIn) {
        WriteFile (hXFile, pInScan + KStart, KSize * TSIZE, &nWrite, NULL);
        WriteFile (hXFile, &pInScan, sizeof (LPTSTR), &nWrite, NULL);
        while ((DWORD) (DWORD_PTR)pInScan < FsIn && ((*pInScan != CR)
                || (*(pInScan + 1) != LF))) {
            pInScan++; /* Skip to end of line. */
        }
        pInScan += 2; /* Skip past CR, LF. */
    }
    CloseHandle (hXFile);
            /* Size of an individual record. */
    return KSize * TSIZE + sizeof (LPTSTR);
}

int KeyCompare (LPCTSTR pKey1, LPCTSTR pKey2)

/* Compare two records of generic characters.
    The key position and length are global variables. */
{
    DWORD i;
    TCHAR t1, t2;
    int Result = 0;
    for (i = 0; i < KSize && Result == 0; i++) {
        t1 = *pKey1;
        t2 = *pKey2;
        if (t1 < t2)
            Result = -1;
        if (t1 > t2)
            Result = +1;
        pKey1++;
        pKey2++;
    }
    return Revrs ? -Result : Result;
}



本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/06/05/1214717.html,如需转载请自行联系原作者

目录
相关文章
|
5月前
|
消息中间件 C++ Windows
02 MFC - Windows 编程模型
02 MFC - Windows 编程模型
22 0
|
6月前
|
监控 编译器 API
[笔记]Windows核心编程《二十二》注入DLL和拦截API(一)
[笔记]Windows核心编程《二十二》注入DLL和拦截API
143 0
|
1天前
|
API C++ Windows
windows编程入门_链接错误的配置
windows编程入门_链接错误的配置
6 0
|
2月前
|
Windows
火山中文编程 -- 第一个windows程序
火山中文编程 -- 第一个windows程序
12 0
|
2月前
|
编译器 API Windows
windows编程基础
windows编程基础
13 0
|
2月前
|
Windows
win32编程 -- windows绘图操作
win32编程 -- windows绘图操作
20 0
|
6月前
|
C++ Windows
[笔记]Windows核心编程《番外篇》几种常见的执行命令行方法
[笔记]Windows核心编程《番外篇》几种常见的执行命令行方法
|
3月前
|
网络协议 Linux C语言
005.在Windows下编程让效率起飞
windows开发Linux方式: 先用编辑器编写源代码 然后进入Linux 系统,使用gcc编译器(后面会讲),对源代码进行编译运行。 熟练后推荐使用VS2019 开发Linux C++ 程序 将自己的Ip地址设为静态IP
40 1
|
4月前
|
人工智能 机器人 C#
Windows编程课设(C#)——基于WPF和.net的即时通讯系统(仿微信)
一款参考QQ、微信的即时通讯软件。采用CS结构,客户端基于.Net与WPF开发,服务端使用Java开发。
|
6月前
|
消息中间件 Ubuntu 编译器
Windows编程
Windows编程
31 0