CodeCount 统计源代码行数






4.43/5 (3投票s)
这是一个让人联想到 libc/libc++ 跨 GNU 和 WIN32 的 SLOC 控制台程序。
引言
CodeCount 是一个让人想起 80 年代 Linux 极客的控制台程序。如今,.NET 和 Visual Studio IDE 越来越臃肿,但为什么不尝试一下 libc 和 vim 呢?它基于 libc/libc++、GNU glibc 和 WIN32 库,因此需要考虑跨平台问题,更不用说跨平台编译到不同的 CPU 芯片组了。
最近,我研究了 Pete Becker 的 C++11 标准,Maximilien 建议的 :) 并编写了一些使用 g++ 4.4.5 和 Visual Studio 2010 编译的测试用例。但是 g++ 4.4.5 不支持 lambda,vs 2010 不支持 std::thread 库。
解析程序选项
GUI 开发者可能不再考虑 char *argv[]
了,但程序选项对控制台程序很有用。GNU libc 提供了 getopt,但原生 WIN32 没有,除非使用 Hans Dietrich 开发的 XGetopt。因此,我简单地使用 argv[1]
来指示目录或文件路径。
目录或文件
C# 开发者只需在 Visual Studio .Net 中输入一些源代码,它就会自动添加更多内容来检查文件路径属性。那么 GNU glibc 和 libc 呢?GNU libc 提供了 S_ISDIR 宏来显示文件类型,Windows 下有 GetFileAttributes
。
FIXME: GetFileAttributes(...) 返回 18(不在返回值列表中),路径变量为 D:\project\.svn。
/* GNU libc */
struct stat buf;
stat(path, &buf);
if (S_ISDIR(buf.st_mode))
printf("it is a directory\n");
else
printf("it is a file\n");
/* WIN32 */
switch (GetFileAttributes(path))
{
case -1:
printf("invalid file\n");
break;
case 18:
case FILE_ATTRIBUTE_DIRECTORY:
printf("it is a directory\n");
break;
default:
printf("it is a file\n");
break;
}
文件名
GNU libc 的 basename 和 WIN32 的 PathFindFileName 用于从文件路径中获取文件名。例如,/home/xzhai/hello.c 的文件名是 hello.c,C:\hello.c 的文件名也是 hello.c。
遍历目录
自定义 TreeView ActiveX 控制或 UserControl 可能会拖放到 CFormView 或 WinForm 中,然后只需编写一些代码来遍历目录。对于 GNU libc,有 opendir 和 readdir,WIN32 有 FindFirstFile 和 FindNextFile。
/* GNU libc */
DIR *dp;
struct dirent *ep;
dp = opendir(path);
while (ep = readdir(dp))
{
printf("%s\n", ep->d_name);
}
closedir(dp);
/* WIN32 */
WIN32_FIND_DATA FindData;
HANDLE hFind = INVALID_HANDLE_VALUE;
char buffer[MAX_PATH];
memset(buffer, 0, MAX_PATH);
sprintf(buffer, "%s\\*", path);
hFind = FindFirstFile(buffer, &FindData);
printf("%s\n", FindData.cFileName);
while (0 != FindNextFile(hFind, &FindData))
{
printf("%s\n", FindData.cFileName);
}
FindClose(hFind);
/* GNU libc */
void walkdir(char *path)
{
...
while (ep = readdir(dp))
{
if (is_dir(ep->d_name))
walkdir(ep->d_name);
}
}
该行包含代码还是注释?
需要删除不包含源代码或注释的行。
>ANSI C 方法
while ('\0' != *line)
{
/* If there is a character not blank nor enter */
if (32 != *line && '\n' != *line)
{
/* the line including code or comment */
}
line++;
}
/* there is no source code nor comment */
ISO C++ 方法
std::string::iterator iter;
// walk through the std::string with iterator refer to char
for (iter = obj_str.begin(); iter != obj_str.end(); iter++)
{
// If there is a character not blank nor enter
if (32 != *iter && '\n' != *iter)
{
return true;
}
}
return false;
C 中的面向对象日志
不仅 C++ 可以进行面向对象编程,还可以通过 typedef struct oop_t
在 C 中实现。
/* OOP in C */
typedef struct
{
int (*init)();
void (*cleanup)();
void (*write)(char *);
} log_t;
函数指针的初始化和清理行为类似于 C++ 中的构造函数和析构函数。
/* allocation for log_t* object */
log_t *log_init()
{
log_t *ret = NULL;
ret = malloc(sizeof(log_t));
/* given the funtion pointer address */
ret->init = &m_init;
ret->cleanup = &m_cleanup;
ret->write = &m_write;
return ret;
}
私有成员和操作
static FILE *m_fptr = NULL;
static int m_init();
static void m_cleanup();
static void m_write(char *log);
历史
2012-02-20 xzhai
- 修复 WIN32 中的 m_filetype 问题,使用 "D:\project\.svn" 路径变量时 GetFileAttributes(...) 返回 18。
2012-02-16 xzhai
- 修复 m_is_codefile 问题,以前的版本可能会将 BuildLog.htm 视为源代码。
- 简化 WIN32 中的 m_filename。
- 添加日志支持。