这个作业属于哪个课程 构建之法-2021秋-福州大学软件工程
这个作业要求在哪里 2021秋软工实践第一次个人编程作业
这个作业的目标 学习使用GitHub、制定代码规范、完成C/C++文件的关键字提取
学号 031904138

制定个人代码规范

个人GitHub主页

文章目录

  • 一、PSP表格
  • 二、解题思路描述
  • 三、设计实现过程
  • 四、代码说明
  • 五、单元测试与性能分析
  • 六、总结

一、PSP表格


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

二、解题思路描述


  • 基础要求:输出关键字统计信息
    (1)读入代码文件,过滤掉空行、非字母的字符,同时删除文件中的注释等部分
    (2)使用.split()方法对文本进行切片,将文本分割为单词列表WordList
    (3)遍历列表WordList,得到列表中的关键字统计信息

  • 进阶要求:输出有几组switch case结构,同时输出每组对应的case个数
    (1)遍历基础要求中得到的WordList[ ],得到全部的switch和case,按顺序记录在另一个列表switch_case中
    (2)遍历列表switch_case,得到switch数目以及对应的case数目

  • 拔高要求:输出有几组if else结构
    记得当时上数据结构时写过一道括号配对的题,寻思着if-else配对和括号配对应该是一类问题,采用的数据结构是栈,本来打算用stack来做,但是为了方便遍历,就换成了列表的形式+堆栈的思路

  • 终极要求:输出有几组if,else if,else结构
    思路同上


三、设计实现过程


  • 先定义需要的关键函数:
def split_word(dir)      # 用于把对应路径的文件分词成列表
def merge_if_else(list)     # 用于合并列表中配对的if和else
def merge_if_elseif_else(list)  #用于合并列表中配对的if-elseif-else
def count_key(dir,rank)     # 实现统计关键字功能
  • 以上关键函数的流程图:
    1、split_word(dir):将代码文件中的全部单词分词为一个列表

    2、merge_if_else(list):合并列表中配对的if和else
    以文件样例为例:
    3、merge_if_elseif_else(list):合并列表中配对的if-elseif-else
    连续的else-if都视作一个if-elseif-else结构,因此只要存在连续的if-else就将其更新为一个"if-elseif-else"字符串
    4、count_key(dir,rank):实现统计关键字功能

四、代码说明


本次代码中有四个关键函数,详细思路如设计实现过程中流程图所示
1、split_word(dir):将代码文件中的全部单词分词为一个列表

#把文件内的单词分割为列表
def split_word(dir):    #dir为输入的代码文件路径f = open(dir, 'r', encoding='gbk')lines = f.readlines()    new_line=""                      # 用于记录文件内容的字符串for line in lines:                    # 逐行读入代码文件if line != '' and line != '\n': # 过滤空行new_line = new_line + line  # 把文件内容连接成一个字符串new_line = remove(new_line)      # 去除注释部分以及引号的内容new_line = remove_non_letter(new_line)  # 去除非字母部分new_line = new_line.strip()  # 去除前后空格lis = new_line.split(" ")  # 分割成列表lis = del_empty(lis)  # 删除列表中空值return lis

2、merge_if_else(list):合并列表中配对的if和else

# 把if和对应else进行配对
def merge_if_else(list):if_else=[]               # 记录if-else结构的列表if_else.append(list[0])   # 把if_else列表当成栈使用for word in list[1:]:     # 把else与其配对的if连接起来if word=="else":if if_else[-1]=="if":if_else.pop()if_else.append("if-else")else:if_else.append(word)else:if_else.append(word)return if_else

3、merge_if_elseif_else(list):合并列表中配对的if-elseif-else

# 把if-elseif-else进行配对
def merge_if_elseif_else(list):if_elseif_else = []             # 记录if-elseif_else结构的列表if_elseif_else.append(list[0])  # 把if_elseif_else列表当成栈使用for word in list[1:]:            # 把if_else与if_else连接起来if word == "if-else" and if_elseif_else[-1] != "if" and if_elseif_else[-1] != "else":if_elseif_else.pop()if_elseif_else.append("if-elseif-else")else:if_elseif_else.append(word)# print(if_elseif_else)return if_elseif_else

4、count_key(dir,rank):实现统计关键字功能
在此函数分别设置里实现不同需求的函数,分别是:

   def rank_1()   # rank1基础要求:输出关键字统计信息def rank_2()  # rank2进阶要求:输出有几组switch case结构,同时输出每组对应的case个数def rank_3()  # rank3:拔高要求:输出有几组if-else结构def rank_4()  # rank4:终极要求:输出有几组if-elseif-else结构

各需求的具体代码如下:

