// CodeLines.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <Commdlg.h>
#include <Shlobj.h>
#include <map>
#include <vector>
#include <iostream>
#include <io.h>
#include <string>
#include <set>
#include <fstream>
#pragma comment(lib,"Shell32.lib") void InitValidTypes(std::set<std::string> &validTypes)
{
validTypes.insert(".h");
validTypes.insert(".cpp");
validTypes.insert(".c");
validTypes.insert(".hpp");
validTypes.insert(".py");
validTypes.insert(".txt");
validTypes.insert(".cs");
validTypes.insert(".css");
validTypes.insert(".js");
validTypes.insert(".lua");
validTypes.insert(".html");
validTypes.insert(".htm");
validTypes.insert(".java");
validTypes.insert(".bat");
validTypes.insert("makefile");
} int32_t WToChar(LPWSTR szWstr, char szCstr[], const int32_t chrLen)
{
int iLength = WideCharToMultiByte(CP_ACP, , szWstr, -, NULL, , NULL, NULL);
return WideCharToMultiByte(CP_ACP, , szWstr, -, szCstr, iLength, NULL, NULL);
} void OpenDirectoryDialog(HWND hWnd, char directoryPath[], const int32_t directoryPathLen)
{
TCHAR szBuffer[MAX_PATH] = { };
BROWSEINFO bi = { };
bi.hwndOwner = hWnd;//拥有着窗口句柄,为NULL表示对话框是非模态的,实际应用中一般都要有这个句柄
bi.pszDisplayName = szBuffer;//接收文件夹的缓冲区
bi.lpszTitle = TEXT("选择一个文件夹");//标题
bi.ulFlags = BIF_NEWDIALOGSTYLE;
BOOL ret = FALSE;
do{
LPITEMIDLIST idl = SHBrowseForFolder(&bi);
ret = SHGetPathFromIDList(idl, szBuffer);
if (!ret)
{
MessageBox(NULL, TEXT("请选择一个文件夹"), NULL, MB_ICONERROR);
}
else
{
//MessageBox(NULL, szBuffer, TEXT("你选择的文件夹"), 0);
WToChar(szBuffer, directoryPath, directoryPathLen);
}
} while (!ret);
} void GetFilesFromDirectory(std::vector<std::string> &files, const char *directoryPath)
{
struct _finddata_t fileinfo;
long hFile = ;
char tmpPath[MAX_PATH] = { };
sprintf_s(tmpPath, "%s\\*", directoryPath);
if ((hFile = _findfirst(tmpPath, &fileinfo)) == -){ return; }
do
{
if ((fileinfo.attrib & _A_SUBDIR))
{
if (strcmp(fileinfo.name, ".") != && strcmp(fileinfo.name, "..") != )
{
sprintf_s(tmpPath, "%s\\%s", directoryPath, fileinfo.name);
GetFilesFromDirectory(files, tmpPath);
}
}
else
{
sprintf_s(tmpPath, "%s\\%s", directoryPath, fileinfo.name);
files.push_back(tmpPath);
}
} while (_findnext(hFile, &fileinfo) == );
_findclose(hFile);
} void StringToLower(std::string &str)
{
for (uint32_t i = ; i < str.length(); ++i)
{
if (str[i] >= 'A' && str[i] <= 'Z')
{
str[i] = str[i] + 'a' - 'A';
}
}
} std::string GetFileExtention(const std::string &fileName)
{
std::string localFileName = fileName;
StringToLower(localFileName);
int pos = localFileName.find_last_of('.');
if (pos >= )
{
return localFileName.substr(pos);
}
return localFileName;
} void DumpFiles(const std::vector<std::string> &files)
{
for (uint32_t i = ; i < files.size() && i < ; ++i)
{
std::cout << files[i] << std::endl;
std::cout << GetFileExtention(files[i]) << std::endl;
}
std::cout << files.size() << std::endl;
} bool IfFileTypeValid(const std::string &fileExtention)
{
static std::set<std::string> validTypes;
if (validTypes.empty()){
InitValidTypes(validTypes);
}
return validTypes.find(fileExtention) != validTypes.end();
} uint32_t CalculateCharShowTimesInBuf(char buf[], const uint32_t len, char aim)
{
uint32_t i = ,counter = ;
while (i < len && buf[i] != '\0')
{
if (buf[i] == aim){ ++counter; }
++i;
}
return counter;
} uint32_t GetFileLines(const std::string &fileName)
{
const uint32_t maxBufLen = ;
static char buf[maxBufLen + ];
std::ifstream inFile(fileName, std::ios::in);
if (!inFile){ return ; }
uint32_t counter = ;
while (!inFile.eof())
{
memset(buf, , maxBufLen);
inFile.read(buf, maxBufLen);
//std::cout << buf;
counter += CalculateCharShowTimesInBuf(buf, maxBufLen, '\n');
}
return counter;
} void StatisticCodeLines(std::map<std::string, uint32_t> &codeLines, const std::string &directoryPath)
{
static std::vector<std::string> files;
files.clear();
GetFilesFromDirectory(files, directoryPath.c_str());
// DumpFiles(files);
for (const std::string &fileName : files)
{
std::string fileExtention = GetFileExtention(fileName);
if (!IfFileTypeValid(fileExtention)){ continue; }
codeLines[fileExtention] += GetFileLines(fileName);
}
} void PrintCodeLines(const std::map<std::string, uint32_t> &codeLines)
{
for (const std::pair<std::string, uint32_t> &p : codeLines)
{
printf("%-6s:%-8u\n", p.first.c_str(), p.second);
}
} int _tmain(int argc, _TCHAR* argv[])
{
char directoryPath[MAX_PATH] = { };
OpenDirectoryDialog(NULL, directoryPath, MAX_PATH);
std::cout << directoryPath << std::endl;
static std::map<std::string, uint32_t> codeLines;
codeLines.clear();
StatisticCodeLines(codeLines, directoryPath);
PrintCodeLines(codeLines);
getchar();
return ;
}

