C++实现wc.exe程序
github项目地址:https://github.com/insomniali/wc
- 基本功能
- wc.exe -c file 统计文件file的字符数 【实现】
- wc.exe -w file 统计文件file的词的数目 【实现】
- wc.exe -l file 统计文件file的行数 【实现】
- 扩展功能
- wc.exe -d file 递归显示目录下符合条件的文件 【实现】
- wc.exe -s file 递归统计目录下符合条件的文件的总字符,词和行数 【实现】
- wc.exe -a file 统计文件file的空白行,注释行,代码行 【实现】
- 高级功能
- wc.exe -x 图形化界面 【未实现】
设计思路
根据需求,程序主要功能可分为两部分,一是接收输入指令并解析,二是对文件执行指令所对照的操作。通过程序内置参数,再调用相应类方法即可满足需求。
字符统计函数:
定义:除转义字符,数字及字母外所有字符
方法:通过getline()获取一行数据,再由字符的ASCII码来判断
单词统计函数:
定义:“a-z”,"A-Z"组成的单个字母或多个连续字母组成的单词
方法:通过getline()获取一行数据,再由字符的ASCII码来判断,在统计完第一个字母后置continuectrl为真,直到统计到第一个不符合定义的字符
行数统计函数
定义:通过getline()判断,不为空则为有效行
方法:grtline()
空白,注释,代码行数统计函数
定义:
空白行:字符串长度为0或长度为1,字符为(;,{,})之一
注释行:以“{//”,“}//”,“;//”,“//”为字符串开头的行
代码行:除空白行,注释行以外所有行
方法:
空白行:用string.length()统计字符串长度,符合定义即为空白行
注释行:获取字符串前三位字符,根据结果是否符合定义判断
代码行:总行数减去空白行数及注释行数
架构图
设计了一个WCclass类,类成员变量是int类型的各种统计数据,类成员方法则是统计各种数据
代码说明
主函数main()
int main(int argc ,char* argv[]) {
string filepath = "C:\\Users\\L\\Desktop\\软件工程\\test"; //测试路径
string filename;
string temp;
string operateword;
string paramater=argv[];
WCclass * test=new WCclass();
for (int i = ; i < argc + ; i++)
{
temp = filepath;
filename = argv[i];
filename = temp + "\\" + filename;
test->fileoperate(filename, paramater);
}
detele test;
return ;
}
指令解析与文件操作函数()
void WCclass::fileoperate(string filename, string paramater)
{
ifstream fin(filename.c_str()); //获取文件名,打开输入流 char ch; //每次判断一个字符
string str; //保存行数据
char **strs; //保存字符串str以“ ”分割的字符串
//可输入参数类型
string paramater1 = "-c";
string paramater2 = "-w";
string paramater3 = "-l";
string paramater4 = "-d";
string paramater5 = "-s";
string paramater6 = "-a"; strs = (char**)malloc(sizeof(char) * ); while (getline(fin, str))
{
int strcount = ;
rowcount(); if ((str.length() == ) || ((str.length() == )&& (str[strcount] == (char)"{")) || ((str.length() == ) && (str[strcount] == (char)"}")))
{
emptyrowcount();
continue;
} strs[strcount] = strtok((char*)str.c_str(), " "); while (strs[strcount] != NULL)
{
strcount++;
strs[strcount] = strtok(NULL, " ");
} for (int i = ; i < strcount; i++)
{
string temp = strs[i];
int continuectrl = ;//控制单词连续
int dqmoff = ;//是否是;,{,}
int flag = ;////是否相邻
for (int j = ; j < temp.length(); j++)
{
ch = temp[j];
if ((ch >= && ch <= ) || (ch >= && ch <= ) || (ch >= && ch <= ) || (ch >= && ch <= ))
{
charcount();
continuectrl = ;
//注释行//的情况
if (ch == )
{
if (j == )
{
flag = ;
}
else if (j == )
{
if (flag == )
{
flag = ;
noterowcount();
}
}
}
//注释行({//,}//,;//)的情况
if ((ch == ) || (ch == ) || (ch == ))
{
if (j == ) {
dqmoff = ;
continue;
}
}
if (dqmoff == )
{
if (ch == )
{
if (flag == )
{
flag = ;
noterowcount();
}
else flag = ;
}
else
{
dqmoff = ;
}
} }
else if ((ch >= && ch <= ) || (ch >= && ch <= ))
{
if (continuectrl == )continue;
continuectrl = ;
wordcount();
}
else if (ch >= ''&&ch <= '')
{
digitcount();
}
else
{
cnwordcount();
}
}
}
}
if (paramater == paramater1)std::cout << "字符数为:" << charnums + cnwordnums / << endl;
else if (paramater == paramater2)std::cout << "单词数为:" << wordnums << endl;
else if (paramater == paramater3)std::cout << "行数为:" << rownums << endl;
else if (paramater == paramater4)listFiles(filename.c_str());
else if (paramater == paramater5)
{
filegroup = (string*)malloc(sizeof(string) * );
filegroup=listFiles(filename.c_str(), filegroup); //获取递归处理文件的文件名数组
for (int i = ; filegroup[i].length() != ; i++) {
std::cout << filegroup[i] << endl;
fileoperate(filegroup[i], paramater1);
fileoperate(filegroup[i], paramater2);
fileoperate(filegroup[i], paramater3);
}
std::cout << endl;
std::cout << "总字符数为:" << charnums + cnwordnums / << endl;
std::cout << "总单词数为:" << wordnums << endl;
std::cout << "总行数为:" << rownums << endl;
}
else if (paramater == paramater6)
{
std::cout << "空行数为:" << emptyrow << endl;
std::cout << "注释行数为:" << noterow << endl;
std::cout << "代码行数为:" << rownums-emptyrow-noterow << endl;
} fin.clear();
fin.close();
free(strs);
}
递归处理函数ListFiles()
void listFiles(const char * dir)
{
char dirNew[];
strcpy(dirNew, dir); intptr_t handle; //intptr_t是为了跨平台,其长度总是所在平台的位数,用来存放地址。
_finddata_t FileInfo; // _finddata_t 是用来存储文件各种信息的结构体。 handle = _findfirst(dirNew, &FileInfo); //第一个参数为文件名,可以用"*.*"来查找所有文件,也可以用"*.cpp"来查找.cpp文件。第二个参数是_finddata_t结构体指针。若查找成功,返回文件句柄,若失败,返回-1。
if (handle == -) // 检查是否成功
return; do
{
if (FileInfo.attrib & _A_SUBDIR) //如果文件是目录
{
if (strcmp(FileInfo.name, ".") == || strcmp(FileInfo.name, "..") == ) //如果文件名和当前目录和父目录相同则跳过,否则会只输出当前目录
continue; std::cout << FileInfo.name << "\t<目录>\n"; // 在目录后面加上"\\"和搜索到的目录名进行下一次搜索
strcpy(dirNew, dir);
strcat(dirNew, "\\");
strcat(dirNew, FileInfo.name); listFiles(dirNew);
}
else
std::cout << FileInfo.name << "\t" << "\n";
} while (_findnext(handle, &FileInfo) == ); //_findnext第一个参数为文件句柄,第二个参数同样为_finddata_t结构体指针。若查找成功,返回0,失败返回 - 1。 _findclose(handle); // 关闭搜索句柄
} std::string* listFiles(const char * dir,std::string* str)
{
char dirNew[];
strcpy(dirNew, dir);
int filenum = ;
std::string* temp = new std::string[];
int partcount = ;
std::string filepath;
char**filepathpart;
filepathpart = (char**)malloc(sizeof(char) * );
std::string filepathtemp = dir; intptr_t handle; //intptr_t是为了跨平台,其长度总是所在平台的位数,用来存放地址。
_finddata_t FileInfo; // _finddata_t 是用来存储文件各种信息的结构体。 handle = _findfirst(dirNew, &FileInfo); //第一个参数为文件名,可以用"*.*"来查找所有文件,也可以用"*.cpp"来查找.cpp文件。第二个参数是_finddata_t结构体指针。若查找成功,返回文件句柄,若失败,返回-1。
if (handle == -) // 检查是否成功
return nullptr; filepathpart[partcount] = strtok((char*)filepathtemp.c_str(), "\\"); while (filepathpart[partcount] != NULL)
{
partcount++;
filepathpart[partcount] = strtok(NULL, "\\");
} for (int i = ; i < partcount - ; i++) {
filepath += filepathpart[i] ;
filepath += "\\";
} do
{
if (FileInfo.attrib & _A_SUBDIR) //如果文件是目录
{
if (strcmp(FileInfo.name, ".") == || strcmp(FileInfo.name, "..") == ) //如果文件名和当前目录和父目录相同则跳过,否则会只输出当前目录
continue; std::cout << FileInfo.name << "\t<目录>\n"; // 在目录后面加上"\\"和搜索到的目录名进行下一次搜索
strcpy(dirNew, dir);
strcat(dirNew, "\\");
strcat(dirNew, FileInfo.name); listFiles(dirNew); }
else {
temp[filenum] = filepath;
temp[filenum] += FileInfo.name;
filenum++;
std::cout << FileInfo.name << "\t" << " \n";
}
} while (_findnext(handle, &FileInfo) == ); //_findnext第一个参数为文件句柄,第二个参数同样为_finddata_t结构体指针。若查找成功,返回0,失败返回 - 1。 _findclose(handle); // 关闭搜索句柄
return temp;
}
测试运行
测试-c,-w,-l,-a
测试文件:1.cpp
测试结果:
字符数为:30
单词数为:10
行数为:13
空行数为:1
注释行数为:3
代码行数为:9
1.cpp
113.cpp
13.cpp
2.cpp
555 <目录>
main.cpp
wcclass.h
113.cpp
13.cpp
2.cpp
main.cpp
C:\Users\L\Desktop\软件工程\test\1.cpp
字符数为:30
单词数为:20
行数为:39
C:\Users\L\Desktop\软件工程\test\113.cpp
字符数为:104
单词数为:52
行数为:75
C:\Users\L\Desktop\软件工程\test\13.cpp
字符数为:146
单词数为:85
行数为:111
C:\Users\L\Desktop\软件工程\test\2.cpp
字符数为:185
单词数为:114
行数为:141
C:\Users\L\Desktop\软件工程\test\main.cpp
字符数为:588
单词数为:581
行数为:417
总单词数为:810
总行数为:417
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
30 |
45 |
· Estimate |
· 估计这个任务需要多少时间 |
10 |
10 |
Development |
开发 |
100 |
300 |
· Analysis |
· 需求分析 (包括学习新技术) |
60 |
30 |
· Design Spec |
· 生成设计文档 |
20 |
20 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
20 |
100 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
20 |
10 |
· Design |
· 具体设计 |
10 |
10 |
· Coding |
· 具体编码 |
10 |
10 |
· Code Review |
· 代码复审 |
10 |
100 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
30 |
200 |
Reporting |
报告 |
10 |
30 |
· Test Report |
· 测试报告 |
10 |
30 |
· Size Measurement |
· 计算工作量 |
10 |
10 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 |
20 |
合计 |
380 |
925 |
C++实现wc.exe程序的更多相关文章
- wc.exe程序
1.gitHub地址:https://github.com/loveYuJun/wc.exe.git 2.PSP表格 psp2.1 Personal Software Process Stages 预 ...
- wc.exe指令(C++)
https://github.com/kielingpao/wc 项目相关要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写一个命令行程序,模仿已有wc.ex ...
- 个人项目(WC.exe)(java)(基于图形界面)
一.Github项目地址:https://github.com/Leungdc/ENhomework 二.PSP: PSP2.1 Personal Software Process Stages 预估 ...
- WC.exe【C】
gitee传送门!!!(电脑打不开github,多次尝试未果,决定先用gitee存着先) 项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写一个命令行程序 ...
- 小白のjava实现wc.exe功能
GitHub地址 项目完成情况 基本功能列表(已实现) wc.exe -c file.c //返回文件 file.c 的字符数 wc.exe -w file.c //返回文件 file. ...
- 模仿WC.exe的功能实现--node.js
Github项目地址:https://github.com/102derLinmenmin/myWc WC 项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要 ...
- 软工作业1—java实现wc.exe
github项目地址 https://github.com/liyizhu/wc.exe WC 项目要求 基本功能列表: wc.exe -c file.c //返回文件 file.c 的字符数 ...
- 用c语言基本实现wc.exe功能
网址:https://github.com/3216005214/wc.exe wc项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写一个命令行程序,模仿 ...
- java实现wc.exe
Github地址:https://github.com/ztz1998/wc/tree/master 项目相关要求 实现一个统计程序,它能正确统计程序文件中的字符数.单词数.行数,以及还具备其他扩展功 ...
随机推荐
- form表单重置、清空方法记录
myform 是form的id属性值 1.调用reset()方法 function fomrReset() { document.getElementById("myform"). ...
- gtftools软件简单介绍(我自己不建议用,因为我发现不好用)
1)背景 生物信息学研究经常涉及计算或提取基因的各种特征,如基因ID作图,GC含量计算和不同类型的基因长度,通过操纵基因模型,这些模型通常以GTF格式注释,可从ENSEMBL或GENCODE数据库获得 ...
- Easyui-datagrid显示时间的格式化代码
{field: 'Time', title: '时间', formatter: function (value, row, index) { var date = new Date(value); v ...
- VMware克隆CentOS网络配置
配置网络 如果是克隆CentOS的: vi /etc/udev/rules.d/70-persistent-net.rules 注释掉网络eth0,把最后一个改为eth0,记录下mac地址. vi / ...
- 【校招面试 之 C/C++】第13题 C++ 指针和引用的区别
1.指针和引用的定义和性质区别: (1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元:而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已.如: int ...
- Django基础教程
实例练习1-提交数据并展示 1.app_01下的views.py info_list=[] def userInfor(req): if req.method=="POST": u ...
- 注册带有Portal功能的DYN365_ENTERPRISE_PLAN1地址
使用官方进入的注册页面注册后试用,发现没有Portal功能. https://trials.dynamics.com/Dynamics365/Signup 使用以下的地址注册可以产生Portal ht ...
- db2 查看表空间使用率
1. 统计所有节点表空间使用率 select substr(TABLESPACE_NAME,1,20) as TBSPC_NAME,bigint(TOTAL_PAGES * PAGE_SIZE)/10 ...
- SECURITY_ATTRIBUTES 实现最低权限总结
SetSecurityDescriptorDacl函数可以用来设置DACL中的信息.如果一个DACL已经在security descriptor中存在,那么此DACL将被替换.值得注意的是MSDN中的 ...
- 如何处理好前后端分离的 API 问题(转载自知乎)
9 个月前 API 都搞不好,还怎么当程序员?如果 API 设计只是后台的活,为什么还需要前端工程师. 作为一个程序员,我讨厌那些没有文档的库.我们就好像在操纵一个黑盒一样,预期不了它的正常行为是什么 ...