github地址

https://github.com/Pryriat/Word_Counter

项目说明

  • 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 返回更复杂的数据(代码行 / 空行 / 注释行)。

空行:本行全部是空格或格式控制字符,如果包括代码,则只有不超过一个可显示的字符,例如“{”。

代码行:本行包括多于一个字符的代码。

注释行:本行不是代码行,并且本行包括注释。一个有趣的例子是有些程序员会在单字符后面加注释:

} //注释

在这种情况下,这一行属于注释行。

[filename]:文件或目录名,可以处理一般通配符。

  • 高级功能:

-x 参数。这个参数单独使用。如果命令行有这个参数,则程序会显示图形界面,用户可以通过界面选取单个文件,程序就会显示文件的字符数、行数等全部统计信息。

  • 需求举例:

      wc.exe -s -a *.c

    返回当前目录及子目录中所有*.c 文件的代码行数、空行数、注释行数。

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 10 20
Estimate 估计这个任务需要多少时间 10 20
Development 开发 300 340
Analysis 需求分析 (包括学习新技术) 30 60
Design Spec 生成设计文档 10 10
Design Review 设计复审 (和同事审核设计文档) 0 0
Coding Standard 代码规范 (为目前的开发制定合适的规范) 0 0
Design 具体设计 20 20
Coding 具体编码 100 110
Code Review 代码复审 40 40
Test 测试(自我测试,修改代码,提交修改) 100 100
Reporting 报告 50 80
Test Report 测试报告 10 10
Size Measurement 计算工作量 10 10
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 30 60
合计 360 440

解题思路描述

设计实现过程

代码说明

控制台输入输出

#coding = UTF-8
from wc_class import word_counter
from ui_class import wc_ui
import argparse
import sys
from PyQt5.QtWidgets import *
from PyQt5.Qt import *
from PyQt5.QtGui import *
from PyQt5.QtCore import * opt = {}
if len(sys.argv) == 1:
sys.argv.append('-h')# 如果未输入参数,则自动添加执行-h
parser = argparse.ArgumentParser(description='Word_Counter by Chenobyl',add_help=True)
parser.add_argument('-c',help='character counts',action="store_true")
parser.add_argument('-w',help='word counts',action="store_true")
parser.add_argument('-l',help='line counts',action="store_true")
parser.add_argument('-a',help='extra informations',action="store_true")
parser.add_argument('-s',help='match files',action="store_true")
parser.add_argument('-x',help='',action="store_true")
parser.add_argument('-f',default=None,help='input file')
args = parser.parse_args()#参数提取
for x,y in args._get_kwargs():
opt[x]=y
a = word_counter(opt)
if opt['x']:
app = QApplication(sys.argv)
u = wc_ui()
u.show()
sys.exit(app.exec())
elif opt['s']:
a.file_select()
else:
a.file_process(opt['f'])

文件统计类

#coding = UTF-8
import re
import codecs
import getopt
import sys
import glob class word_counter:
def __init__(self,opt):#用于存储文件统计结果的属性
self.char_num = 0
self.word_num = 0
self.lines = 0
self.nullline = 0
self.single_comment = 0
self.multi_comment = 0
self.code_line = 0
self.is_null = False
self.file = ''
self.opt=opt def isnull(self,string):
'''
判断文件是否为空
'''
null_pattern = re.compile('.|\s')#判断文件是否有字符
tmp_result = null_pattern.findall(string)
if len(tmp_result) == 0:
return True
return False def char_count(self,string):
'''
文件字符数统计
'''
return len(string) def word_count(self,string):
'''
文件单词数统计
'''
word_pattern = re.compile('\S+\s?')#匹配模式:非空白+空白=单词
tmp_result = word_pattern.findall(string)
return len(tmp_result) def line_count(self,string):
'''
文件行数统计、空行统计与代码行统计
'''
null_line = 0
code_line = 0
sepcial_pattern = re.compile('.*\n?')
tmp_result = sepcial_pattern.findall(string)
for lines in tmp_result:
if len(lines.strip()) == 0 or (len(lines.strip()) == 1 and lines.strip() in ['{','}','#','/','\\','(',')']):#规定中的空白行规则
null_line += 1
elif len(lines.strip())>=1 and lines[0]!= '/':
code_line += 1
return (len(tmp_result)-1,null_line-1,code_line) def single_comment_count(self,string):
'''
单行注释统计
'''
re_pattern = re.compile('//')
del_pattern = re.compile('"[^"]*//[^"]*"')#排除双引号内情况
multi_in_single_pattern = re.compile('/\*.*')#排除多行注释内情况
tmp_result1 = re_pattern.findall(string)
tmp_result2 = del_pattern.findall(string)
for lines in tmp_result1:
if len(multi_in_single_pattern.findall(lines)) == 1:
self.multi_comment -= 1
print('sig',len(tmp_result1) - len(tmp_result2))
return len(tmp_result1) - len(tmp_result2) def multi_comment_count(self,string):
'''
多行注释统计
'''
multi_lines = 0
del_lines = 0
multi_pattern = re.compile('/\*+[^\*]+\*/')
single_in_multi_pattern = re.compile('//.*')#排除单行注释内情况
del_pattern = re.compile('"[^"]*/\*[^"]*\*/')#排除双引号内情况
tmp_result = multi_pattern.findall(string)
for result1 in tmp_result:
self.single_comment -= len(single_in_multi_pattern.findall(result1))
for x in result1:
if x == '\n':
multi_lines+=1
del_result = del_pattern.findall(string)
for x in del_result:
if x == '\n':
del_lines += 1
return multi_lines - del_lines def file_process(self,file):
'''
文件处理主函数
'''
with codecs.open(file, 'r', 'utf-8') as f:
self.file_string = f.read()
print('file:'+file,end=' ')
if self.isnull(self.file_string):
print('null file!')
return
else:
self.multi_comment += self.multi_comment_count(self.file_string)
self.single_comment += self.single_comment_count(self.file_string)
self.char_num += self.char_count(self.file_string)
self.word_num += self.word_count(self.file_string)
(self.lines,self.nullline) = self.line_count(self.file_string)
(self.lines,self.nullline,self.code_line) = self.line_count(self.file_string)
if self.opt['a'] :
print('character:'+str(self.char_num),end = ' ')
print('words:'+str(self.word_num),end=' ')
print('lines:'+str(self.lines),end=' ')
print('code_line:'+str(self.code_line),end=' ')
print('null_line:'+str(self.nullline),end=' ')
print('comment_line:'+str(self.single_comment+self.multi_comment))
else:
if not (self.opt['c'] or self.opt['w'] or self.opt['l']):
print('Please input command\n')
return
if self.opt['c']:
print('character:'+str(self.char_num),end = ' ')
if self.opt['w']:
print('words:'+str(self.word_num),end=' ')
if self.opt['l']:
print('lines:'+str(self.lines),end=' ') def file_select(self):#文件匹配
print(self.opt['f'])
file_list = glob.glob(self.opt['f'])
for x in file_list:
self.file_process(x)

