2021秋软工实践第一次个人编程作业

L1angYC13 2021-09-20 19:07:31
这个作业属于哪个课程 构建之法-2021秋-福州大学软件工程 https://bbs.csdn.net/forums/fzuSoftwareEngineering2021
这个作业要求在哪里 2021秋软工实践第一次个人编程作业 https://bbs.csdn.net/topics/600574694
这个作业的目标学习GitHub和Git使用,锻炼思考以及编码能力,提升计算机素养
学号031902609
GitHub地址 第一次个人软工作业仓库地址 https://github.com/LiangYC1021/2021-Software-Engineering-1

PSP表

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划
· Estimate· 估计这个任务需要多少时间600720
Development开发
· Analysis· 需求分析 (包括学习新技术)6040
· Design Spec· 生成设计文档3030
· Design Review· 设计复审2020
· Coding Standard· 代码规范 (为目前的开发制定合适的规范)300
· Design· 具体设计4040
· Coding· 具体编码180180
· Code ReviewPlanning· 代码复审计划6040
· Test· Estimate· 测试(自我测试,修改代码,提交修改)· 估计这个任务需要多少时间200240
ReportingDevelopment报告6060
· Postmortem & Process Improvement Plan· Design Review· 事后总结, 并提出过程改进计划· 设计复审3030
· 合计13101400

Git部分

仓库链接

第一次个人软工作业仓库地址 https://github.com/LiangYC1021/2021-Software-Engineering-1

commit信息规范

我在本次作业后期才发现其实正确commit的方法是对之前上传的代码进行update,这样可以很直观的看出来和之前的版本修改之处,而不是每次都新create一份完整代码。

文件规范

本次上传GitHub仓库的内容为每次更新的版本的 CPP 文件及其相应的文档(包含了修改、更新的内容)。

代码部分

代码风格

风格不知道怎么说。。请前往仓库查看代码!

代码规范

  • 缩进:每个花括号语句内使用相同缩进,缩进比上一级语句多一个制表符tab。

  • 变量命名:所有变量名以在代码中的实际作用命名。

  • 每行最多字符数:无制定,但我的代码中不会有长行,保证能在一个屏幕中可见。

  • 函数最大行数:除主函数外,最大行数为30行。

  • 函数、类命名:本题中没用到类、封装等。函数命名以在代码中的实际作用命名,以大写字母开头。

  • 常量:本题中未使用到const常量。通常会在头文件下方定义一个const int N = 1e5 + 5 。

  • 空行规则:函数之间、整体全局变量定义区与函数之间会空一行;函数内不空行。

  • 注释规则:代码内使用英文注释防止编码乱码。但在GitHub的commit、每次更新的文档中会部分使用中文进行解释。

  • 操作符前后空格:操作符前后无空格。

  • 其他规则:每份代码会包含缺省源,其中有:万能头文件、循环宏定义、无穷大宏定义、longlong 类型定义、常用模数、常量大小等。

    #include<bits/stdc++.h>
    #define inf 1e18+5
    #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    using namespace std;
    typedef long long ll;
    const int mod=998244353;
    const int N=1e5+5;
    

后续会将代码规范单独水一贴

单元测试及函数解析

第一次遇到单元测试这类的要求,不太清楚是要干啥,我当前的理解是对每个函数进行解释与测试。

关键代码内容也在该部分!

以下函数按照程序运行逻辑的顺序给出。

1.Pre()函数:预处理读入的每行代码,删除其中的“字符串“和注释中的内容。

inline string Pre(string s)
{
    string res="";
    for(int i=0;i<s.size();i++){
        if(s[i]=='"'){
            for(int j=i+1;i<s.size();j++){
                if(s[j]=='"'){
                    s.erase(i,j-i+1);
                    break;
                }
            }
        }
    }    
    for(int i=0;i<s.size();i++){
        if(s[i]=='/'&&s[i+1]=='/'){
            return res;
        }
        res+=s[i];
    }
    return res;
} 

输入一行代码测试,输出处理后的结果。正确。

img

2.Match(string s)函数:对于每次分离出来的一部分子串,暴力枚举32个关键字判断是否相同,相同时对某些关键字执行相应操作。返回一个bool变量。

