docstats.c
来自「一本已经绝版的好书」· C语言 代码 · 共 274 行
C
274 行
/*************************************************************
Module name: DocStats.C
Notices: Copyright (c) 1995-1997 Jeffrey Richter
*************************************************************/
#include "..\CmnHdr.H" /* See Appendix C. */
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
#include <stdio.h> // For sprintf
#include <string.h>
#include <process.h> // For _beginthreadex
#include "Resource.H"
//////////////////////////////////////////////////////////////
typedef enum {
STAT_FIRST = 0,
STAT_LETTERS = STAT_FIRST,
STAT_WORDS,
STAT_LINES,
STAT_LAST = STAT_LINES
} STATTYPE;
HANDLE g_hEventsDataReady[STAT_LAST - STAT_FIRST + 1];
HANDLE g_hEventsProcIdle[STAT_LAST - STAT_FIRST + 1];
BYTE g_bFileBuf[1024];
DWORD g_dwNumBytesInBuf;
// Forward reference
DWORD WINAPI StatThreadFunc(LPVOID lpvParam);
//////////////////////////////////////////////////////////////
BOOL DocStats(LPCTSTR pszPathname, PDWORD pdwNumLetters,
PDWORD pdwNumWords, PDWORD pdwNumLines) {
HANDLE hThreads[STAT_LAST - STAT_FIRST + 1];
HANDLE hFile;
DWORD dwThreadID;
STATTYPE StatType;
*pdwNumLetters = 0;
*pdwNumWords = 0;
*pdwNumLines = 0;
// Open the file for reading.
hFile = CreateFile(pszPathname, GENERIC_READ, 0,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
// File open failed.
chMB(__TEXT("File could not be opened."));
return(FALSE);
}
for (StatType = STAT_FIRST; StatType < STAT_LAST + 1;
StatType++) {
// Signaled when not processing buffer.
g_hEventsDataReady[StatType] =
CreateEvent(NULL, FALSE, FALSE, NULL);
g_hEventsProcIdle[StatType] =
CreateEvent(NULL, FALSE, TRUE, NULL);
// Create all the threads. Threads MUST be
// created AFTER the event objects.
hThreads[StatType] = chBEGINTHREADEX(NULL, 0,
StatThreadFunc, (PVOID) StatType, 0, &dwThreadID);
}
do {
// Wait for the worker threads to be idle.
WaitForMultipleObjects(STAT_LAST - STAT_FIRST + 1,
g_hEventsProcIdle, TRUE, INFINITE);
// Read part of the file into the global memory buffer.
ReadFile(hFile, g_bFileBuf, chDIMOF(g_bFileBuf),
&g_dwNumBytesInBuf, NULL);
// Signal the works that the data is ready.
for (StatType = STAT_FIRST; StatType < STAT_LAST + 1;
StatType++) {
SetEvent(g_hEventsDataReady[StatType]);
}
} while (g_dwNumBytesInBuf != 0);
// All the statistics for the file have been accumulated;
// time to clean up.
CloseHandle(hFile);
// Wait for all of the threads to return.
WaitForMultipleObjects(STAT_LAST - STAT_FIRST + 1,
hThreads, TRUE, INFINITE);
// Get the statistic from each thread
GetExitCodeThread(hThreads[STAT_LETTERS], pdwNumLetters);
GetExitCodeThread(hThreads[STAT_WORDS], pdwNumWords);
GetExitCodeThread(hThreads[STAT_LINES], pdwNumLines);
// Clean up the handles for all the threads
for (StatType = STAT_FIRST; StatType < STAT_LAST + 1;
StatType++) {
CloseHandle(hThreads[StatType]);
CloseHandle(g_hEventsDataReady[StatType]);
CloseHandle(g_hEventsProcIdle[StatType]);
}
return(TRUE);
}
//////////////////////////////////////////////////////////////
DWORD WINAPI StatThreadFunc(LPVOID lpvParam) {
STATTYPE StatType = (STATTYPE) lpvParam;
DWORD dwNumBytesInBuf, dwByteIndex, dwNumStat = 0;
BYTE bByte;
BOOL fInWord = FALSE, fIsWordSep;
do {
// Wait for the data to be ready.
WaitForSingleObject(g_hEventsDataReady[StatType],
INFINITE);
dwNumBytesInBuf = g_dwNumBytesInBuf;
dwByteIndex = 0;
for (; dwByteIndex < dwNumBytesInBuf; dwByteIndex++) {
bByte = g_bFileBuf[dwByteIndex];
// Note that this program works only on ANSI files
// regardless of whether the source code is compiled
// for ANSI or Unicode.
switch (StatType) {
case STAT_LETTERS:
if (IsCharAlphaA(bByte))
dwNumStat++;
break;
case STAT_WORDS:
fIsWordSep = (strchr(" \t\n\r", bByte) != NULL);
if (!fInWord && !fIsWordSep) {
dwNumStat++;
fInWord = TRUE;
} else {
if (fInWord && fIsWordSep)
fInWord = FALSE;
}
break;
case STAT_LINES:
if ('\n' == bByte)
dwNumStat++;
break;
}
}
// Data processed; signal that we are done.
SetEvent(g_hEventsProcIdle[StatType]);
} while (dwNumBytesInBuf > 0);
return(dwNumStat);
}
//////////////////////////////////////////////////////////////
BOOL Dlg_OnInitDialog (HWND hwnd, HWND hwndFocus,
LPARAM lParam) {
// Associate an icon with the dialog box.
chSETDLGICONS(hwnd, IDI_DOCSTATS, IDI_DOCSTATS);
// Initialize the dialog box by disabling all
// the nonsetup controls.
EnableWindow(GetDlgItem(hwnd, IDC_DODOCSTATS), FALSE);
return(TRUE);
}
/////////////////////////////////////////////////////////////
void Dlg_OnCommand (HWND hwnd, int id, HWND hwndCtl,
UINT codeNotify) {
TCHAR szPathname[_MAX_PATH];
OPENFILENAME ofn;
DWORD dwNumLetters, dwNumWords, dwNumLines;
switch (id) {
case IDC_FILENAME:
EnableWindow(GetDlgItem(hwnd, IDC_DODOCSTATS),
Edit_GetTextLength(hwndCtl) > 0);
break;
case IDC_FILESELECT:
chINITSTRUCT(ofn, TRUE);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szPathname;
ofn.lpstrFile[0] = 0;
ofn.nMaxFile = chDIMOF(szPathname);
ofn.lpstrTitle = __TEXT("Select file for reversing");
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
GetOpenFileName(&ofn);
SetDlgItemText(hwnd, IDC_FILENAME, ofn.lpstrFile);
SetFocus(GetDlgItem(hwnd, IDC_DODOCSTATS));
break;
case IDC_DODOCSTATS:
GetDlgItemText(hwnd, IDC_FILENAME, szPathname,
chDIMOF(szPathname));
if (DocStats(szPathname, &dwNumLetters, &dwNumWords,
&dwNumLines) ) {
SetDlgItemInt(hwnd, IDC_NUMLETTERS, dwNumLetters,
FALSE);
SetDlgItemInt(hwnd, IDC_NUMWORDS, dwNumWords,
FALSE);
SetDlgItemInt(hwnd, IDC_NUMLINES, dwNumLines,
FALSE);
}
break;
case IDCANCEL:
EndDialog(hwnd, id);
break;
}
}
/////////////////////////////////////////////////////////////
BOOL CALLBACK Dlg_Proc (HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
}
return(FALSE);
}
/////////////////////////////////////////////////////////////
int WINAPI _tWinMain (HINSTANCE hinstExe,
HINSTANCE hinstPrev, LPTSTR pszCmdLine, int nCmdShow) {
chWARNIFUNICODEUNDERWIN95();
DialogBox(hinstExe, MAKEINTRESOURCE(IDD_DOCSTATS),
NULL, Dlg_Proc);
return(0);
}
/////////////////////// End Of File ///////////////////////
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?