图形界面类

from PyQt5.QtWidgets import *
from PyQt5.Qt import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from wc_class import word_counter class wc_ui(QDialog):
def __init__(self, parent=None):#控件初始化
super().__init__()
self.opt = opt = {'a':True}
self.wc = word_counter(self.opt)
self.setWindowTitle('Word Counter by Chernobyl')
self.file_label = QLabel()
self.is_null_label = QLabel('isnull:')
self.character_label = QLabel('character:')
self.word_label = QLabel('word:')
self.line_label = QLabel('line:')
self.null_line_label = QLabel('null_line:')
self.code_line_label = QLabel('code_line:')
self.comment_line_label = QLabel('comment_line:')
self.mainlayout = QVBoxLayout()
self.file_button = QPushButton('select file')
self.file_button.clicked.connect(self.selectfile) self.mainlayout.addWidget(self.file_label)
self.mainlayout.addWidget(self.is_null_label)
self.mainlayout.addWidget(self.character_label)
self.mainlayout.addWidget(self.word_label)
self.mainlayout.addWidget(self.line_label)
self.mainlayout.addWidget(self.null_line_label)
self.mainlayout.addWidget(self.code_line_label)
self.mainlayout.addWidget(self.comment_line_label)
self.mainlayout.addWidget(self.file_button) self.setLayout(self.mainlayout) def selectfile(self):#选择文件,并获取所有信息,更新控件的显示值
file_name = QFileDialog.getOpenFileName(self,"select file ","C:\\","c source files(*.c);;cpp source files(*.cpp);;header files(*.h)")
self.wc.file_process(file_name[0])
self.file_label.setText('file: %s'%(file_name[0]))
self.is_null_label.setText('isnull: %s'%(str(self.wc.is_null)))
self.character_label.setText('character: %d'%(self.wc.char_num))
self.word_label.setText('word: %d'%(self.wc.word_num))
self.line_label.setText('line: %d'%(self.wc.lines))
self.code_line_label.setText('code_line: %d'%(self.wc.code_line))
self.comment_line_label.setText('comment_line: %d'%(self.wc.single_comment+self.wc.multi_comment))
self.null_line_label.setText('null_line: %d'%(self.wc.nullline))

运行截图

  • 按照题目要求所创建的5个文件——空白、一个字母、一个单词、一整行、普通文件。截图如下

  • 软件帮助界面如下

  • 使用ubuntu内置的wc工具结果如下。注意,猜测wc工具的匹配规则为结尾有换行符算作一行——这是个bug,因为示例一行文件中虽然结尾无换行符,但应算作一行

  • 使用自己实现的wc工具结果如图

  • 图形界面截图如下



项目小结

  • 发现了在进行软件项目时的诸多问题,如进度管控、功能实现、debug等
  • 发现了wc工具的"bug"
  • 熟悉了python的图形界面编写和程序打包