inline bool Match(string s)
{
    string res="NULL";
    rep(i,1,32){
        if(s==Key[i]){
            res=Key[i];
            break;
        }
    }
    if(res=="switch"&&Case_num){
        Swt.push_back(Case_num);
        Case_num=0;
    }
    if(res=="case")Case_num++;
    if(res=="if" || res=="else")ie.push_back(res);
    if(res!="NULL"){
        Tot_num++;
        return true;
    }
    return false;
}

过于简单,与后续函数一同测试。

3.check(string s)函数。该函数对getline获得的每一行代码进行操作。提取出其中的花括号和关键字,便于后续的判别操作。

由于32个关键字的长度为2~8,于是很简单的对每个相应长度的子串拿去执行上方提到的Match函数。从长度8至2枚举的原因是有类似于"do" "double"这种情况,若先判断了长度为2的"do"关键字,但实际情况为"double",则会出错。

inline void check(string s)
{
    int len=s.size();
    s+="$$$$$$$$$";
    //Prevent overflow
    for(int i=0;i<len;i++){
        if(s[i]=='{')ie.push_back("{");
        if(s[i]=='}')ie.push_back("}");
        for(int j=8;j>=2;j--){
            if(Match(s.substr(i,j))){
                i+=j-1;
                break;
            }
        }        
    }
}

在其中加一句代码用于测试,检测到一个正确的关键字就输出:

cout<<s.substr(i,j)<<endl;

输入一行正确的代码语句。正确。

img

4.Special_Check(string s) 函数。用于判断,将一对"else" "if" 替换成 "else_if"。

inline void Special_Check(string s)
{
    int len=s.size();
    s+="$$$$";
    int temp_if=0,temp_else=0;
    for(int i=0;i<len;i++){
        if(s.substr(i,2)=="if")temp_if++;
        if(s.substr(i,4)=="else")temp_else++;
    }
    if(temp_else && temp_if){
        stack<string>tmp;
        bool f1=0,f2=0;
        while(f1==0 && f2==0){
            string bk=ie.back();
            ie.pop_back();
            if(bk=="if")f2=1;
            if(bk=="else")f1=1;
            if(bk!="if"&&bk!="else")tmp.push(bk);
        }
        ie.pop_back();
        ie.push_back("else_if");
        while(!tmp.empty()){
            ie.push_back(tmp.top());
            tmp.pop();
        }
        //Replace "else" "if" with "else_if"
    }
}

对于读入的一行,获取的关键字及花括号为:

img

img

正确。

5.Count_ie_num()函数。该函数较为关键,用于匹配每个if else对、if else_if else对。它可以处理许多特判!

我的主要思路是对于刚刚提取的if else else_if 及左右花括号 { }这几个关键字,用栈这一数据结构来进行他们的匹配(灵感来自于括号匹配题目)。

