Github项目地址
https://github.com/haImurat/3121005125
WC 项目要求
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 的行数
3. 解题思路
编程语言的选择
最近在学习python,觉得python比较方便好用,内含的库较多,可直接使用,因此选择python进行这次作业的开发。
需要用到的知识
控制命令行传参数、tkinter、字典、I/O流、正则表达式
结构分析
看到有较多的功能,所以不能将所有的程序写在一个py文件,要将必要的功能进行封装,需要时再调用,所以只需要一个主程序,去调用其他字程序就行了。
4. 设计实现过程
根据需求,对每个功能进行细分、简化,找出每个功能的详细需求,把每个功能都实现完成,生成函数,然后考虑封装调用,在主函数中实现调用各个功能函数,完成开发。
函数调用
5. 代码说明
1)主程序
import sys
import output as op
from window import Window
def main():
"""主程序"""
file = sys.argv[2] #从命令行中获取参数文件名
command = sys.argv[1]
file_name = file
if command == '-x':
Window()
op.Output(command,file_name)
main()
2)Output()函数:根据命令行的参数对应输出或者调用
def Output(command,file_name): """选择命令,输出数据""" datas = count(file_name) if command == '-c': export(file_name,"字符数",datas['character']) elif command == '-w': export(file_name, "单词数", datas['word']) elif command == '-l': export(file_name, "行数", datas['line']) elif command == '-s': #处理目录下符合条件的文件 print("\nC:\\Users\\荣\\PycharmProjects\\homework目录下的文件统计:\n") recursion() elif command == '-a': print('\n文件%s下的统计:' % file_name) print(datas) else: print("请输入正确指令")def export(filename,name,data): print('文件名:%s, %s: %d' % (filename,name,data))
3)count()函数,实现统计的功能,计算行数、字符数、代码数,利用字典存储数据,返回。
简要说明:首先利用open函数打开文件,然后对文件中每行进行循环,如果去掉每行两端的空白后等于空,则空行数加1;如果这行含有“//”,则注释行加1;计算单词数的时候,先用空格代
替其他特殊符号,利用split()函数通过空格使每行分隔开成为一个列表,使用正则判断是否为单词,如果是,则单词数加1。
def count(file_name): """统计文件中的数据""" data = {} data['line'] = 0 data['word'] = 0 data['character'] = 0 data['empty_line'] = 0 #空行 data['note_line'] = 0 #注释行 data['code_line'] = 0 #代码行 try: with open(file_name, 'r', encoding='utf-8')as fi: for lines in fi: if lines.strip() == '': data['empty_line'] += 1 continue if '//' in lines: data['note_line'] += 1 replace = re.subn(r"[#<>,;()""&{}+]"," ",lines) #用空格代替替他符号 words = replace[0].split() data['line'] += 1 for word in words: if re.match(r".*[A-Za-z].*",word): data['word'] += 1 if data['word'] > 1: data['code_line'] += 1 data['character'] += len(lines) - 1 except Exception as err: print(err) finally: fi.close() return data
4)recursion()函数,调用getfile()函数,获得文件名,利用循环处理目录下符合条件的文件,输出数据。
def recursion():
"""处理目录下符合条件的文件"""
file_list = getfile()
for filename in file_list:
datalist = count(filename)
print("文件名:%s" % filename)
print(datalist)
5)getfile()函数,利用os的功能walk找到目录下符合条件的所有文件。
def getfile():
"""处理目录下符合条件的文件,返回文件名"""
g = os.walk(r"C:\Users\荣\PycharmProjects\homework")
files = []
for path,d,filelist in g:
for filename in filelist:
if filename.endswith('.c'):
files.append(filename)
return files
6)window窗口,当命令行含有-x的时候,调用此窗口,选择文件进行统计。
def Window():
"""打开窗口,选择文件"""
root = tk.Tk()
root.title("选择文件")
root.geometry("300x100")
button = tk.Button(root, text='浏览文件', relief=tk.RAISED,command=Response)
button.place(x=100, y=20, width=100, height=50)
root.mainloop()
sys.exit()
7)Response()函数,当点击浏览文件按钮后,弹出文件管理窗口,选择文件。
def Response():
'''打开选择文件夹对话框'''
root = tk.Tk()
root.withdraw()
Filepath = filedialog.askopenfilename() #获得选择好的文件
# print('Folderpath:',Folderpath)
print('Filepath:',Filepath)
data_list = out.count(Filepath)
print(data_list)
Result(data_list,Filepath)
8)Result()函数,利用tkinter的窗口显示结果,现学现做,略显生硬。
def Result(datas,filename):
"""统计结果窗口"""
root = tk.Tk()
root.title("选择文件")
root.geometry("420x320")
file_name = tk.Label(root, text='文件名: %s'%filename, justify=tk.RIGHT, width=80)
line = tk.Label(root, text='行数: %s'%datas['line'], justify=tk.RIGHT, width=80)
word = tk.Label(root, text='单词数: %s'%datas['word'], justify=tk.RIGHT, width=80)
character = tk.Label(root, text='字符数: %s' % datas['character'], justify=tk.RIGHT, width=80)
empty_line = tk.Label(root, text='空行数: %s' % datas['empty_line'], justify=tk.RIGHT, width=80)
note_line = tk.Label(root, text='注释行: %s' % datas['note_line'], justify=tk.RIGHT, width=80)
code_line = tk.Label(root, text='代码行: %s' % datas['code_line'], justify=tk.RIGHT, width=80)
file_name.place(x=50,y=10,width=280,height=30)
line.place(x=135, y=40, width=100, height=20)
word.place(x=135, y=85, width=100, height=20)
character.place(x=135, y=130, width=100, height=20)
empty_line.place(x=135, y=175, width=100, height=20)
note_line.place(x=135, y=220, width=100, height=20)
code_line.place(x=135, y=265, width=100, height=20)
root.mainloop()
sys.exit()
6. 测试运行
测试文件:
测试结果:
7. 实现完程序后,实际花费时间
PSP2.1 | Personal Software ProcessStages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 30 |
Estimate | 估计这个任务需要多少时间 | 30 | 50 |
Development | 开发 | 800 | 1000 |
Analysis | 需求分析(包括学习新技术) | 60 | 120 |
Design Spec | 生成设计文档 | 20 | 20 |
Design Review | 设计复审 | ||
Coding Standard | 代码规范(为目前的开发制定合适的规范) | 20 | 20 |
Design | 具体设计 | 30 | 30 |
Coding | 具体编码 | 300 | 400 |
Code Review | 代码复审 | 20 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 200 | 200 |
Reporting | 报告 | 60 | 60 |
Test Repor | 测试报告 | 30 | 30 |
Size Measurement | 计算工作量 | 10 | 10 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 30 | 30 |
合计 | 1610 | 2030 |
8. 项目小结
经过这个小项目开发,发现的问题还是挺多的,编程基础很重要,有很多功能函数其实已经存在的了,只是不知道,或者不会调用,然后自己编码进行解决,吃力不讨好的事情,费时间,而且代码拓展性不高。有些功能看起来很难实现,但细细分析,把程序分为一个个函数,把每个函数的功能写好,再供程序调用,先解决小的问题,把简单的弄好,困难的部分也会变得简单。由于时间和基础的关系,有些功能没完全实现,或者是没实现,所以说PSP表格很重要,对自己的时间规划进行预估,给自己压力,每一次缩小了实际耗时和预估耗时的差距,就是进步。此次作业存在许多不足,以后会加强改进。
标签:name,个人,项目,root,tk,file,line,data From: https://www.cnblogs.com/halmurat/p/17708399.html