2021-09-20

这个作业属于那个课程 构建之法-2021年秋-福州大学软件工程
这个作业要求在哪里 2021年秋软工实践第一次个人编程作业
这个作业的目标 实现一个程序功能,它可以对读入的 C或C++代码文件进行不同等级的关键字提取;学会使用 Git 进行版本控制
学号 031902110

GitHub 仓库

文章目录

一、PSP表格

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

二、解题思路

当拿到题目的时候,分析题目要求。题目共分为 4 个要求,逐步实现每个要求,先从基础的开始。

1. 文本的读取及处理

  • 先把所有的标点符号都找出来,再用空格来替代标点符号,最后再以空格作为分隔符来分隔单词。

2. 基础要求

  • 创建一个关键字集合
  • 设置一些过滤条件过滤非关键字,将关键字保存到列表中
  • 统计关键字的个数并输出

3. 进阶要求

  • 创建一个列表存储每个 swtich 对应的 case 个数
  • 利用基础要求中获得的关键字列表,对列表做一次遍历
  • 当遇见 switch 从 0 开始记录 case 的个数直到遇见下一个 swtich 或关键字列表遍历结束
  • 输出 switch 和 case 的信息

4. 拔高和终极要求

  • 这两个要求相关性很大,所以放到一起完成
  • 把 else if 合并成 elseif
  • 遍历关键字列表,遇见 if、elseif (多个只需入栈一次)就将其入栈(用列表模拟栈)
  • 遇到 else 时查看栈顶元素,若为 if 则将其出栈,if else 结构数量加 1
  • 若栈顶为 elseif 则做出栈操作两次,if,else if,else结构数量加 1

三、设计实现过程

1. 代码组织

2021-09-20

2. 函数流程图

2021-09-20

2021-09-20
2021-09-20
2021-09-20
2021-09-20

四、代码说明

1. 文本读入函数


def get_text():
    file = open(sys.argv[1], "r", encoding="UTF-8")  # 用 UTF-8 格式打开防止乱码
    txt = file.read()
    for ch in '!#$%&()+,-.:;<=>?@[\\]^_{|}~':
        # 考虑注释和引号,不能去掉符号 * / “
        txt = txt.replace(ch, " ")  # 将符号替换成空格
    file.close()
    return txt

2. 去除注释、双引号字符串



def words_filter():
    txt = get_text().replace("else if", "elseif")
    separator = [r'//.*', r'\/\*(?:[^\*]|\*+[^\/\*])*\*+\/', r'".*"']
    # 分别以  //单行注释  /* 多行注释*/  "引号" 作为分隔符
    for sp in separator:
        wordlist = re.split(sp, txt)  # 运用正则表达式匹配分隔文本
        txt = ""
        for word in wordlist:  # 重新拼接字符串
            txt = txt + word
    wordlist = txt.split()
    return wordlist


words = words_filter()
filterwords = []

3. 统计关键字个数



def first_level():
    keywords = {"auto", "break", "case", "char", "const",
                "continue", "default", "do", "double", "else",
                "enum", "extern", "float", "for", "goto",
                "if", "int", "long", "register", "return",
                "short", "signed", "sizeof", "static", "struct",
                "switch", "typedef", "union", "unsigned",
                "void", "volatile", "while", "elseif"
                }  # 把 else if 合并 成 elseif 作为一个关键字,为拔高和终极要求做准备
    counts = {}  # 关键字字典
    cnt = 0
    for word in words:
    	# 设置条件过滤字符串,保留关键字
        if len(word) == 1 or (word not in keywords):
            continue
        counts[word] = counts.get(word, 0) + 1  
        filterwords.append(word)
        cnt = cnt + 1
    cnt = cnt + counts.get("elseif", 0)  # elseif 合并后要多算一次
    print("total num: {}".format(cnt))
    return counts

4. 计算 switch case 个数



def second_level(counts):
    num = counts.get("switch", 0)
    print("switch num: {}".format(num))
    if num == 0:
        print("case num: {}".format(num))
        return
    count = []
    flag = -1
    for word in words:
        if word == "switch":  # 遇到 switch, count[]列表元素加 1
            count.append(0)
            flag += 1
        elif word == "case":
            count[flag] += 1
        else:
            continue
    print("case num: ", end="")
    print(" ".join(str(x) for x in count))

5. 计算 if else 和 if, elseif, else



def last_level():
    stack = []
    if_else_num = 0
    if_elseif_else_num = 0
    for word in filterwords:
        if word == "if":  # 遇到 if 就把它入栈
            stack.append(word)
        elif word == "elseif" and stack[-1] != "elseif":  # 连续 elseif 入栈一个就行
            stack.append(word)
        elif word == "else":  # 遇到 else 查看栈顶关键字
            if stack[-1] == "if":  # 是 if 直接出栈,if else 结构加 1
                stack.pop()
                if_else_num += 1
            elif stack[-1] == "elseif":  # 栈顶是 elseif 连续出栈两个元素
                stack.pop()
                stack.pop()
                if_elseif_else_num += 1
    print("if-else num: {}".format(if_else_num))
    if sys.argv[2] == '4':
        print("if-elseif-else num: {}".format(if_elseif_else_num))

五、单元测试截图和描述

2021-09-20
单元测试结果和预期一致

六、性能测试

2021-09-20

七、总结

  • 作业收获
    • 通过这次作业,我学习了一些新的 python 技能,如:从命令行执行程序并读取参数、正则表达式的使用、单元测试、性能分析。
    • 学会了用 Git 来控制版本库,每一次的 commit 都能收获一点点的成就感。
    • 学会将本地仓库与远程的 GitHub 仓库关联起来,明白了 Git 这种分布式管理的优点。
    • 能够对目标进行简单规划
  • 遇到的困难及解决
    • 最大的困难就是对时间的把控,很难完全按照制定好的时间规划做任务。对此我的解决方法是不要把时间一下规划得太长,多将时间分片,这样做任务的时候不容易中断
上一篇:CF1101B Accordion 题解


下一篇:3.2 if语句实现选择结构