软件工程作业——Word Counter的更多相关文章

  1. 软件工程作业 - word count

    (编程和软件工程作业系列) 实践最简单的项目:WC 实践是理论的基础和验证标准,希望读者贯彻“做中学”的思想,动手实现下面的项目,并和别人的成绩相比较,分析产生差距的原因. 1. 实现一个简单而完整的 ...

  2. 在大型软件中用Word做报表: 书签的应用

    本文转载:http://www.cnblogs.com/huyong/archive/2011/08/24/2151599.html 报表基本上在每一个项目中占有很大的比例,做报表也是我们开发人员必须 ...

  3. OFFICE2007软件打开word时出现SETUP ERROR的解决方法

    今天打开word时出现以下错误窗口: 在度娘上找了一下解决方案,原来每次打开word时都会启动一些无用的东西,找到这些东西的路径D:\Program Files\Common Files\micros ...

  4. 第一次软件工程作业——html制作一份简单的个人简历

    源码链接(码云):https://gitee.com/yongliuli/codes/eavjr7lxotb85s0icnq1z68 简历效果图展示: 代码展示: 添加背景音乐的方法: 在<he ...

  5. 第一次软件工程作业(One who wants to wear the crown, Bears the crown.)

    回顾你过去将近3年的学习经历 1.当初报考的时候,是真正的喜欢计算机这个专业吗? 报考时对于计算机专业只能说不讨厌,也可以认为对其没有任何的感觉. 有一个比我自己还注意我未来的老妈,我的报考只能通过一 ...

  6. 软件工程作业 - Week 1

    构建之法读后疑问: 初步的完成构建程序设计思路之后实现过程中发现了问题或者可以优化的地方是立马就改进还是完成之后按照步骤统一进行优化. 覆盖性测试,针对一些永远用不到只是用来预防极为极端的情况下,例如 ...

  7. 关于Office软件中Word输入时卡顿无反应的解决办法!

    最近在安装office2013时遇到了这样一个问题,就是在激活office之后,打开Word输入内容时十分卡顿.也是狂搜网上各种办法,有说改注册表的,也有说在office选项里设置什么输入法的,全试了 ...

  8. 第一次软件工程作业补充plus

    一.代码的coding地址:coding地址. 二.<构建之法>读后问题以及感言(补充): 1.对于7.3MSF团队模型,7.2.6保持敏捷,预期和适应变化,中的"我们是预期变化 ...

  9. 软件工程作业0——The Road Not Taken

    目录 第一部分:结缘计算机 缘起 四顾 思考 第二部分:在计算机系里学习 挑战 落差 第三部分:未来规划 向前 未来四个月的软工课 项目 内容 这个作业属于 2020春季计算机学院软件工程(罗杰 任健 ...

随机推荐

  1. redis的安装与类型

    redis Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件 源码安装 redis , 编译安装 为何用源码安装,不用yum安装, 编译安装的优势 ...

  2. oracle 数据库运维知识

    1.在数据库中连接用某个用户连接数据库报错: Product: DbVisualizer Pro 9.1.1 Build: #2063 (2013/10/01 12:27) Java VM: Java ...

  3. 6 《锋利的jQuery》Ajax的应用(略。)

    Ajax的优势 1.不需要插件支持 2.优秀的用户体验 3.提高web程序的性能(传输数据的方式,按需发送) 4.减轻服务器和带宽的负担 Ajax的不足 1.浏览器对XMLHttpRequest对象支 ...

  4. git用远程库的内容覆盖本地

    git fetch --all 下载远程的库的内容到本地,不做任何的合并(怎么合并可以自己选择) git reset --hard origin/master 撤销本地.暂存区.版本库(用远程服务器的 ...

  5. 用户态文件系统fuse学习【转】

    本文转载自:https://blog.csdn.net/ty_laurel/article/details/51685193 FUSE概述 FUSE(用户态文件系统)是一个实现在用户空间的文件系统框架 ...

  6. 织梦简洁机械设备dedecms模板

    织梦简洁机械设备dedecms模板,个人网站模板,dedecms模板. 模板地址:http://www.huiyi8.com/sc/7269.html

  7. openfire调试环境

    导入工程: File->New->project: 选择“Java project from existing ant buildfile” 再从菜单windows->show vi ...

  8. (转)C语言之原码、反码和补码

    原码.反码和补码 1).数据在内存中存储的时候都是以二进制的形式存储的. int num = 10; 原码.反码.补码都是二进制.只不过是二进制的不同的表现形式. 数据是以补码的二进制存储的. 2). ...

  9. bzoj2673

    限制这么多 肯定是网络流 考虑连边 首先我们计算出每行最多放的棋子数$sx[i]$,每列最多放的棋子数$sy[i]$ 首先由源点向第$i$行连流量为$sx[i]$费用为$0$的边,第$i$列向汇点连流 ...

  10. HihoCoder1654: XY游戏([Offer收割]编程练习赛39)(好久没写搜索)(已经超级简短了)

    描述 如下图所示,在4x4的棋盘上有X和Y两种棋子各若干枚:O表示空格. OXXY YOOX XOOY XOXX 小Hi每次可以选择任意一枚棋子,将它移动到上下左右相邻的空格中. 小Hi想知道最少移动 ...