65.9K
CodeProject 正在变化。 阅读更多。
Home

CodeCount 统计源代码行数

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.43/5 (3投票s)

2012 年 2 月 16 日

CPOL

2分钟阅读

viewsIcon

34039

downloadIcon

402

这是一个让人联想到 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。
  • 添加日志支持。
© . All rights reserved.