软工第一次个人编程作业
这个作业属于哪个课程 | 构建之法-2021秋-福州大学软件工程 |
---|---|
这个作业的要求在哪里 | 2021秋软工实践第一次个人编程作业. |
这个作业的目标 | 实现一个程序功能,它可以对读入的C或C++代码文件进行不同等级的关键字提取。 |
学号 | 031902432 |
PSP表格
PSP | 预估时间(h) | 实践时间 (h) |
---|---|---|
plan(计划) | ||
Estimate(估计时间) | 40 | 45 |
Development(开发) | ||
Analysis&Learning(需求分析(包括学习新技术)) | 12 | 14 |
Design Spec(生成设计文档) | 2 | 2 |
-Coding Standard(代码规范 ) | 0.5 | 0.5 |
Design Review ( 设计复审) | 1 | 1.5 |
Coding (编码) | 18 | 24 |
Test(测试,修改代码) | 7 | 8 |
Test Report(测试报告) | 2 | 2.5 |
Size Measurement(计算工作量) | 1 | 1 |
Postmortem & Process Improvement Plan(事后总结, 并提出过程改进计划) | 2 | 2 |
total(总用时) | 45.5 | 55.5 |
代码规范
作业地址github仓库
commit截图
解题思路
首先看到这个题目的时候,我大脑一片空白。第一感觉就是用c++会很麻烦,需要调用很多函数实现(仅仅是我自己的感觉)。后面听其他软工班级的同学说用python做软工作业会简单很多,所以我又跑去B站找py教程自学,边学边摸索。学习过程中慢慢认同py的强大之处。后面学习了基础之后开始在网上查找python有没有和这道题相似的题目,方便参考网上大佬的思路与代码处理。首先要完成文件的读入,网上有选用open函数打开,然后利用循环按行或者按字读入的,还有一些是直接read,我选择了read读入将目标文件存入。后面就是处理文件中的多余的字符,比如{},(),[]等. 在百度菜鸟教程上说明了可以用正则表达式运用匹配去除字符。
def read_text(path):# path为传入的c,cpp路径
try:
fp = open(path, 'r', encoding='utf-8')
str_str = '~`!#$%^&*()_+-=|\';":/.,?><~·!@#¥%……&*()——+-=“:’;、。,?》《{}'
file_text = re.sub(r"[%s]+" % str_str, " ", fp.read()) # 通过正则化原文本内容,去除所有符号
file_text = file_text.split('\n') # 按换行符分割文本
fp.close()
except:
print("文件打开错误")
return file_text
基础要求:输出关键字统计信息:要找到关键字以及总数,可以用匹配方法和关键字匹配,查找到则标记+1,用相同方法遍历代码,循环直至结束。但是这个会比较慢,时间复杂度较高。我觉得可用字典函数把关键字存储起来,但是我还没学会字典,所以只能先用list(列表)来完成。
def key_word(key_list):
key_word0= {'else if', 'char', 'double', 'enum', 'float', 'int', 'long',
'short', 'signed', 'struct','void', 'for', 'do', 'while', 'break',
'continue', 'union', 'unsigned', 'const', 'sizeof', 'typedef', 'volatile' ,
'if', 'else', 'goto', 'switch', 'case', 'default', 'return', 'auto', 'extern',
'register', 'static'
} #创建包含所有c++内置关键字的字典
key_num= 0
for word in key_list:
if word in key_word0:
key_num += 1
return key_num # 返回文件中C、CPP关键词的总数
进阶要求:输出有几组switch case结构,同时输出每组对应的case个数:匹配原则。具体的标记可以以下一个switch来判断该switch结构长度。这个方法同上。
def case_num(ed_key_list):# 文件中有switch才能统计case
length = len(ed_key_list)
if (ed_key_list.count('switch',0)):#从索引0位置查找switch个数且找到就执行
num_case = []
for i in range(length):
if ed_key_list[i] == 'switch':
if (i + 1) == length or ed_key_list[i + 1] != 'case': #switch是列表最后的元素或下一位置不是case
num_case.append(0)
elif i < length - 1: #switch是列表中间元素
flag = 1 #标记查找时步长
if ed_key_list[i + flag] == 'case': #下一位置为case
case_cnt = 0 #标记case个数
while i + flag < length: #在列表元素中查找,避免越界,系统报错
if ed_key_list[flag + i] == 'case':
case_cnt += 1
flag += 1
else:
break
num_case.append(case_cnt)
else:
num_case.append(0)
return num_case
else:
return [0]
拔高要求:输出有几组if else结构,终极要求:输出有几组if,else if,else结构:刚开始我对于这个是没有思路的,后面看了前面的大佬们提交的作业中受到了启发(或者说是看到了才想到可以用堆栈解决,后面的思路可以说不是我的,只是觉得我找不到其他的思路,只好往这种思路上想):找到if-else和if-else-if结构,可以用堆栈,先定义if代表1,else代表2,elseif代表3,每碰到一个if,堆栈就压入一个1,碰到一个elseif就压入3,而碰到else的时候就开始循环删除,直到删除到1停止,如果删除的数中有3,那这就是个if-else-if结构,如果没有3就是if-else结构,压入数和删除数可以利用append和pop完成。我百度了py中怎么使用堆栈。可惜的是做不出来这个,emo。
def count_if_else(key_list):
count_if_else = 0
count_if_else_if = 0
l=key_list
flag=0
if l[0] == 'i' and l[1] == 'f':#判断if
stack.append(1)
if l[0] == 'e' and l[4] == 'i':#判断elseif
stack.append(3)
elif l[0] == 'e' and l[1] == 'l':#判断else
while stack[-1] != 1:
if stack[-1] == 3:
flag=1
stack.pop()
stack.pop()
if flag == 0:
count_if_else += 1
if flag == 1:
count_if_else_if += 1
else:
pass
temp= list([count_if_else,count_if_else_if])
list_key = temp
return list_key
单元测试
测试一
测试二
测试三
测试四
性能测试
遇到的困难
首先就是函数的构建,文件输入和if_else_if 查找。这两个对我来说是挺困难的,文件的输入我刚开始是真没看懂怎么实现输入,按行输入循环遍历还是直接读入挺难抉择,而且也不会这个,主要还是代码敲少了,以前欠的债,自食其果。后面查阅了网上的资料和舍友的讲解才勉强能够实现。if_els_if结构我用了堆栈,特地去菜鸟教程和百度上查找用法。令我窒息的是没有结果输出。放弃了,后面听听其他人的解法。
其次就是python的函数,这里面的函数挺多的,但是记起来麻烦,需要去百度,还得清楚他的具体用法。但是实现功能的算法还是比c++要简单多,有可能c++用十行实现的功能py只需要一行。刚开始自学py,还是有许多不是很清楚的地方,比如字典和列表以及集合之间的应用场景。需要在后面的时间里慢慢摸索。
然后就是性能测试,我找了半天没在pycharm上找到测试(人裂开),按照网上教程的步骤找也没搞清楚,教程就弄了个配置步骤,后面的没懂,还需要慢慢自己去查找。
最后就是坑多的Git。下载Git后,看了实践教程,跟着做了一遍后,下一次就忘了。在上传文件的时候一大堆的bug。最难受的就是SSH密钥,上传文件时push不了,去百度才知道SSH密钥未配置。好不容易在git命令中找到密钥,在复制的时候又漏了一小部分,后面又花了大精力去检验才知道。弄好SSH后还是push不了,又查资料才知道本地文件库分支未与远程库分支连接,解决这些后,总算能够上传了。
总结
学到的知识还挺多的,git的使用,python的基本知识和实践,在敲代码的过程中的逐步加深理解,比c++简便快捷好操作,对于一些函数可以大致使用了,比如count,endswitch,startswitch基本函数。
对于代码的掌握又多了一个半吊子编程语言。在完成作业时,也学会了制定自己的代码规范,PSP表格的制作和对时间的规划。