# rank1基础要求:输出关键字统计信息def rank_1():        for word in word_list:if word in keyWords:  # 提取出关键字并存放到 keyword_list[ ]中keyword_list.append(word)continueprint("total num: {0}".format(len(keyword_list)))
# rank2进阶要求:输出有几组switch case结构,同时输出每组对应的case个数def rank_2():switch_case=[]             #用于记录按序取出的所有switch,casefor word in word_list:if word in ['switch','case']:   #提取出switch,case并存放到switch_case[ ]中switch_case.append(word)switch_num = 0           # 记录switch的数目case_num = []                 # 记录case的数目for i in range(len(switch_case)):    # 遍历列表得到全部switch-case结构if switch_case[i] == "switch":switch_num += 1temp_case_num = 0for j in range(i+1,len(switch_case)):if switch_case[j] == "case":temp_case_num += 1else:breakcase_num.append(temp_case_num)#控制输出格式print("switch num: {0}".format(switch_num))if (len(case_num) == 0):print("case num: 0")else:print("case num: ", end='')for num in case_num:print(str(num) + " ", end='')print()
#rank3:拔高要求:输出有几组if-else结构def rank_3():ifOrElse = []         # 记录所有单个if,else的列表if_else_num=0     # 记录if-else的数量for word in word_list:if word=="if" or word=="else":ifOrElse.append(word)         # 把所有的if else单独提取出来if_else = merge_if_else(ifOrElse)   # 逐步进行合并 先配对if-elseif_elseif_else = merge_if_elseif_else(if_else)   #再配对if-elseif-elseif(len(if_elseif_else)!=0):while("if-elseif-else" in if_elseif_else):  # 统计if-elseif-else数目for i in range(len(if_elseif_else)):if if_elseif_else[i]=="if-elseif-else":if_elseif_else[i]=""         #记录完后删除if_elseif_else=del_empty(if_elseif_else)     # 删除列表中的空值if(len(if_elseif_else)!=0):if_else=merge_if_else(if_elseif_else)   #再次进行合并if_elseif_else=merge_if_elseif_else(if_else)if(len(if_elseif_else)!=0):if_else = merge_if_else(if_elseif_else)     #对统计完if-elseif-else的列表进行合并while ("if-else" in if_else):  # 统计if-else的数目for i in range(len(if_else)):if if_else[i] == "if-else":if_else[i] = ""        # 统计完后删除if_else_num += 1if_else = del_empty(if_else)  # 删除列表中的空值if(len(if_else)!=0):if_else = merge_if_else(if_else)  # 再次进行合并print("if-else num: {0}".format(if_else_num))  # if-else的数目

终极要求在rank3中已经实现了,步骤同上,此处就不再赘述

因此,count_key(dir,rank)的总结构表示如下:

def count_key(dir,rank):if rank==1:rank_1()if rank==2:rank_1()rank_2()if rank==3:rank_1()rank_2()rank_3()if rank==4:rank_1()rank_2()rank_3()rank_4()

五、单元测试与性能分析


1、使用C语言文件样例进行测试,运行结果:

2、使用coverage工具统计python单元测试覆盖率
执行代码覆盖率统计,只需要通过coverage的run参数执行被统计代码即可,命令行输入:

coverage run test.py arg1 arg2

会自动生成一个覆盖率统计结果文件(data file):.coverage。
有了覆盖率统计结果文件,只需要再运行report参数,就可以在命令里看到统计的结果
命令行输入:

coverage report


Stmts/Miss表示语句总数/未执行到的语句数

3、性能分析
由于程序运行时间有点短,加入了time.sleep(10)再进行性能分析
按照累积时间进行降序排序并输出

其中,输出每列的具体解释如下:

ncalls:表示函数调用的次数;
tottime:表示指定函数的总的运行时间,除掉函数中调用子函数的运行时间;
percall:(第一个percall)等于 tottime/ncalls;
cumtime:表示该函数及其所有子函数的调用运行的时间,即函数开始调用到返回的时间;
percall:(第二个percall)即函数运行一次的平均时间,等于 cumtime/ncalls;
filename:lineno(function):每个函数调用的具体信息;

从图中得到的信息为:

1、整个过程一共有1965个函数调用被监控,其中1913个是原生调用(即不涉及递归调用)
2、总共执行的时间为22.961秒(包括一个time.sleep(10))
3、可见程序大部分时间主要花在分离不同需求关键字的过程中,其中把代码文件拆分为单词列表的过程是一个主要耗时的部分。


六、总结


  • 通过此次个人编程作业,接触到了PSP表格,第一次深入了解了github的具体使用,更加熟悉了使用MarkDown进行博客的排版编写,了解到更多python的编码规范,也对逐步完成需求有了初步的认识。
  • 遇到很多没接触过的词汇,单元测试,性能分析,单元测试覆盖率…面向百度查阅了好多好多资料,过程繁杂但也收获满满,get了一些新技能比如GitHub的使用,正则表达式的使用,单元测试工具的使用等等
  • 在此过程中也认识到自己有很多的不足,代码都是很基础的语法,不够简洁,没有选择到效率更高的数据结构,总体上还是感觉差强人意,希望这些过程能够成为激励自己的动力吧,边学边做边积累,加油加油加油!

附1:完整代码

countKey.py

附2:GitHub Commit截图

