您的位置:首页 > 编程语言 > C语言/C++

用C++自制的源码统计工具

2016-10-07 00:20 197 查看
之前决定看LevelDB是因为码量少,而且注释多,据说就2W来行。

于是写个程序统计,自己心里有个数。

下面是运行结果:



要统计的文件格式可以根据自己指定的regex表达式来筛选。

你可以修改CodeScanner.cpp中静态数据成员CodeScanner::file_type的初始化值来改变你希望统计的文件格式!

通过调用CodeScanner::TotalFileInfoIn("你需要统计的文件的绝对路径")即可得出目录下文件的总行数。

详见main方法!!!

所有操作都是通过调用CodeScanner的静态方法来实施!下面介绍一下这个类静态方法的功能。

//这个函数递归统计目录树的信息,将信息存入类的静态公有成员DirectoryTree。

TotalFileInfoIn("你需要统计的源码所在路径")

//这个函数负责统计每个文件的总行数,并且写入到一个fFileLine_map中。

CountDirectoryFileLineNum();

//这函数根据前两个函数的操作结果,以一个目录树的形式的打印出来!每个文件夹或者文件后面都跟着文件行数统计!

PrintDirectoryTree()

#include "CodeScanner.h"
int main(void)
{
CodeScanner::TotalFileInfoIn("E:\\开源代码\\leveldb\\leveldb-master");
CodeScanner::CountDirectoryFileLineNum();
CodeScanner::PrintDirectoryTree();
return 0;
}


下面是CodeScanner.h成员:

#pragma once
#undef UNICODE
#include<windows.h>
#include<iostream>
#include<string>
#include<memory>
#include<map>
#include<vector>
#include<regex>
#include<fstream>
using namespace std;
class CodeScanner
{
public:
CodeScanner();
~CodeScanner();
static map<string,vector<string>>
TotalFileInfoIn(string path);
static void PrintDirectoryTree(
string pre_directory="",
string sub_directory=RootPath,
map<string,vector<string>>
dir_map=DirectoryTree);
static string RootPath;
static map<string, vector<string>> DirectoryTree;
static string file_type;
static map<string, int> FileLine_map;
static int CountDirectoryFileLineNum(string directory_name=RootPath);
private:
static int FileLine(string filename);
inline static string PrintLevel(int blank) {
string blankStr;
while (blank > 0)
{
blankStr.append(" ");
--blank;
}
return blankStr;
}
};


下面是CodeScanner.cpp:

你可以通过改变正则表达式来决定需要统计的文件格式!

#include "CodeScanner.h"

map<string, vector<string>> emptymap;
map<string, vector<string>>
CodeScanner::DirectoryTree=emptymap;

string CodeScanner::RootPath = "";

map<string, int> emptymap2 = { {"",0} };
map<string, int> CodeScanner::FileLine_map = emptymap2;

<span style="font-size:32px;">string CodeScanner::file_type=".+\\.(cpp|cxx|c|cc|h|md)$";</span>

CodeScanner::CodeScanner()
{
}

CodeScanner::~CodeScanner()
{
}

map<string,vector<string>>
CodeScanner::TotalFileInfoIn(string path)
{
if (!RootPath.length())
RootPath = path;
if (path.length() == 0)
return DirectoryTree;
WIN32_FIND_DATA FileInfo;
string FilePath;
HANDLE handle;
shared_ptr<char> CharPath;
CharPath.reset(new char[path.length() + 5]);
int index = 0;
for (auto perchar : path)
CharPath.get()[index++] = perchar;
CharPath.get()[index++] = '\\';
CharPath.get()[index++] = '*';
CharPath.get()[index++] = '.';
CharPath.get()[index++] = '*';
CharPath.get()[index] = '\0';
handle = FindFirstFile(CharPath.get(), &FileInfo);
if (handle == INVALID_HANDLE_VALUE)
return DirectoryTree;
do{
string subdirectory(FileInfo.cFileName);
if (FileInfo.dwFileAttributes
&FILE_ATTRIBUTE_DIRECTORY)
{
if (subdirectory != "."&&subdirectory != "..")
{
DirectoryTree[path].
push_back(subdirectory);
TotalFileInfoIn(path + "\\" + subdirectory);
}
}
else {
DirectoryTree[path].
push_back(subdirectory);
}
}while (FindNextFile(handle, &FileInfo));
CharPath.get();
return DirectoryTree;
}

void CodeScanner::PrintDirectoryTree(
string pre_directory,
string sub_directory,
map<string, vector<string>> dir_map)
{
string absoluteURL =
(pre_directory.length()==0?
pre_directory
:pre_directory+"\\")+sub_directory;
if (dir_map.find(absoluteURL)
== dir_map.end())
return;
cout << PrintLevel(pre_directory.length())<< sub_directory
<< ":" <<FileLine_map[absoluteURL]<<endl;
for (auto dir_content : dir_map[absoluteURL])
{
if (dir_map.find(absoluteURL+"\\"+dir_content)
== dir_map.end()) {
cout << PrintLevel(
absoluteURL.length()) <<
dir_content<<":->"<<
FileLine_map
[absoluteURL+"\\"+dir_content]<<
endl;
}else
PrintDirectoryTree(
absoluteURL,dir_content);
}
}

int CodeScanner::FileLine(string filename)
{
regex r(file_type,regex::icase);
smatch legalfile;
if (regex_search(filename, legalfile, r)) {
int filelinenum = 0;
string linecontent;
ifstream filereader(filename,ifstream::in);
if (filereader.good())
while (getline(filereader, linecontent))
++filelinenum;
filereader.close();
return filelinenum;
}
return 0;
}

int CodeScanner::CountDirectoryFileLineNum(
string directory_name)
{
if (DirectoryTree.find(directory_name)
== DirectoryTree.end())
FileLine_map[directory_name]=
FileLine(directory_name);
else {
string pre_directory = directory_name+"\\";
for (auto sub_directory :
DirectoryTree[directory_name])
FileLine_map[directory_name] +=
CountDirectoryFileLineNum(
pre_directory + sub_directory);
}
return FileLine_map[directory_name];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: