软件工程基础课-个人项目纪实

  • 个人项目纪实
    • 2018.3.21 Github&Git
    • 2018.3.22 结构分析
    • 2018.3.23 暴力回溯算法
    • 2018.3.24 生成终局OK & 新BUG
    • 2018.3.25 头文件顺序BUG & 代码分析初体验
    • 2018.3.26 版本回退 & 头文件重复包含错误 & 零代版本
    • 2018.3.27 代码风格修改
    • 2018.3.29
    • 2018.3.30 优化加速
    • 2018.4.1 取消跟踪部分文件 && 单元测试
      • 单元测试
    • 2018.4.3 代码覆盖率分析 && 终于告一段落了
      • 代码覆盖率分析
      • 终于要告一段落了

个人项目纪实

为什么要单独写个纪实呢为感觉实践过程太尼玛坑爹了,处处中招,各种触发警报,各种又红又黄的提示,都看不下去了,想想也是,这是我的第一次应该是正式的项目工程了,要会用github、git进行版本管理,还有用宇宙第一IDE进行测试、性能分析等等,所有的这种工程实践都是第一次去做,难免磕磕碰碰,这些经历的记录还是非常有意义的。


2018.3.21 Github&Git

今天第一次在github上建仓库,我的第一个仓库——Personal_Suduku。
首先是配置我的个人信息,虽然账号是去年暑假创建的,不过没怎么配置,空空如也。这个比较简单,看一般的教程就会,不过选哪个邮箱作为我的登陆邮箱好头疼,因为邮箱有点多。。。头像简单,这个早就准备好了,虽然有点丑~
然后是在本地用git命令clone我的仓库到指定文件夹,原本想先在本地创建仓库,再推到github上,后来感觉有点麻烦,对小白不友好就放弃了。当然在这个过程之前,要先配置SSH,先在Git Bash中输入进行判断是否安装了SSH,再输入指定RSA算法生成密钥,然后三个回车即可,注意留心它给出的文件夹的位置,不同电脑位置有些不同,然后打开文件夹(注意这个是隐藏文件夹),找到其中的文件,用vscode/sublime text等编辑器打开,尽量别用windows自带的记事本,复制其中的内容并添加到Github上的SSH key上(点击头像旁的小三角,找到并点击,进入个人信息配置界面,再找到并点击,进入后再点,里输入你之前的那个邮箱,里粘贴里复制的内容)。添加SSH key成功后再次打开Git Bash输入它会问你输入即可,然后等待一段时间出现就说明成功了。
接下来就可以从Github上clone仓库了。先去gihub上进入需要clone的项目仓库界面,旁边有个绿色的点击并复制内容然后在Git Bash中输入其中就是刚才复制的内容。然后等待即可。你也可以指定本地保存的仓库位置,不过需要提前使用命令进入指定文件夹,然后输入上面的git clone命令就可以了。
然后说说Visual Studio 2017里的坑,建议大家先下Gihub插件并输登陆。我在VS里添加了一些文件夹,然后想试试能不能commit,结果报错

出现权限错误,想了想,好像没有将新建的文件提交到仓库中,我使用命令看了看,结果提示

意思就是和两个文件没有被跟踪,即没有被添加到仓库中。那么输入两条命令和添加这两个文件。
再取VS里发现可以commit了,然后我们可以同时推送到github上。


2018.3.22 结构分析

今天主要分析了一下程序结构

主体结构

Created with Rapha2.1.2 开始 输入指令 分析指令 求解数独 输出 结束 生成终局 yes no

在分析指令这一块应该还有个箭头指到输出,因为会有错误输入的情况,要输出警告。

2018.3.23 暴力回溯算法

今天又有警告。。。

又是和第一次一样的警告,emmmm,似乎没有完全搞懂这个问题,尴尬,在VS里有个那就进命令行并关闭VS,然后我直接又报错,再试又报错,就是上面那个,咦,看看提示,,那就试试,可以了。难道每次都有全新的产生吗
用VS直接推送虽然爽歪歪,但是还是不够熟练,有好多推送和备注都没对上,我似乎之前几次都是临时保留,然后推送的都是上次的缓存。还要多用用才行,还有,那个版本回退是什么情况前没用过,很好奇具体操作及效果~

晚上写了生成终局的部分,算法没有用多高大上的,就是暴力回溯搜索,有点小bug,为啥只能输出一份终局面全乱码了是我个人觉得算法的思想毫无问题啊,应该是我实现时有地方搞错了。
算了我就是觉得暴力回溯没问题,bug再调调,现在讲一下算法原理吧,这个绝对没问题。
数独的规则应该都知道了,横竖1~9不能有重复,然后每个3×3的小九宫格内又是1~9不能有重复,总共是9×9的大九宫格。
我们看一下这个规则,会发现一个规律,就是第一行有数x后不能再有x,它一定会依次出现在后面的行,同理列也一样,然后其他数也是这样。那么我们如果按数字顺序在第一个小方格内填入1,然后再在第二行某个格填入1,依次类推直到填完9种数,到这里有人会说这样迟早会产生冲突,出现不符合规则的局面,没错,的确会这样,那么我们就从试不了的地方开始回溯,换个数继续试,直到满足位置,这里有时候会回溯好几步才能成功,不过计算机比较快,尤其是用递归实现起来还是相当快的了。
用伪代码描述:

这个算法的出口就是你要生成多少终局,如果不限制的话,让它穷举完。。。应该是6670903752021072936960种,具体介绍在这篇论文Enumerating possible Sudoku grids。


2018.3.24 生成终局OK & 新BUG

刚把生成终局的bug搞定,原来是递归时传入的一个参数输错了。。。它们的类型一样,命名也像,所以就。。。我靠,智障如我!改正之后非常nice,输出还是比较快的。不过还是有不少优化空间,当然核心算法就要改动不少了,目前是没有什么比较好的思路,推倒重来有点。。。看时间吧。
输出借鉴了网上的一个方案,生成的终局不要立刻输出,先存到数组里,然后再一起输出到文件里,这样会比较快,emmmmm,好像很有道理的样子,然后有一次存终局的数组开的太大,好像有20亿级是200亿级后又是运行崩溃,报错内容忘记截了,这块有点脑残了,明明是可以算出来需要多少的,总共9×9数独,加上每个数字后有空格或回车即81×2=162” role=”presentation” style=”position: relative;”>81×2=162,然后每份数独之间空行,再加1,即163,然后压力测试要求有一百万份数独,就是163×106” role=”presentation” style=”position: relative;”>163×106。后来运行OK!
这里提醒各位不要试图用电脑自带的记事本打开这一百万的数独文件,我看了下大小有164MB。

软件工程基础课-个人项目纪实
推荐用vscode、sublime text、vim之类的编辑器开,我因为也在用vscode编程,所以就用vscode开了,基本上秒开,顺带安利一下vscode!
再提醒一个习惯,就是使用构造函数初始化一下创建的对象!析构函数好像没什么用,反正目前没用过,以后说不定。

最最最严重的是VS又给我报了一个诡异的错误,见下:

严重性 代码 说明 项目 文件 禁止显示状态
错误 C3861 “time”: 找不到标识符 Project_Sudoku …personal_sudukuproject_sudokuproject_sudokuproject_sudoku.cpp 16

我一脸懵逼,原本想用time函数给我的程序计个时,结果跟我说time找不到了了看头文件,也有啊,又看了看命名空间也没毛病啊,再看看项目里也没有和这个头文件命名冲突的。。。莫名其妙的错误。。。而且我在编辑时代码智能提示里也可以给出这个函数啊,是找得到的啊。


2018.3.25 头文件顺序BUG & 代码分析初体验

