大家好,今天我继续更新博客。
今天的主要任务是将之前实现的生成终局和求解数独这两个功能进行合并,并且能够处理各种异常的命令行输入。
Github完整项目地址:https://github.com/surpasss/software-engineering
1.进行合并
之前生成终局的CreateSudoku函数是传递一个参数n,指的是需要生成终局的数量;求解数独的SolveSudoku函数为了简单起见,没有传入参数,而是在SolveSudoku函数里打开问题文件。但是今天合并的时候从低耦合高内聚的角度考虑,觉得SolveSudoku函数应该传递问题文件的文件名这个参数,这样的话问题文件的打开读入关闭全在SolveSudoku函数里,具有高内聚的特点。这里反思一下,接口的设计在写代码之前就应该设计好,合并的时候就不用修改接口了,否则在一些问题上接口不匹配会比较麻烦。
这道题中,进行合并不难,通过判断命令行参数的格式选择调用对应的函数。对命令行输入进行处理是通过定义在main函数的两个形式参数——argc和*argv,argv是字符串数组,argc是字符串数组中字符串的个数,而命令行读取字符串和scanf函数读取字符串是一样的,以空格或换行符结束一个字符串。因此合并子功能很容易实现,更关键的是异常处理。
2.异常处理
依据题意,只有sudoku.exe -c num和sudoku.exe -s path两个合法输入,分别代表生成终局和求解数独,并且要求能处理生成终局的各种异常情况,而对求解数独则没做要求,并且保证数独题目的文件格式正确。因此从题目角度出发,当前我只对生成终局处理各种异常输入,至于求解数独的各种输入异常以后再完善。
对此,有以下几点情况需要考虑:
①.参数个数是否正确
②.第二个参数是否是"-c"
③.第三个参数是否[1, 1000000]之间的整型数字
以下是我的测试用例:
输入 | 是否合法 |
---|---|
sudoku.exe -c | 否 |
sudoku.exe -x | 否 |
sudoku.exe -c20 | 否 |
sudoku.exe -c abc | 否 |
sudoku.exe -c 123.45 | 否 |
sudoku.exe -c 12345 | 是 |
sudoku.exe -c -1 | 否 |
sudoku.exe -c 0 | 否 |
sudoku.exe -c 1 | 是 |
sudoku.exe -c 999999 | 是 |
sudoku.exe -c 1000000 | 是 |
sudoku.exe -c 1000001 | 否 |
sudoku.exe -c 001 | 否 |
测试结果如下:
可以看到,全都满足,并且发现生成1e6个终局不用两秒(已检查sudoku文件,无误),比之前还短了很多呢。
3.实现代码:
首先是ConverNum函数的定义
//define.cpp
#include "define.h"
int ConvertNum(char *s)
{
int len = strlen(s);
if (len >= 7 && strcmp(s, "1000000"))//排除大于1e6的整数
return -1;
else if (s[0] == '0')//排除0和前缀0
return -1;
int num = 0;
for (int i = 0; i < len; i++)
{
if (!isdigit(s[i]))//排除非数字字符
return -1;
else
num = num * 10 + s[i] - '0';
}
return num;
}
接下来是主函数的定义
//main.cpp
#include "define.h"
int main(int argc, char* argv[])
{
clock_t start = clock();
if (argc != 3)//参数数量出错
{
cout << "Wrong! please input right format." << endl;
return 0;
}
if (strcmp(argv[1], "-c") == 0)
{
/*
检查argv[2],如果合法,返回对应整数;
如果不合法,返回-1
*/
int num = ConvertNum(argv[2]);
if (num == -1)//argv[2]不合法
{
cout << "Wrong! please input right format." << endl;
return 0;
}
else//argv[2]合法
{
CreateSudoku(num);
cout << "Create sudoku successfully" << endl;
}
}
else if (strcmp(argv[1], "-s") == 0)
{
SolveSudoku(argv[2]);
}
else//argv[1]既不是"-c",也不是"-s"
{
cout << "Wrong! please input right format." << endl;
return 0;
}
//打印总的运行时间
clock_t end = clock();
cout << "Runing time : " << ((double)end - start) / CLOCKS_PER_SEC << "s\n";
}