计算 C 或 C++ 代码的行数






3.40/5 (11投票s)
2005 年 12 月 29 日
2分钟阅读

80085

954
一篇关于统计代码行数的文章。
主窗口最初为 760x550(为文章而缩小)。
引言
这个程序只统计代码行数,但具有一些非常有用的功能。
- 我使用了 MFC 类
CFileFind
来递归地查找所选文件夹中的文件。 - 此版本识别的文件类型定义在
BOOL IsCplusplusFile(CString &lpszFileName)
中。 - 主窗口可以使用滚动条箭头或键盘按键(上、下、左、右、Home 和 End)滚动。
- 我使用了宏
_MSC_VER
进行条件编译,以便可以使用 VC++ 6.0 或 VC++ 8.0 编译代码。 - 主窗口居中显示在桌面上。
- 用户第一次运行程序时,浏览器将从项目目录启动。当程序退出时,上次选择的文件夹将保存到 ini 文件中,从而记住您上次的选择。
- 在程序会话期间,浏览器启动目录
m_szDirectory
会被更新并传递给函数CALLBACK BrowseCallbackProc(....);
。“浏览文件夹”对话框也在CALLBACK
函数中居中显示在桌面上。
背景
在 Microsoft Visual C++ 8.0 中,几个较旧的 C 函数被声明为已弃用;在大多数情况下,函数定义末尾添加了 _s
,并且函数内部需要一个 size_t
变量。
例如
// The char array is created on the stack. char title[10]; // should have been MAX_PATH. // VC++ 6.0 function. strcpy(title, "Open Dialog Box"); // strcpy(..); has no array bounds checking, the string literal is 16 bytes. // The next 6 bytes in stack are overwritten and the program crashes. // VC++ 8.0 function. strcpy_s(title, MAX_PATH, "Open Dialog Box"); // This will throw and exception in the Debug version and a Message Box // will be displayed. __________________________________________ [ Microsoft Visual Studio ] [------------------------------------------] [ ] [ Run-Time Check Failure #2 - Stack around ] [ the variable 'title' was corrupted. ] [ ] [ [ Break ] [ Continue ] ] [__________________________________________]
预定义宏 _MSC_VER
定义了编译器版本:对于 Microsoft Visual C++ 6.0 定义为 1200,对于 Microsoft Visual C++ 8.0 定义为 1400。
使用代码
- 查找文件夹中的所有文件
VOID GetFileNamesInDirectory(CString &lpszDirectory) { CFileFind finder; CString strFullPath; BOOL bWorking = FALSE; CString strWildcard(lpszDirectory); if (strWildcard.Right(1) != "\\") strWildcard += "\\*.*"; bWorking = finder.FindFile(strWildcard); while (bWorking) { bWorking = finder.FindNextFileA(); if (finder.IsDots()) continue; if (finder.IsDirectory()) { strFullPath = finder.GetFilePath(); GetFileNamesInDirectory(strFullPath); } else { strFullPath = finder.GetFilePath(); szaFiles.Add(strFullPath); } } finder.Close(); }
- 获取 C 或 C++ 文件类型
BOOL IsCplusplusFile(CString &lpszFileName) { char szExt[_MAX_EXT]; #if _MSC_VER < 1400 _splitpath(lpszFileName, NULL, NULL, NULL, szExt); #else _splitpath_s(lpszFileName, NULL, 0, NULL, 0, NULL, 0, szExt, _MAX_EXT); #endif if (!_stricmp(szExt, ".c") || !_stricmp(szExt, ".cpp")|| !_stricmp(szExt, ".dsp")|| !_stricmp(szExt, ".dsw")|| !_stricmp(szExt, ".h") || !_stricmp(szExt, ".hpp")|| !_stricmp(szExt, ".rc") || !_stricmp(szExt, ".vcproj")) { return TRUE; } return FALSE; }
- 键盘滚动
case WM_KEYDOWN: switch(wParam) { case VK_LEFT: SendMessage(hwnd, WM_HSCROLL, SB_LINELEFT, 0); break; case VK_RIGHT: SendMessage(hwnd, WM_HSCROLL, SB_LINERIGHT, 0); break; case VK_DOWN: SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0); break; case VK_UP: SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0); break; case VK_HOME: SendMessage(hwnd, WM_VSCROLL, SB_TOP, 0); break; case VK_END: SendMessage(hwnd, WM_VSCROLL, SB_BOTTOM, 0); break; } return 0;
- 条件编译
int GetNumberOfLinesInFile(CString &lpszFileName) { FILE *lpFile; int nNumberOfLines; #if _MSC_VER < 1400 lpFile = fopen(lpszFileName, "r"); #else errno_t ernum; ernum = fopen_s(&lpFile, lpszFileName, "r"); #endif nNumberOfLines = 0; if (lpFile != NULL) { char ch; do { ch = fgetc(lpFile); if (ch == '\n') { nNumberOfLines ++; } }while (ch != EOF); fclose(lpFile); } return nNumberOfLines; }
- 居中显示主窗口
void CenterWindow(HWND hwnd) { int x, y; HWND hwndDeskTop; CRect rcWnd, rcDeskTop; // Get a handle to the desktop window hwndDeskTop = ::GetDesktopWindow(); // Get dimension of desktop in a rect ::GetWindowRect(hwndDeskTop, &rcDeskTop); // Get dimension of main window in a rect ::GetWindowRect(hwnd, &rcWnd); // Find center of desktop x = rcDeskTop.Width() / 2; y = rcDeskTop.Height() / 2; x -= rcWnd.Width() / 2; y -= rcWnd.Height() / 2; // Set top and left to center main window on desktop ::SetWindowPos(hwnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE); }
- 保存上次选择的文件
case WM_DESTROY: WritePrivateProfileString("CountLinesApp", "DIRECTORY", m_szDirectory, szAppIniFile); PostQuitMessage (0) ; return 0 ; case WM_CREATE: GetCurrentDirectory(MAX_PATH, m_szDirectory); szAppIniFile = m_szDirectory; szAppIniFile += "\\CountLinesApp.ini"; dwNum = GetPrivateProfileString("CountLinesApp", "DIRECTORY", "C:\\", m_szDirectory, MAX_PATH, szAppIniFile); if (dwNum == 3) GetCurrentDirectory(MAX_PATH, m_szDirectory);
- 更新启动目录并居中显示窗口
int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM pData) { switch(uMsg) { case BFFM_INITIALIZED: { int x, y; HWND hwndDeskTop; CRect rc, rcDeskTop; // Get dimension of dlg window in a rect ::GetWindowRect(hwnd, &rc); // Get a handle to the desktop window hwndDeskTop = ::GetDesktopWindow(); // Get dimension of desktop in a rect ::GetWindowRect(hwndDeskTop, &rcDeskTop); // Find center of client x = rcDeskTop.Width() / 2; y = rcDeskTop.Height() / 2; x -= rc.Width() / 2; y -= rc.Height() / 2; // Set top and left to center dlg window on Desk Top SetWindowPos(hwnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE); LPCTSTR lpszPath = m_szDirectory; TCHAR szTemp[MAX_PATH]; if(lpszPath==NULL) { ::GetCurrentDirectory(MAX_PATH, szTemp ); lpszPath = szTemp; } // WParam is TRUE since you are passing a path. // It would be FALSE if you were passing a pidl. ::SendMessage(hwnd,BFFM_SETSELECTION,TRUE, (LPARAM)lpszPath); break; } case BFFM_SELCHANGED: { char szSelection[MAX_PATH]; if(!::SHGetPathFromIDList((LPITEMIDLIST)lParam, szSelection) || szSelection[1]!=':') { szSelection[0] = '\0'; ::SendMessage(hwnd, BFFM_ENABLEOK, 0, FALSE); } else { ::SendMessage(hwnd, BFFM_ENABLEOK, 0, TRUE); } ::SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szSelection); break; } default: break; } return 0; }
关注点
滚动条不会自动重绘,所以我添加了自己的消息处理程序。
#define WM_DRAW_BAR WM_USER + 1 case WM_DRAW_BAR: // Set vertical scroll bar range and page size si.cbSize = sizeof (si) ; si.fMask = SIF_ALL ; si.nMin = 0 ; si.nMax = nVMax ; si.nPage = nVPage; si.nPos = 0 ; si.nTrackPos = 0; SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ; // Set horizontal scroll bar range and page size si.cbSize = sizeof (si) ; si.fMask = SIF_ALL ; si.nMin = 0 ; si.nMax = nHMax ; si.nPage = nHPage ; si.nPos = 0 ; si.nTrackPos = 0; SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ; return 0;
历史
- 2005 年 12 月 29 日 - 版本 1.0。