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

测试结果:

C:\Users\L\Desktop\软件工程\wc\Release>wc.exe -c 1.cpp
字符数为:30
C:\Users\L\Desktop\软件工程\wc\Release>wc.exe -w 1.cpp
单词数为:10
C:\Users\L\Desktop\软件工程\wc\Release>wc.exe -l 1.cpp
行数为:13
C:\Users\L\Desktop\软件工程\wc\Release>wc.exe -a 1.cpp
空行数为:1
注释行数为:3
代码行数为:9
测试-d
测试结果:
C:\Users\L\Desktop\软件工程\wc\Release>wc.exe -d *.*
1.cpp
113.cpp
13.cpp
2.cpp
555     <目录>
main.cpp
wcclass.h
测试-s
测试结果:
1.cpp
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
 
 
总字符数为:1351
总单词数为:810
总行数为:417
 
代码覆盖率:100%
PSP

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

 项目总结
              这次项目让我感受最大的在于测试方面,之前写代码没有作过多的测试。这次学习到单元测试,代码覆盖率等方法和概念,可以应用到以后的程序开发中。其次,psp表也是一个新的概念,一开始估计时间都比较少,过于乐观,直到开发和测试阶段,很多没有想到的小问题让我卡住了很长一段时间,以至于实际时间比估计时间翻了三倍。最后是让我学会了先写好大致框架再实现,没有出现以前的边写边改,最好代码很紊乱的问题。我相信一个好的程序员是在开发中成长的,这次项目为我的开发之路开了个好头。

C++实现wc.exe程序的更多相关文章

  1. wc.exe程序

    1.gitHub地址:https://github.com/loveYuJun/wc.exe.git 2.PSP表格 psp2.1 Personal Software Process Stages 预 ...

  2. wc.exe指令(C++)

    https://github.com/kielingpao/wc 项目相关要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写一个命令行程序,模仿已有wc.ex ...

  3. 个人项目(WC.exe)(java)(基于图形界面)

    一.Github项目地址:https://github.com/Leungdc/ENhomework 二.PSP: PSP2.1 Personal Software Process Stages 预估 ...

  4. WC.exe【C】

    gitee传送门!!!(电脑打不开github,多次尝试未果,决定先用gitee存着先) 项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写一个命令行程序 ...

  5. 小白のjava实现wc.exe功能

    GitHub地址 项目完成情况 基本功能列表(已实现) wc.exe -c file.c     //返回文件 file.c 的字符数 wc.exe -w file.c    //返回文件 file. ...

  6. 模仿WC.exe的功能实现--node.js

    Github项目地址:https://github.com/102derLinmenmin/myWc WC 项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要 ...

  7. 软工作业1—java实现wc.exe

    github项目地址 https://github.com/liyizhu/wc.exe WC 项目要求 基本功能列表: wc.exe -c file.c     //返回文件 file.c 的字符数 ...

  8. 用c语言基本实现wc.exe功能

    网址:https://github.com/3216005214/wc.exe wc项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写一个命令行程序,模仿 ...

  9. java实现wc.exe

    Github地址:https://github.com/ztz1998/wc/tree/master 项目相关要求 实现一个统计程序,它能正确统计程序文件中的字符数.单词数.行数,以及还具备其他扩展功 ...

随机推荐

  1. MongoDB 数据查询

    数据查询 基本查询 方法find():查询 db.集合名称.find({条件文档}) 方法findOne():查询,只返回第一个 db.集合名称.findOne({条件文档}) 方法pretty(): ...

  2. testlink问题--linux环境下

    搭建testlink 时出现问题,相关解决办法: 1.Maximum Session Idle Time before Timeout 修改php.ini文件,修改成session.gc_maxlif ...

  3. CloseableHttpClient(二)

    package com.cmy.httpClient; import java.io.IOException; import org.apache.http.HttpEntity; import or ...

  4. Oracle完全卸载

      停用oracle服务:进入计算机管理,在服务中,找到oracle开头的所有服务,右击选择停止   在开始菜单中,找到Universal Installer,运行Oracle Universal I ...

  5. 对ubuntu初学感想

    感觉对ubuntu一头雾水...作为什么都不懂得小菜鸟,感觉以后还有很多要学习的.fighting

  6. oralce 存储过程、函数和触发器

    一.存储过程和存储函数 指存储在数据库中供所有用户程序调用的子程序叫存储过程.存储函数.   创建存储过程 用CREATE PROCEDURE命令建立存储过程. 语法: create [or repl ...

  7. jq给动态生成的标签绑定事件的几种方法

    经常遇到给动态生成的标签绑定事件不好用,自己简单测试总结了下,结论如下了: body> <!-- 下面是用纯动态方式生成标签 --> <div id="d2" ...

  8. 转载hibernate 的3种 状态 。。

    转自  http://huangtut.iteye.com/blog/261520  对我有帮助,所以收藏了 Hibernate三种状态的区分,以及save,update,saveOrUpdate,m ...

  9. windows10 装linux子系统

    http://blog.csdn.net/Yuxin_Liu/article/details/52347898 试了一下,下载太慢,就没继续用,可以用实验楼这个网来玩玩linux

  10. Devexpress VCL Build v2013 vol 13.2.5 发布

    支持xe6 了,但是承诺的功能在哪里? What's New in 13.2.5 (VCL Product Line)   New Major Features in 13.2 What's New ...