效果图:

C++ 一个统计文件夹下所有代码文件行数的小工具的更多相关文章

  1. 用Java实现将多级文件夹下的所有文件统一放到一个文件夹中

    每次下了电影(男生懂得呦),每部电影都放在一个单独的文件夹里,看的时候很是不方便啊,一直重复着进入文件夹.后退,再进.再退的操作,而手动把这些电影全部复制出来又太繁琐.因此为了解决这个问题,用IO写了 ...

  2. php 遍历一个文件夹下的所有文件和子文件

    php 遍历一个文件夹下的所有文件和子文件 <?php /** * 将读取到的目录以数组的形式展现出来 * @return array * opendir() 函数打开一个目录句柄,可由 clo ...

  3. Java基础面试操作题: File IO 文件过滤器FileFilter 练习 把一个文件夹下的.java文件复制到另一个文件夹下的.txt文件

    package com.swift; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File ...

  4. Java遍历一个文件夹下的全部文件

    Java工具中为我们提供了一个用于管理文件系统的类,这个类就是File类,File类与其它流类不同的是,流类关心的是文件的内容.而File类关心的是磁盘上文件的存储. 一,File类有多个构造器,经常 ...

  5. 读取指定文件夹下的全部文件,可通过正则进行过滤,返回文件路径数组 -- 基于node的一个函数

    var fs = require('fs'); // 模板文件夹路径 var templateDirectory = '../src'; //相对于当前文件的相对路径 //var templateDi ...

  6. Java——用程序编译一个文件夹下所有java文件到另一个文件夹下

    package com.java.test.a; import java.io.IOException; import java.util.ArrayList; import java.util.Ar ...

  7. GreenDao 数据库:使用Raw文件夹下的数据库文件以及数据库升级

    一.使用Raw文件夹下的数据库文件 在使用GreenDao框架时,数据库和数据表都是根据生成的框架代码来自动创建的,从生成的DaoMaster中的OpenHelper类可以看出: public sta ...

  8. C/C++不同文件夹下包含头文件的方法及#include的使用

    转自:http://blog.sina.com.cn/s/blog_6e0693f70100so42.html 本文主要介绍了如何不同文件夹下使用预处理器指示符#include. 假设我们有如下一个工 ...

  9. 递归输出文件夹下的所有文件的名称(转自 MSDN)

    问题:如何输出给定文件夹目录下面的所有文件的名称? C#代码: using System; using System.IO; namespace MyTest { public class Progr ...

随机推荐

  1. oracle调试存储过程

    跟着楼主一起来测试存储过程吧: 1.右键要测试的存储过程 出现如下提示框 2.填写参数 3.点击开始,如下操作 over,就是这么简单 -------------------------------- ...

  2. ural 1343. Fairy Tale

    1343. Fairy Tale Time limit: 1.0 secondMemory limit: 64 MB 12 months to sing and dance in a ring the ...

  3. awk 学习

    1. awk用例 今天用awk来统计一个字符出现的次数,总是比实际多一个.查了半天才发现问题所在. 文本tt.txt如下: <lst name="responseHeader" ...

  4. Java 动态代理

    被代理的接口特点: 1. 不能有重复的接口,以避免动态代理类代码生成时的编译错误. 2. 这些接口对于类装载器必须可见,否则类装载器将无法链接它们,将会导致类定义失败. 3. 需被代理的所有非 pub ...

  5. BZOJ 3170 & 切比雪夫距离

    题意: 给出N个点,在这N个点中选一个点使其它的点与这个点的切比雪夫距离和最小. SOL: TJOI真是...厚道还是防水...这种题目如果知道切比雪夫距离是什么那不就是傻逼题...如果不知道那不就懵 ...

  6. Android HttpURLConnection Post 参数 (https)

    声明utf-8: public static String CHARSET_UTF8 = HTTP.UTF_8; eg:登陆请求方法,通过接口返回结果: public static void logi ...

  7. 转:jQuery插件开发精品教程,让你的jQuery提升一个台阶

    要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台一样,得平台者得天下.苹果,微软,谷歌等巨头,都有各自的平台及生态圈 ...

  8. 【CodeVS】p1038 一元三次方程求解

    题目描述 Description 有形如:ax3+bx2+cx+d=0  这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d  均为实数),并约定该方程存在三个不同实根(根的范围在-100 ...

  9. BZOJ3105: [cqoi2013]新Nim游戏 博弈论+线性基

    一个原来写的题. 既然最后是nim游戏,且玩家是先手,则希望第二回合结束后是一个异或和不为0的局面,这样才能必胜. 所以思考一下我们要在第一回合留下线性基 然后就是求线性基,因为要取走的最少,所以排一 ...

  10. iOS 网络框架编写总结

    一,常用 1> 不错的处理接收到的网络图片数据的方法 id img= ISNSNULL(pic)?nil:[pic valueForKey:@"img"]; NSString ...