2021秋软工实践第一次个人编程作业相关推荐

  1. 2021秋软工实践第一次结对编程作业

    这个作业属于哪个课程 构建之法-2021秋-福州大学软件工程 这个作业要求在哪里 2021秋软工实践第一次结对编程作业 这个作业的目标 实现博饼软件原型并进行博客写作 学号 031902139 队友学 ...

  2. 2021秋软工实践第一次结对编程作业-需求分析

    博饼软件需求分析 一.简要说明 博饼,是厦门人几百年来独有的中秋传统活动,是一种独特的月饼文化,也是厦门人对历史的一种传承.现在,博饼依然是厦门人最钟爱的中秋活动,也是最热闹的一个民俗节日形式. 目前 ...

  3. 2022秋软工实践 第一次结对编程作业

    2022秋软工实践 第一次结对编程作业 需求分析 (1)Need,需求 (2)Approach,做法 (3)Benfit,好处 (4)Competitors,竞争 (5)Delivery,推广 UML ...

  4. 2021秋软工实践个人作业一

    2021秋软工实践个人作业一 2021秋软工实践个人作业一 自我介绍 技能树 精简技能树 技能树描述 学期目标 软件工程A 构建之法-2021秋-福州大学软件工程 作业要求 2021秋软工实践个人作业 ...

  5. 2021秋软工实践 Lab6 团队展示与选题报告

    作业所属课程 构建之法-2021秋-福州大学软件工程 作业要求 第6次作业-团队展示+选题报告 作业的目标 为开源爱好者服务,实现更实用.更便利.更具人性化的GitHub工具类小程序 团队名称 MDY ...

  6. 软工实践第一次博客作业

    1.个人简介 我是031702109唐怡:爱好是听歌,火漆:在福大食堂最喜欢的就是西红柿炒鸡蛋:最近超迷<all time low(cash cash remix)>:听闻先生治家有方,鄙 ...

  7. 软工实践第一次作业-自我审视和规划

    软工实践第一次作业-自我审视和规划 题目地址:https://edu.cnblogs.com/campus/fzu/FZUSoftwareEngineering1816W/homework/2060? ...

  8. 软工实践第一次作业-准备

    软工实践第一次作业-准备 标签(空格分隔): 软工实践 Chs97's Blog 回想一下你初入大学时对计算机专业的畅想 当初你是如何做出选择计算机专业的决定的? 计算机或许是注定的吧.回想第一次接触 ...

  9. 2022秋软工实践个人作业二

    2022秋软工实践个人作业二 Task I Task II 这个作业属于哪个课程 软工实践 这个作业要求在哪里 2022秋软工实践个人作业二 这个作业的目标 git html 学号 032002342 ...

  10. 软工实践第八次作业(软件工程实践总结)

    原博客 目录 一.请回望暑假时的第一次作业,你对于软件工程课程的想象 二.个人或结对或团队项目实践中的经验总结+实例/例证结合的分析 三.对下一届实践的建议和告知.对于后来人的期许. 四.分析一下自己 ...

最新文章

  1. Matlab和Modelsim联合仿真的配置
  2. java点到原点距离_java-从经纬度坐标到欧氏距离(EuclideanDistance)完整代码
  3. android git上传出现错误,热更新上传patch包时提示上传失败,文件不合法
  4. ClassCastException:AdaptiveIconDrawable cannot be cast to BitmapDrawable
  5. Express 路由、Ejs 、静态文件托管、中间件
  6. linux resin 查看日志命令,【转】linux:访问日志分析
  7. mysql 分页拦截器_MyBatis 拦截器 (实现分页功能)
  8. Makefile的学习笔记
  9. HD 2177(威佐夫博弈 入门)
  10. 60天申请软件著作权
  11. 20211104 为什么相似矩阵的迹相同
  12. 我的python笔记06
  13. 爬取网站小猪短租的少量信息及详细介绍 ,requests库,bs4库的使用
  14. 接口耗时优化与cpu飙高解决
  15. qr码生成_在PHP中生成QR码
  16. fiilt1左耳连不上_FIIL T1完美解决真无线耳机的痛点:更快更稳更自由
  17. NYOJ-20 吝啬的国度 AC
  18. nth_element(C++)
  19. 【源码分享】ASP.NET企业办公综合管理系统源码(OA+CRM+进销存+财务)
  20. Linguistic Sorting and Matching

热门文章

  1. 杭州治堵有“智慧” 阿里云数加激活城市大脑
  2. java中怎样显示图片_[Java教程]Java中显示图片的方法
  3. 基于CNN的区域特定多尺度特征提取的两阶段停车位检测
  4. 2007福布斯名人榜完全名单 巩俐收入盖过章子怡
  5. 1090: 哥德巴赫猜测
  6. 【论文笔记】Switching Convolutional Neural Network for Crowd Counting
  7. 企业怎样优化用户体验?F5给出三条专业建议
  8. 恶魔和梦魇的私语------- 关于软件开发的务虚主义对话(3)
  9. 区块链交易验证和支付验证
  10. 解决了Office2007向程序发送命令时出现错误 的问题