对于每个右花括号 ‘}’ ,都处理到前一个左花括号‘{‘ 之间的关键字对。由于题目、老师、助教的解释,不是由else结尾的if else对、if else_if else对都是不予计数的,因此在这俩花括号之间,对于每个”else“,都往前匹配,若存在else_if ,则if else_if else对数增加,只有if与其相匹配则if else对数增加。

inline void Count_ie_num()
{
    for(int i=0;i<ie.size();i++){
        if(ie[i]=="}"){
            while(!stk.empty()){
                string tp=stk.top();
                stk.pop();
                if(tp=="{")break;
                else if(tp=="else"){
                    bool flag=0;
                    while(!stk.empty()){
                        tp=stk.top();
                        stk.pop();
                        if(tp=="else_if")flag=1;
                        if(tp=="if")break;
                    }
                    if(flag)elseif_num++;
                    else else_num++;
                }
            }
        }
        else stk.push(ie[i]);
    }    
}

img

对于长成这样的结构,其中的if else_if else对是不被计数的。运行结果正确。

img

在这个样例中,红色代表if else对,绿色代表if else_if else对。运行结果正确。

6.Out(int level) 函数。该函数较为简单,只是对于每次输入的等级,输出对应等级的内容。

附加功能为有:①当输入等级不在[1,4]内时,会报错,提示输入正确等级。②当没有switch case结构时,会输出没有该结构。

inline void Out(int level)
{
    if(!(1<=level && level<=4)){
        cout<<"This is an incorrect level, please enter a level between 1 and 4."<<endl;
        return;
    }    
    if(level>=1)cout<<"total num: "<<Tot_num<<endl;    
    if(level>=2){        
        if(Swt.size()>0){
            cout<<"switch num: "<<Swt.size()<<endl;
            cout<<"case num: ";    
            for(int i=0;i<Swt.size();i++){
                if(i)cout<<" ";
                cout<<Swt[i];
            }        
        }
        else cout<<"There is no Switch structure";
        cout<<endl;
    }
    if(level>=3)cout<<"if-else num: "<<else_num<<endl;
    if(level>=4)cout<<"if-elseif-else num: "<<elseif_num<<endl;            
}

输出测试放在后续完整代码运行时体现。

完整代码

完整代码以及从头开始的多个版本可前往 本次作业的GitHub仓库 https://github.com/LiangYC1021/2021-Software-Engineering-1 查看!

Level4-5为目前的最终版本。

博客部分

任务分解

  • 任务可大致分为前置部分,编码部分,寻找特判、更改代码部分以及博客记录部分。

    • 前置部分:制作代码规范,制作 PSP 表格,分析作业要求,寻找解题思路等。因为很久没用GitHub了所以查阅大量资料才完成上传操作。

    • 编码部分:编写每个函数、整合等。

    • 寻找特判、更改代码部分:因为很多同学跟我说了很多种奇怪的情况,之后对此进行调整。

    • 博客记录部分:按照作业要求编写博客。

PSP表格

见博客最上方。

困难描述及解决办法寻找

本次遇到的困难主要有GitHub仓库的上传和很多特判的情况。

  • 关于仓库上传,上次使用还是2020年上栋哥oop的时候使用的,使用方法早就忘了。查阅了许多资料,最后还是找到了自己当年的博客,才很清晰的了解了上传方式。
  • 至于那些特殊的、奇怪的情况,是在很多同学的告知下不断发现并编码解决的,解决方法就是慢慢自己思考,debug。。

程序测评

正确性

该程序无oj评测,只能通过手造样例来判断正确性。

样例1:作业页面样例,输入了不同的等级,输出相应等级要求。

img

样例2:

该输入其实不是正确的可编译代码,只是为了造特判而随便写的一个例子。

判断了:①字符串内的关键字不计②不以else结尾的 "if else_if else"结构不计数。

img

样例3:

该样例只包含switch-case结构,不论是否以“default"结尾的switch都能判断。

img

样例4:

这个样例的第一块if那边看起来有点奇怪,其实那部分是一个"if else_if else"结构。

img

运行速度

本次作业采用朴素算法,按复杂度分析来说是O(n^2^)的。但由于本题的 n 都偏小,就算采用O(n^3^)的算法可能也不会跑到4、5秒。

起初这种多模式串匹配的问题一拍脑袋想到的是自动机做法,后来朴素做法写着写着就发现好像没时间写优化做法了,重构有点麻烦,后续有空会添加至博客!

总结

  • 编码部分,刚开始拿到这个题目的时候因为平常有在一直写C++代码,觉得这个是一个比较简单的模拟题,但在同学的帮助下发现了很多奇怪的情况,最终一一解决了。但比较遗憾的是在ddl前没写个AC自动机的强化版本,希望后续有时间的时候是真的能去写出来并发布!
  • 作业中的一些要求,比如PSP表格的制作、单元测试、覆盖率优化、性能优化等是之前没了解过的,在此次作业中做的不是特别好,后续会学习使用.
  • 此次收获最大的部分我觉得是GitHub的熟悉与使用,现在了解后觉得git雀食挺有用的,它可以在多人协作编码时多线程工作,也可也很直观的看到前后版本的更新变化,进行版本控制。但git命令用的比较少,在建立了本地仓库与远程仓库的连接后都是用GitHub desktop进行commit,感觉比git命令方便.同时也知道了如何正确地使用git修改之前的commit(应该update而不是create).
  • 现在是凌晨三点,真的写了非常久,白天有空再提交.
  • img

...全文
493 2 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
KimSton 2021-09-29
  • 打赏
  • 举报
回复

没有太大问题,但有几点要主要:
1.解题思路可以先写出,这样会比较清晰;
2.截图标注要么做好要么不做;
3.作业不够简约美观;
4.文件规范未给完整

L1angYC13 2021-09-20
  • 打赏
  • 举报
回复 1

本地typora写完上传后,图片巨糊,一级标题与低等级的标题大小差距不大,只能说csdn很奇怪了

189

社区成员

发帖
与我相关
我的任务
社区描述
福州大学软件工程教学,推行邹欣老师“构建之法”。
软件工程 高校
社区管理员
  • Dawnfox
  • REP1USONE
  • 纪华裕
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