昨天的那个time函数bug解决了,修改很简单,我把各个文件中的头文件移到顶行,再把移到了这些头文件的下面,然后就编译通过了。。。
看的这篇博文error C2065:未声明的标识符错误,大意即不仅要引入相关的头文件,其位置也要放正确。
在网上这个C3861错误或相关的错误问题基本上的解决办法就这样:
1. 是否引用了正确的头文件。
2. 是否引用了正确的命名空间。
3. 是否存在引用的头文件与工程内创建的文件产生命名冲突。
4. 引用的头文件的位置顺序是否正确

这bug真是太迷了。。。还好顺利解决了!后来看到Visual Studio的官方文档里就有简单的提到。。。Visual Studio 中的 C++ 入门

看一下100万的时间,emmmmmmmm,感觉还行!虽然大佬的比我快一个数量级。。。

软件工程基础课-个人项目纪实

下午初试了一下代码分析,因为要求里说提交的代码要经过代码分析工具的分析并消除所有警告。
我给项目配置的规则集是Microsoft 本机建议规则,毕竟是官方文档列举的标准规则集,看了一下描述还行就用了。
在勾选生成时启用C/C++代码分析后马上试了试,然后一下给我爆出25条警告。。。
主要有一下几种(选了些代表,未全列):

警告代码 警告说明 我的解决策略
C26494 Variable ‘end’ is uninitialized. Always initialize an object (type.5: http://go.microsoft.com/fwlink/p/inkID=620421). 因为是变量没有初始化,所以初始化一下即可
C26495 Variable ‘Sudoku::board’ is uninitialized. Always initialize a member variable (type.6: http://go.microsoft.com/fwlink/p/inkID=620422). 又是变量没有初始化,不过这条警告是指向我的类的构造函数,当然也能理解,是成员变量没有初始化,基本上就初始化一下就好,使用的memset()初始化,因为用循环全遍历还是报警告
C26439 This kind of function may not throw. Declare it ‘noexcept’ (f.6: http://go.microsoft.com/fwlink/inkid=853927). 可能不会引发此类型的函数,将其声明为”noexcept”。emmmmm,这个有点迷啊,官方文档是这么说的,自己看吧C26439 SPECIAL_NOEXCEPT,那就按文档里说的显示声明即可
C26485 Expression ‘this->board’: No array to pointer decay (bounds.3: http://go.microsoft.com/fwlink/p/inkID=620415). 无数组到指针的衰减(bounds.3)。。。要炸啊,我C26495用memset()改后就蹦出这个,
C26496 The variable ‘row’ is assigned only once, mark it as const (con.4: https://go.microsoft.com/fwlink/p/inkID=784969). 这个变量就用过一次,要标记为常量,加个const
C26451 Arithmetic overflow: Using operator ‘+’ on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator ‘+’ to avoid overflow (io.2: https://go.microsoft.com/fwlink/inkid=864598). 应用算术运算后进行转换。调用操作符之前将值转换为更广泛的类型以避免溢出。所以改成了,是因为这个数就用了一次,要用常量
C26409 Avoid calling new and delete explicitly, use std::make_unique instead (r.11: http://go.microsoft.com/fwlink/inkid=845485). 避免显式调用 new 和 delete,请改用 std::make_unique (r.11)
C6386 写入到“this->OutArray”时缓冲区溢出: 可写大小为“OutNum*1”个字节,但可能写入了“8”个字节。
C26481 Don’t use pointer arithmetic. Use span instead (bounds.1: http://go.microsoft.com/fwlink/p/inkID=620413). 请勿使用指针算法。改用范围(bounds.1)。
C26401 Do not delete a raw pointer that is not an owner (i.11: http://go.microsoft.com/fwlink/inkid=845474). 请勿删除不是所有者的原始指针(i.11)。用个出错了
C26409 Avoid calling new and delete explicitly, use std::make_unique instead (r.11: http://go.microsoft.com/fwlink/inkid=845485). 避免显式调用 new 和 delete,请改用 std::make_unique (r.11)。这条警告是紧接这上面的 来源:撒旦发射点发射点

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2018年2月19日
下一篇 2018年2月19日

相关推荐