// 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. 03_Swift2基础之基本数据类型+相互转换

    1. 整数 整数就是没有小数部分的数字,比如`42`和`-23`.整数可以是`有符号`(正.负.零)或者`无符号`(正.零). Swift 提供了,,和位的有符号和无符号整数类型.这些整数类型和 C语 ...

  2. iOS之05-三大特性之封装

    本次主要学习面向对象的三大特性:封装.继承和多态中的封装 封装 1. 好处 降低耦合率 可重复调用类中的属性 提高安全性,外部不能随便修改变量的值,保证了数据的安全性 2. set方法 1.作用:提供 ...

  3. ASP.NET 操作Cookie详解 增加,修改,删除

    Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份而储存在用户本地终端上的数据(通常经过加密).定义于RFC2109.它是网景公司的前雇员Lou Montulli在1993年3 ...

  4. bzoj 1217 [HNOI2003]消防局的设立 Label:图论

    题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状 ...

  5. c++实现des算法

    程序分三部分,des头文件,des类实现,main函数调用. //panda //2013-4-13 //des //des.h class DES { private: //public: //明文 ...

  6. 【BZOJ】2212: [Poi2011]Tree Rotations

    题意 给一棵\(n(1 \le n \le 200000)\)个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少. 分析 可以发现如果交换非叶结点的左右子树,对子树内的交换无影响, ...

  7. linux系统中errno与error对照表

    1.使用了一个小程序输出所有的errno对应的error字符串,代码如下 #include <errno.h> void showError(int err){ printf(" ...

  8. AlertDialog使用时遇到问题

    1.其内de子控件高宽度为0? AlertDialog.Builder builder = new AlertDialog.Builder(StoryActivity.this); View view ...

  9. [LintCode] Sort Integers 整数排序

    Given an integer array, sort it in ascending order. Use selection sort, bubble sort, insertion sort ...

  10. Linux_linux中profile、bashrc、bash_profile之间的区别和联系(转)

    /etc/profile:此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行. 并从/etc/profile.d目录的配置文件中搜集shell的设置. 英文描述为: # /etc/p ...