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 + -
显示快捷键?