个人项目作业--WC的实现
GitHub项目地址
https://github.com/1721819634/WC
1.Word Count 项目要求:
wc.exe 是一个常见的工具,它能统计文本文件的字符数、单词数和行数。这个项目要求写一个命令行程序,模仿已有wc.exe 的功能,并加以扩充,给出某程序设计语言源文件的字符数、单词数和行数。
实现一个统计程序,它能正确统计程序文件中的字符数、单词数、行数,以及还具备其他扩展功能,并能够快速地处理多个文件。
具体功能要求:
程序处理用户需求的模式为:
wc.exe [parameter] [file_name]
基本功能列表:
wc.exe -c file.c //返回文件 file.c 的字符数
wc.exe -w file.c //返回文件 file.c 的词的数目
wc.exe -l file.c //返回文件 file.c 的行数
扩展功能:
-s 递归处理目录下符合条件的文件。
-a 返回更复杂的数据(代码行 / 空行 / 注释行)。
空行:本行全部是空格或格式控制字符,如果包括代码,则只有不超过一个可显示的字符,例如“{”。
代码行:本行包括多于一个字符的代码。
注释行:本行不是代码行,并且本行包括注释。一个有趣的例子是有些程序员会在单字符后面加注释:
} //注释
在这种情况下,这一行属于注释行。
[file_name]: 文件或目录名,可以处理一般通配符。
高级功能:
-x 参数。这个参数单独使用。如果命令行有这个参数,则程序会显示图形界面,用户可以通过界面选取单个文件,程序就会显示文件的字符数、行数等全部统计信息。
需求举例:
wc.exe -s -a *.c ===> 返回当前目录及子目录中所有*.c 文件的代码行数、空行数、注释行数。
2.预计开发时间 PSP
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
5 |
|
· Estimate |
· 估计这个任务需要多少时间 |
10 |
|
Development |
开发 |
300 |
|
· Analysis |
· 需求分析 (包括学习新技术) |
45 |
|
· Design Spec |
· 生成设计文档 |
10 |
|
· Design Review |
· 设计复审 (和同事审核设计文档) |
0 |
|
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
10 |
|
· Design |
· 具体设计 |
120 |
|
· Coding |
· 具体编码 |
60 |
|
· Code Review |
· 代码复审 |
30 |
|
· Test |
· 测试(自我测试,修改代码,提交修改) |
120 |
|
Reporting |
报告 |
60 |
|
· Test Report |
· 测试报告 |
30 |
|
· Size Measurement |
· 计算工作量 |
20 |
|
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
10 |
|
合计 |
830 |
3.解题思路
编程语言:python
预计要学习的知识:I/O流、GUI图形编程、正则表达式
设计结构分析:
字符数、单词数、行数等都可以看做是从一个文本中可获得的属性,因此把他们的获得方法封装成一个类会很方便调用。最后设计一个主函数根据传入的命令调用他们。
遇到的困难:
由于之前对I/O流接触得比较少,在实现文件的读入时常发现如编码出错等小错误。对于python的GUI设计,现学现做,单是学习并搞懂基本操作就花了我挺多的时间。
在实现完基本功能去实现扩展功能的时候,比较烦恼如何不把代码设计得太繁杂。
4.设计实现过程
编写功能类,在初始化时需传入文件路径和命令符。每个功能对应类中的一个函数,除此之外还有一个主调用函数
函数功能如下:
chars_count: 实现计算文本字符个数的函数
lines_count:实现文本行数计数,返回代码行、注释行、空行以及总行数
words_count:实现文本单词计数
recur_files:用于递归处理文件目录。具体实现为获取传入路径所有的子文件,逐一判断个子文件是否为文件夹;若是文件夹则递归处理,否则调用主函数
主调用函数:根据命令符调用以上函数
GUI类:用于实现图形界面操作
函数调用关系:
5.代码说明
WC功能类
class WC:
def __init__(self, file_dict, order):
self.file_dict = file_dict
self.order = order # 计算字符个数
def chars_count(self, in_dict=None):
f_dict = self.file_dict if in_dict is None else in_dict
file = open(f_dict, mode='r', encoding='UTF-8')
chars = len(file.read())
file.close()
return chars # 计算行数
def lines_count(self, in_dict=None):
f_dict = self.file_dict if in_dict is None else in_dict
file = open(f_dict, mode='r', encoding='UTF-8')
read = file.readlines()
space_lines = 0 # 空行行数
code_lines = 0 # 代码行行数
comment_lines = 0 # 注释行行数
comment_flag = False # 注释行判断标志,用于判断多行注释
start_comment_line = 0 # 多行注释的起始位置
total_lines = 0 # 总行数
for line in read:
total_lines += 1
line = line.strip()
if not comment_flag:
if line.startswith('"""') or line.startswith("'''"):
comment_flag = True
start_comment_line = total_lines
elif line.startswith('#'):
comment_lines += 1
elif len(line) <= 1:
space_lines += 1
else:
code_lines += 1
else:
if line.endswith('"""') or line.endswith("'''"):
comment_flag = False
comment_lines += (total_lines - start_comment_line + 1)
file.close()
return [code_lines, comment_lines, space_lines, total_lines] # 计算词语数目
def words_count(self, in_dict=None):
f_dict = self.file_dict if in_dict is None else in_dict
file = open(f_dict, mode='r', encoding='UTF-8')
read = file.readlines()
words = [] # 存储单词,得到单词并且存入列表中 for line in read:
# 用空格代替一串非数字和字母
word = re.sub(r'[^0-9a-zA-Z\u4E00-\u9FFF]+', ' ', line) # 用空格代替一串非数字和字母
word = word.strip()
word = word.split(' ')
# 若该行为空或没有任何单词,word = ['']
if word != ['']:
words.extend(word)
file.close()
return len(words) def main_function(self, in_dict=None, in_oredr=None):
from gui import WcFrame as WF
f_dict = self.file_dict if in_dict is None else in_dict
order = self.order if in_oredr is None else in_oredr
is_file = False # 若目录不为文件,只能与'-s'搭配
if os.path.isfile(f_dict):
is_file = True
if order == '-c' and is_file:
charco = self.chars_count(f_dict)
print("字符数:", charco)
elif order == '-w' and is_file:
wordco = self.words_count(f_dict)
print("单词数:", wordco)
elif order == '-l' and is_file:
lineco = self.lines_count(f_dict)
print("总行数:", lineco[3])
elif order == '-a' and is_file:
lineco = self.lines_count(f_dict)
print("代码行行数:", lineco[0])
print("注释行数:", lineco[1])
print("空行数:", lineco[2])
elif order == '-s' and not is_file:
self.recur_files()
elif order == '-x':
app = wx.App()
frame = WF(None)
frame.Show()
app.MainLoop()
elif order == '-g' and is_file: # 输出全部信息
lineco = self.lines_count(f_dict)
print("字符数:", self.chars_count(f_dict))
print("单词数:", self.words_count(f_dict))
print("代码行行数:", lineco[0])
print("注释行数:", lineco[1])
print("空行数:", lineco[2])
print("总行数:", lineco[3])
else:
print("输入命令有误,请重新输入!") def recur_files(self, in_dict=None):
f_dict = self.file_dict if in_dict is None else in_dict
path_list = os.listdir(f_dict) # 获取当前目录下的文件名
result = []
result.extend(path_list)
for path in path_list:
new_dict = os.path.join(f_dict, path) # 将获取的文件名拼接到原目录后面,组成新目录
if os.path.isfile(new_dict): # 判断是否为文件
print('----------------')
print('文件', path)
self.main_function(new_dict, '-g')
else:
result.extend(self.recur_files(new_dict))
return result # 返回所有文件名,用于测试函数
GUI图形类
class WcFrame(wx.Frame):
def __init__(self, parent):
super(WcFrame, self).__init__(parent, title="Word Count", pos=(1000, 200), size=(500, 190))
self.path_test = wx.TextCtrl(self, pos=(5, 5), size=(350, 24))
self.open_button = wx.Button(self, label="打开", pos=(370, 5), size=(50, 24))
self.open_button.Bind(wx.EVT_BUTTON, self.OnOpenFile) # 绑定打开文件事件到open_button按钮上
# wx.TE_MULTILINE可以实现以滚动条方式多行显示文本,若不加此功能文本文档显示为一行
self.content_text = wx.TextCtrl(self, pos=(5, 39), size=(475, 100), style=wx.TE_MULTILINE)
self.cal_button = wx.Button(self, label="计算", pos=(430, 5), size=(50, 24))
self.cal_button.Bind(wx.EVT_BUTTON, self.word_count) def OnOpenFile(self, event): # 打开文件事件
wildcard = 'All files(*.*)|*.*'
dialog = wx.FileDialog(None, 'select', os.getcwd(), '', wildcard, wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
if dialog.ShowModal() == wx.ID_OK:
self.path_test.SetValue(dialog.GetPath())
dialog.Destroy def word_count(self, event):
wc = WC(self.path_test.GetValue(), '-g')
chars = wc.chars_count()
words = wc.words_count()
lines =wc.lines_count()
result = '字符数:{}, 单词数:{},代码行行数:{},注释行行数:{},空行行数:{} 总行数:{}'.format(chars, words, lines[0], lines[1], lines[2], lines[3])
self.content_text.SetValue(result)
6. 测试运行
程序实现功能
本程序实现了高级功能的支持通过图形界面选取文件;-c、-l、-w、-s指令以及-a的全部指令(为了方便测试,我多设计了一个输出全部结果的指令-g)
支持各种文本文档文件,
测试使用样例
import numpy as np
from sympy import *
from numpy import random
'''
this file is used to test wc. Here is the parameters
chars: 407
words: 75
code_lines: 11
space_lines: 1
comment_lines: 10
total_lines: 22
''' sst = random.randint(10, 30, size=(10, 10))
s = sst.ravel()
long = len(s)
mean = sum(s) / long
std = np.sqrt(sum((s - mean) ** 2 / long))
print(np.pi)
print(math.sqrt(4))
print(std)
# print(net)
测试过程
① 打开编译器,编译代码,弹出窗口
② 输入命令符和文件路径
③ -s命令测试
④ GUI测试
单元测试文件及结果
import unittest
from wc import WC class TestWC(unittest.TestCase):
def test_wc(self):
wc = WC('D:/PyC/Projects/WC/example/test.py', '-c')
self.assertEqual(wc.file_dict, 'D:/PyC/Projects/WC/example/test.py')
self.assertEqual(wc.order, '-c') def test_chars_count(self):
wc = WC('D:/PyC/Projects/WC/example/test.py', '')
chars = wc.chars_count()
self.assertEqual(chars, 407) def test_lines_count(self):
wc = WC('D:/PyC/Projects/WC/example/test.py', '')
lines = wc.lines_count()
self.assertEqual(lines[0], 11)
self.assertEqual(lines[1], 10)
self.assertEqual(lines[2], 1)
self.assertEqual(lines[3], 22) def test_words_count(self):
wc = WC('D:/PyC/Projects/WC/example/test.py', '')
words = wc.words_count()
self.assertEqual(words, 75) def test_recur_files(self):
test = ['1', 'test.py', 'test.txt', '1.txt', 'fish.py']
wc = WC('D:/PyC/Projects/WC/example', '')
result = wc.recur_files()
for i in range(len(test)):
self.assertEqual(result[i], test[i]) def test_main_function(self):
for order in ['-c', '-w', '-l', '-a', '-s', '-x', '-a', '-g', ' ']:
wc = WC('D:/PyC/Projects/WC/example/test.py', order)
wc.main_function() if __name__ == '__main__':
unittest.main()
7.实现完程序后,实际花费时间
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
5 |
6 |
· Estimate |
· 估计这个任务需要多少时间 |
10 |
8 |
Development |
开发 |
300 |
480 |
· Analysis |
· 需求分析 (包括学习新技术) |
45 |
120 |
· Design Spec |
· 生成设计文档 |
10 |
5 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
0 |
0 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
10 |
10 |
· Design |
· 具体设计 |
120 |
80 |
· Coding |
· 具体编码 |
60 |
80 |
· Code Review |
· 代码复审 |
30 |
35 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
120 |
150 |
Reporting |
报告 |
60 |
50 |
· Test Report |
· 测试报告 |
30 |
45 |
· Size Measurement |
· 计算工作量 |
20 |
30 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
10 |
15 |
合计 |
830 |
1114 |
8.项目小结
在开发项目前,以为这个程序并不会花很多时间。但在实际上手后发现并非如此。虽然花在代码实现的时间并没有那么多,但我
的时间大部分花在代码调试以及学习新知识上。由于开发经验并不是很多,我在开发前并没有很严格的进行需求分析和设计分析,
导致在添加功能的时候由于没搞清一些代码的关系而出现bug的情况。这让我重新审视了需求分析的重要性。在实现-x功能时,由
于时间关系我并没有做很好的优化,导致这功能任然要输入一个路径作为参数,算是一个缺陷。同时,在开发后期,我想到了更为
方便的设计结构,但由于代码已成型不便修改。这再次让我重新认识到的项目前分析的重要性。
个人项目作业--WC的实现的更多相关文章
- 个人项目作业WC(JAVA)
GitHub地址:https://github.com/1666403186/WC 一.题目描述 Word Count1. 实现一个简单而完整的软件工具(源程序特征统计程序).2. 进行单元测试.回归 ...
- 个人项目作业——wc.exe
一.Github项目地址 https://github.com/PIPIYing/wc 二.项目概况 项目描述 Word Count 1. 实现一个简单而完整的软件工具(源程序特征统计程序). 2. ...
- 个人项目作业WC
项目github地址 https://github.com/gs735028922gs/wordc 项目相关要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写 ...
- 个人项目作业(wc.exe)
1.GitHub项目地址 https://github.com/QiuBin666/WC 项目介绍: 题目描述 Word Count1. 实现一个简单而完整的软件工具(源程序特征统计程序).2. 进行 ...
- 个人项目作业-Word Count
个人项目作业 1.Github地址 https://github.com/CLSgGhost/SE_work 2.项目相关需求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数. ...
- 结对项目作业GUI
一.Coding.Net项目地址:https://git.coding.net/zhengsh589/CoupleProject.git 二.PSP表格(完成前): PSP 任务内容 计划共完成需要的 ...
- 个人项目作业$\cdot$求交点个数
个人项目作业\(\cdot\)求交点个数 一.作业要求简介 本次作业是北航计算机学院软件工程课程的个人项目作业,个人开发能力对于软件开发团队是至关重要的,本项目旨在通过一个求几何图形的交点的需求来使学 ...
- 【BUAA 软工个人项目作业】玩转平面几何
BUAA 软件工程个人项目作业 项目 内容 课程:2020春季软件工程课程博客作业(罗杰,任健) 博客园班级链接 作业:BUAA软件工程个人项目作业 作业要求 课程目标 学习大规模软件开发的技巧与方法 ...
- 【软工】个人项目作业——个人软件流程(PSP)
[软工]个人项目作业--个人软件流程(PSP) 项目 内容 班级:北航2020春软件工程 006班(罗杰.任健 周五) 博客园班级博客 作业:设计程序求几何对象的交点集合 个人项目作业 个人课程目标 ...
随机推荐
- Shell脚本常用命令整理
该笔记主要整理了一些常见的脚本操作命令,大致如下(持续补充中): 1. while.for循环 1. while.for循环 #!/bin/bash # while循环 v_start_date=${ ...
- BPMN开源工作流编辑器bpmn-js落地实践中文文档
BPMN是一套标准的业务流程建模符号规范,bpmn-js是基于此规范实现的一套渲染工具包和web建模器,可以实现拖拽生成工作流程图,效果大概如下 最近刚好用到,研究之后写了系列文章,分享给有需要的小伙 ...
- 记一次ceph的故障修复(20160408)
ceph的在正常运行的时候基本不会出现故障,出现故障一般在变动的时候,具体有下面几种可能出现的情形 软件升级 增加存储节点 减少存储节点 调整副本数目 调整pg数目 磁盘出现损坏 节点网络出现异常 以 ...
- mdtest测试工具
软件介绍 mdstest是软件的元数据操作基准测试工具,用来模拟对文件或者目录的open.stat.close操作,然后报告性能 下载软件压缩包: yum install openmpi openmp ...
- Nacos配置中心源码分析
1.使用 compile 'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-config:2.2.3.RELEASE' spring: app ...
- 使用FL Studio来制作停顿的效果
停顿效果是一种在音乐创作中非常常用的音效,它能起到缓冲的作用,而且能使这段旋律更具节奏感,在比较激情的歌曲中尤为常见.例如知名歌手王力宏演唱的<火力全开>中就使用了停顿效果,为歌曲加了不少 ...
- 文档丢失不用怕,EasyRecovery帮你一键恢复
我们在使用电脑的过程中,有时会因为各种原因,导致我们所写的文档丢失了.遇到这种情况,该怎么办呢? 下面,就给大家分享一下用EasyRecovery如何恢复被丢失的文档. 1.双击进入EasyRecov ...
- 教你调节Boom 3D的3D音效强度,让音乐更带感
Boom 3D的专业3D环绕技术,让用户能全身心地沉浸在立体音效中.无论是聆听音乐,还是观赏电影,立体音效都能为人们带来更加真实的听觉感触. 那么,Boom 3D的3D环绕功能到底能给用户带来怎样的体 ...
- 换系统之后为什么iMindMap会提示“许可证使用的次数过多”
iMindMap是一款十分受欢迎的思维导图软件,随着12版本的上线,iMindMap新增了很多新用户,最近小编发现有不少新用户在群里反映:"为什么购买iMindMap时说可以支持换机,但是在 ...
- synchronized关键字的内存语义
以下内容摘自:Java并发编程之美 加锁和释放锁的语义:当获取锁以后会清空锁块内本地内存中将会被用到的共享变量,在使用这些共享变量的时从主内存进行加载,在释放锁时将本地内存中修改的 共享变量刷新到主内 ...