个人项目作业——wc.exe
一、Github项目地址
https://github.com/PIPIYing/wc
二、项目概况
项目描述
Word Count
1. 实现一个简单而完整的软件工具(源程序特征统计程序)。
2. 进行单元测试、回归测试、效能测试,在实现上述程序的过程中使用相关的工具。
3. 进行个人软件过程(PSP)的实践,逐步记录自己在每个软件工程环节花费的时间。
项目要求
wc.exe 是一个常见的工具,它能统计文本文件的字符数、单词数和行数。这个项目要求写一个命令行程序,模仿已有wc.exe 的功能,并加以扩充,给出某程序设计语言源文件的字符数、单词数和行数。
实现一个统计程序,它能正确统计程序文件中的字符数、单词数、行数,以及还具备其他扩展功能,并能够快速地处理多个文件。
项目功能
具体功能要求
程序处理用户需求的模式为:wc.exe [parameter] [file_name]
基本功能
1. 支持-c参数:返回文件 file.c 的字符数(实现)
2. 支持-w参数:返回文件 file.c 的词的数目(实现)
3. 支持-l参数:返回文件 file.c 的行数(实现)
基本功能列表:
wc.exe -c
file.c //返回文件 file.c 的字符数
wc.exe -w
file.c //返回文件 file.c 的词的数目
wc.exe -l
file.c //返回文件 file.c 的行数
拓展功能
1. 支持-s参数:递归处理目录下符合条件的文件(实现)
2. 支持-a参数:返回更复杂的数据(代码行 / 空行 / 注释行)(实现)
3. 支持*,?参数:可以处理一般通配符(实现)
空行:本行全部是空格或格式控制字符,如果包括代码,则只有不超过一个可显示的字符,例如“{”。
代码行:本行包括多于一个字符的代码。
注释行:本行不是代码行,并且本行包括注释。一个有趣的例子是有些程序员会在单字符后面加注释:
} //注释
在这种情况下,这一行属于注释行。
[file_name]:
文件或目录名,可以处理一般通配符。
高级功能
1. 支持-x参数:程序显示图形界面,用户可以通过界面选取单个文件,程序就会显示文件的字符数、行数等全部统计信息(未实现)
2. 支持-s、-a和一般通配符(*,?)参数:返回当前目录及子目录中所有*.c 文件的代码行数、空行数、注释行数(实现)
-x 参数。这个参数单独使用。如果命令行有这个参数,则程序会显示图形界面,用户可以通过界面选取单个文件,程序就会显示文件的字符数、行数等全部统计信息。
需求举例:
wc.exe -s -a *.c
返回当前目录及子目录中所有*.c 文件的代码行数、空行数、注释行数。
三、解题思路
看完题目描述和项目要求,明确这是一个cmd下的命令行系统,通过在cmd界面输入命令行来执行相关功能。
由于本人还没有学过Java,所以本次项目采用了C语言来完成。其中主要用到了头文件stdio.h定义的关于文件的函数,再基于各个功能模块进行分析。
四、设计实现过程
通过分析功能,将每个功能写成一个接口,再通过main函数接收命令行来调用相关功能的接口,实现功能并在cmd打印相关信息。
基本接口如下:
int countChar(char path[N], char
file[N]);
功能:统计文件字符数
设计:把基本路径和文件名拼接,调用函数fopen_s读取文件
1. 若文件不存在,打印信息
2. 若文件存在,则统计字符数(不包括中文字)和中文字(包括中文字符,其中中文字和中文字符各占2个字符位),打印字符数和中文字数
int countWord(char path[N], char
file[N]);
功能:统计文件单词数
设计:把基本路径和文件名拼接,调用函数fopen_s读取文件
1. 若文件不存在,打印信息
2. 若文件存在,则通过统计空格数来统计单词数,打印单词数
int countLine(char path[N], char
file[N]);
功能:统计文件行数
设计:把基本路径和文件名拼接,调用函数fopen_s读取文件
1. 若文件不存在,打印信息
2. 若文件存在,则通过函数fgets按行读取字符的特性,统计行数,打印行数
int countElse(char path[N], char
file[N]);
功能:统计文件代码行数、空行数和注释行数
设计:把基本路径和文件名拼接,调用函数fopen_s读取文件
1. 若文件不存在,打印信息
2. 若文件存在,则三种行数的判断规则如下:
a.代码行:调用函数fgets按行读取字符,除去空格、换行、\t之外都计入字符数,最后字符数>1即为代码行
b.空行:调用函数fgets按行读取字符,除去空格、换行、\t之外都计入字符数,最后字符数<1即为空行
c.注释行:分为//和/* */。前者读取到两个’/’即为注释行,后者读取到开始符号/*和结束符号*/之间的行均为注释行
3. 最后打印代码行数、空行数和注释行数
int searchFile(char path[N],char
mode[N],int tag);
功能:递归查找符合条件的文件
设计:通过拼接文件的查找路径,根据需求,调用函数_findfirst获取文件句柄
1. 若文件句柄=-1,则文件不存在
2. 根据文件句柄遍历文件并打印符合需求的文件名;有子目录则返回该函数,进行递归操作
int splitPath(char path[N],char
mode[N]);
功能:拆分在cmd下输入的完整路径
设计:检查最后一个’/’后是不是文件名或一般通配符,并标记
1. 路径符合要求,返回基本路径和文件名或一般通配符
2. 路径不符合要求,则打印错误信息
五、代码说明
统计字符数
1 //统计字符数
2 int countChar(char path[N], char file[N])
3 {
4 FILE* fp = NULL;
5 errno_t err;
6 //英文字符计数器和中文字符计数器
7 int n = 0, nC = 0;
8 int c[M];
9 int i = 0;
10 char filePath[N] = { 0 };
11
12 strcpy_s(filePath, path);
13 strcat_s(filePath, file);
14
15 err = fopen_s(&fp, filePath, "r");
16 if (fp == NULL)
17 {
18 printf("该文件不存在。\n");
19 return -1;
20 }
21 else {
22 for (i = 0; i < M; i++) {
23 c[i] = fgetc(fp);
24 if (feof(fp)) break;
25 else {
26 if (c[i] > 127) {
27 //每个中文字和中文符号各占2个字符位
28 c[i + 1] = fgetc(fp);
29 i += 2;
30 //统计中文字
31 nC++;
32 }
33 else if (c[i] < 0)
34 break;
35 //统计字符数(包括字母、数字、英文符号、空格、换行,不包括中文字符)
36 else n++;
37 }
38 }
39 n -= 1;
40 printf("字符数:%d\t中文字:%d\n", n,nC);
41 }
42
43 fclose(fp);
44 return n;
45 }
统计单词数
1 //统计单词数
2 int countWord(char path[N], char file[N]) {
3 FILE* fp = NULL;
4 errno_t err;
5 int c;
6 //计数器
7 int n = 0;
8 char filePath[N] = { 0 };
9
10 strcpy_s(filePath, path);
11 strcat_s(filePath, file);
12
13 err = fopen_s(&fp, filePath, "r");
14 if (fp == NULL)
15 {
16 printf("该文件不存在。\n");
17 return -1;
18 }
19 do
20 {
21 c = fgetc(fp);
22 if (feof(fp)) break;
23 //通过空格来统计单词数
24 else if (c == ' ') n++;
25 } while (1);
26
27 printf("单词数:%d\n", n);
28
29 return n;
30 }
统计行数
1 //统计行数
2 int countLine(char path[N], char file[N]) {
3 FILE* fp = NULL;
4 errno_t err;
5 char b[N];
6 //计数器
7 int n = 0;
8 char filePath[N] = { 0 };
9
10 strcpy_s(filePath, path);
11 strcat_s(filePath, file);
12
13 err = fopen_s(&fp, filePath, "r");
14 if (fp == NULL)
15 {
16 printf("该文件不存在。\n");
17 return -1;
18 }
19 do {
20 //fgets()函数按行读取字符,每读一次为一行,以此计数
21 if (fgets(b, N, fp)) n++;
22 else break;
23 } while (1);
24
25 printf("行数:%d\n", n);
26
27 return n;
28 }
统计代码行、空行和注释行
1 //统计代码行、空行和注释行
2 int countElse(char path[N], char file[N]) {
3 FILE* fp = NULL;
4 errno_t err;
5 char b[N];
6 //记录代码行数,记录空行数,记录注释行,记录数组长度,记录字符长度,记录两种注释行数(//和/* */),记录三种行的总数
7 int codeLine = 0, blankLine = 0, commentLine = 0, length = 0, count_char = 0, countC1 = 0, countC2 = 0, sum = 0;
8 int i, j;
9 //tag是查找/* */注释符号的前半部分的标记,查找成功记为1,查找失败记为0
10 int tag = 0;
11 char filePath[N] = { 0 };
12
13 strcpy_s(filePath, path);
14 strcat_s(filePath, file);
15
16 err = fopen_s(&fp, filePath, "r");
17 if (fp == NULL)
18 {
19 printf("该文件不存在。\n");
20 return -1;
21 }
22 do {
23 //fgets()函数按行读取字符
24 if (fgets(b, N, fp)) {
25 length = strlen(b);
26 for (i = 0, count_char = 0; i < length; i++) {
27 if (b[i] != ' ' && b[i] != '\n' && b[i] != '\t')
28 //在一行中,除去空格、换行、\t之外都计入字符数
29 count_char++;
30 if (b[i] == '/' && b[i + 1] == '/') {
31 //第一种注释情况,读入的一行为注释行,跳出循环
32 countC1++;
33 //注释行不属于代码行
34 if (count_char > 1) codeLine--;
35 //注释行不属于空行
36 else blankLine--;
37 break;
38 }
39 if (tag == 1) {
40 countC2++;
41 //在该行查找注释的结束符号
42 for (j = i; j < length; j++) {
43 if (b[j] == '*' && b[j + 1] == '/') {
44 //查找结束符号成功,该行为注释行
45 //注释行不属于代码行
46 if (count_char > 1) codeLine--;
47 //注释行不属于空行
48 else blankLine--;
49 //现查找注释行前半部分失败
50 tag = 0;
51 break;
52 }
53 }
54 //tag=0说明该行是完整的注释行,同行查找结束符号成功
55 if (tag == 0) break;
56 //否则同行查找结束符号失败,把tag置为1
57 else {
58 //注释行不属于代码行
59 if (count_char > 1) codeLine--;
60 //注释行不属于空行
61 else blankLine--;
62 break;
63 }
64 }
65 if (b[i] == '/' && b[i + 1] == '*' && tag == 0) {
66 countC2++;
67 tag = 1;
68 //第二种注释情况,读入的一行为注释行,同行查找结束符号
69 for (j = i + 2; j < length - 2; j++) {
70 if (b[j] == '*' && b[j + 1] == '/') {
71 //查找结束符号成功,该行为注释行
72 countC2++;
73 //注释行不属于代码行
74 if (count_char > 1) codeLine--;
75 //注释行不属于空行
76 else blankLine--;
77 //现查找注释行前半部分失败
78 tag = 0;
79 break;
80 }
81 }
82 //tag=0说明该行是完整的注释行,同行查找结束符号成功
83 if (tag == 0) break;
84 //否则同行查找结束符号失败,把tag置为1
85 else {
86 //注释行不属于代码行
87 if (count_char > 1) codeLine--;
88 //注释行不属于空行
89 else blankLine--;
90 break;
91 }
92 }
93 }
94 //字符数大于1为代码行,否则为空行
95 if (count_char > 1) codeLine++;
96 else blankLine++;
97 }
98 else break;
99 } while (1);
100
101 commentLine = countC1 + countC2;
102 sum = codeLine + blankLine + commentLine;
103
104 printf("代码行:%d\t", codeLine);
105 printf("空白行:%d\t", blankLine);
106 printf("注释行:%d\n", commentLine);
107
108 //返回注释行,作为单元测试的内容
109 return commentLine;
110 }
递归查找符合条件的文件
1 //递归查找符合条件的文件
2 int searchFile(char path[N],char mode[N],int tag) {
3 //文件句柄
4 intptr_t Handle1;
5 intptr_t Handle2;
6 //文件结构体
7 struct _finddata_t fileInfo1;
8 struct _finddata_t fileInfo2;
9 //特定文件查找路径、所有文件的查找路径、递归路径
10 char nowPath_file[N] = { 0 };
11 char nowPath_folder[N] = { 0 };
12 char nowPath_re[N] = { 0 };
13 //查找文件和文件夹的通识符
14 char mode_N[N] = { "*.*" };
15 int i, num = 0;
16 //标记文件夹
17 int mark = 0;
18
19 //基本路径
20 strcpy_s(nowPath_file, path);
21 strcpy_s(nowPath_folder, path);
22 strcpy_s(nowPath_re, path);
23 //拼接特定文件和所有文件的查找路径
24 strcat_s(nowPath_file, mode);
25 strcat_s(nowPath_folder, mode_N);
26
27 //根目录的文件句柄
28 Handle1 = _findfirst(nowPath_folder, &fileInfo1);
29 //.c类型文件的文件句柄
30 Handle2 = _findfirst(nowPath_file, &fileInfo2);
31
32 if ((Handle2 = _findfirst(nowPath_file, &fileInfo2)) == -1L)
33 printf("该目录中没有这种类型的文件。\n");
34 else {
35 //查找文件后缀名.
36 for (i = 0; i < strlen(fileInfo2.name); i++) {
37 if (fileInfo2.name[i] == '.') {
38 mark = 1;
39 break;
40 }
41 }
42 //只打印文件名,不打印文件夹名
43 if (mark == 1 && strcmp(fileInfo2.name, ".") != 0 && strcmp(fileInfo2.name, "..") != 0) {
44 printf("文件名:%s\n", fileInfo2.name);
45 //单元测试的参数
46 num = num + 1;
47 //实现指令的功能
48 if (tag == 1) {
49 countChar(nowPath_re, fileInfo2.name);
50 }
51 else if (tag == 2) {
52 countWord(nowPath_re, fileInfo2.name);
53 }
54 else if (tag == 3) {
55 countLine(nowPath_re, fileInfo2.name);
56 }
57 else if (tag == 4) {
58 countElse(nowPath_re, fileInfo2.name);
59 }
60 else;
61 mark = 0;
62 }
63 //_findnext是以_findfirst为开始接着查找以下符合H2(.c)的文件并打印
64 while (_findnext(Handle2, &fileInfo2) == 0) {
65 //查找文件后缀名.
66 for (i = 0; i < strlen(fileInfo2.name); i++) {
67 if (fileInfo2.name[i] == '.') {
68 //标记文件夹
69 mark = 1;
70 break;
71 }
72 }
73 //只打印文件名,不打印文件夹名
74 if (mark == 1 && strcmp(fileInfo2.name, ".") != 0 && strcmp(fileInfo2.name, "..") != 0) {
75 printf("文件名:%s\n", fileInfo2.name);
76 //单元测试参数
77 num = num + 1;
78 //实现指令的功能
79 if (tag == 1) {
80 countChar(nowPath_re, fileInfo2.name);
81 }
82 else if (tag == 2) {
83 countWord(nowPath_re, fileInfo2.name);
84 }
85 else if (tag == 3) {
86 countLine(nowPath_re, fileInfo2.name);
87 }
88 else if (tag == 4) {
89 countElse(nowPath_re, fileInfo2.name);
90 }
91 else;
92 }
93 mark = 0;
94 }
95 _findclose(Handle2);
96 }
97
98 if ((Handle1 = _findfirst(nowPath_folder, &fileInfo1)) == -1L)
99 printf("该目录中没有文件。\n");
100 else {
101 do {
102 if (fileInfo1.attrib & _A_SUBDIR) {
103 //判断是否为"."当前目录,".."上一层目录,查找子目录的文件
104 if ((strcmp(fileInfo1.name, ".") != 0) && (strcmp(fileInfo1.name, "..") != 0))
105 {
106 printf("\n%s文件夹\n", fileInfo1.name);
107 //拼接子目录的路径,进行递归查找
108 strcat_s(nowPath_re, fileInfo1.name);
109 strcat_s(nowPath_re, "\\");
110 //单元测试参数
111 num += searchFile(nowPath_re, mode, tag);
112 }
113 }
114 //循环该目录中所有文件
115 } while (_findnext(Handle1, &fileInfo1) == 0);
116 _findclose(Handle1);
117 }
118 //返回单元测试参数
119 return num;
120 }
拆分在cmd下输入的完整路径
1 //拆分在cmd下输入的完整路径
2 int splitPath(char path[N],char mode[N]) {
3 int i, j, k, len;
4 //1表示到符合输入要求的路径
5 int mark = 0;
6 len = strlen(path);
7
8 for (i = len; i >= 0; i--) {
9 if (path[i] == '\\') {
10 for (j = i; j < len; j++) {
11 //是文件/通配符的标志
12 if (path[j] == '.' || path[j] == '*') {
13 for (k = 0; i < len; i++, k++) {
14 mode[k] = path[i + 1];
15 path[i + 1] = '\0';
16 }
17 mark = 1;
18 }
19 if (mark == 1) break;
20 }
21 if (mark == 1) break;
22 }
23 }
24 if (mark == 1) return 1;
25 else printf("输入文件路径有误,请重新输入!\n例:E:\\test\\file.c\n");
26 return -1;
27 }
主函数
1 //主函数
2 int main(int argc, char* argv[]) {
3 //char path[N] = { "E:\\vs project\\wcTest\\" };
4 //char mode[N] = { "*.*" };
5 //char file[N] = { "test.c" };
6 char path[N] = { "E:\\test" };
7 char mode[N] = { 0 };
8 //1是-c,2是-w,3是-l,4是-a
9 int tag = 0;
10
11 //统计
12 if (strcmp(argv[1], "-c") == 0) {
13 strcpy_s(path, argv[2]);
14 if (splitPath(path, mode) == 1) countChar(path, mode);
15 }
16 else if (strcmp(argv[1], "-w") == 0) {
17 strcpy_s(path, argv[2]);
18 if (splitPath(path, mode) == 1) countWord(path, mode);
19 }
20 else if (strcmp(argv[1], "-l") == 0) {
21 strcpy_s(path, argv[2]);
22 if (splitPath(path, mode) == 1) countLine(path, mode);
23 }
24 else if (strcmp(argv[1], "-a") == 0) {
25 strcpy_s(path, argv[2]);
26 if (splitPath(path, mode) == 1) countElse(path, mode);
27 }
28 //拓展功能
29 else if (strcmp(argv[1], "-s") == 0 && strcmp(argv[2], "-c") == 0) {
30 tag = 1;
31 strcpy_s(path, argv[3]);
32 if (splitPath(path, mode) == 1) searchFile(path, mode, tag);
33 }
34 else if (strcmp(argv[1], "-s") == 0 && strcmp(argv[2], "-w") == 0) {
35 tag = 2;
36 strcpy_s(path, argv[3]);
37 if (splitPath(path, mode) == 1) searchFile(path, mode, tag);
38 }
39 else if (strcmp(argv[1], "-s") == 0 && strcmp(argv[2], "-l") == 0) {
40 tag = 3;
41 strcpy_s(path, argv[3]);
42 if (splitPath(path, mode) == 1) searchFile(path, mode, tag);
43 }
44 else if (strcmp(argv[1], "-s") == 0 && strcmp(argv[2], "-a") == 0) {
45 tag = 4;
46 strcpy_s(path, argv[3]);
47 if (splitPath(path, mode) == 1) searchFile(path, mode, tag);
48 }
49 //批处理同类型文件
50 else if (strcmp(argv[1], "-s") == 0) {
51 strcpy_s(path, argv[2]);
52 if (splitPath(path, mode) == 1) searchFile(path, mode, tag);
53 }
54 else printf("指令有误,请重新输入!\n");
55
56 system("pause");
57
58 return 0;
59 }
六、测试运行
测试运行分为三个模块:单元测试、回归测试、运行测试
1. 单元测试
单元测试分为三部分测试:
TestMethod1:统计字符数、单词数、行数、其他行数的测试,通过返回值确定函数是否正确
TestMethod2:递归文件的测试,通过目录(包括子目录)中的文件个数确定函数是否正确
TestMethod3:拆分路径的测试,通过返回值确定函数是否正确
测试结果如下图:
小结:单元测试通过,编写的各个接口可用
2. 回归测试
回归测试分为五部分测试,如下所示。
空文件测试:
只有一个字符的文件测试:
只有一个词的文件测试:
只有一行的文件测试:
一个典型的源文件测试:
小结:回归测试通过
3. 运行测试
运行需求中的各条命令行,并展示运行测试结果如下。
基本功能
wc.exe –c E:\test\file.c
wc.exe –w E:\test\file.c
wc.exe –l E:\test\file.c
拓展功能
测试文件夹如图所示
wc.exe –s E:\test\*.c
wc.exe –a E:\test\file.c
wc.exe –s E:\test\*
wc.exe –s E:\test\file?.c
高级功能
测试文件夹如图所示
wc.exe –s –a E:\test\*.c
wc.exe –s –a E:\test\*
七、PSP表格
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
||
· Estimate |
· 估计这个任务需要多少时间 |
300 |
360 |
Development |
开发 |
||
· Analysis |
· 需求分析 (包括学习新技术) |
10 |
30 |
· Design Spec |
· 生成设计文档 |
10 |
20 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
10 |
10 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
5 |
5 |
· Design |
· 具体设计 |
30 |
40 |
· Coding |
· 具体编码 |
180 |
240 |
· Code Review |
· 代码复审 |
60 |
50 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
120 |
90 |
Reporting |
报告 |
||
· Test Report |
· 测试报告 |
60 |
40 |
· Size Measurement |
· 计算工作量 |
20 |
20 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 |
15 |
合计 |
535 |
560 |
八、项目小结
1. 本次项目采用C语言完成,编码过程较为复杂,同时也学习到了C语言的一些补充知识。
2. 结合PSP表格可以认识到自己在预想和实际开发中的不足之处。
3. 要学习更多的语言来便捷地进行项目的开发
九、学习进度条
第N周 |
新增代码(行) |
累计代码(行) |
本周学习耗时(小时) |
累计学习耗时(小时) |
重要成长 |
2 |
451 |
451 |
9 |
9 |
了解了c语言头文件stdio.h中的其他函数 |
个人项目作业——wc.exe的更多相关文章
- 个人项目作业WC(JAVA)
GitHub地址:https://github.com/1666403186/WC 一.题目描述 Word Count1. 实现一个简单而完整的软件工具(源程序特征统计程序).2. 进行单元测试.回归 ...
- 个人项目(WC.exe)(java)(基于图形界面)
一.Github项目地址:https://github.com/Leungdc/ENhomework 二.PSP: PSP2.1 Personal Software Process Stages 预估 ...
- 个人项目(wc.exe)
一.项目在GitHub上的地址: ·https://github.com/DawsonHuang/Word_Count 二.项目描述: ·项目名:WordCount(以下简称WC或项目) ·项目简述: ...
- 个人项目作业WC
项目github地址 https://github.com/gs735028922gs/wordc 项目相关要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写 ...
- 个人项目作业--WC的实现
GitHub项目地址 https://github.com/1721819634/WC 1.Word Count 项目要求: wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数. ...
- 个人项目作业(wc.exe)
1.GitHub项目地址 https://github.com/QiuBin666/WC 项目介绍: 题目描述 Word Count1. 实现一个简单而完整的软件工具(源程序特征统计程序).2. 进行 ...
- 软工作业No.1。Java实现WC.exe
网址:https://github.com/a249970271/WC WC 项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写一个命令行程序,模仿已有w ...
- 个人项目 wc.exe
GitHub地址:https://github.com/oAiuo/wordCount 一.题目描述 Word Count1. 实现一个简单而完整的软件工具(源程序特征统计程序).2. 进行单元测试. ...
- 个人项目WC.exe Node.js+electron实现
前言 实现语言:Javascript 编译工具:webstorm GitHub:https://github.com/NPjuan/WC.git 项目要求 wc.exe 是一个常见的工具,它能统计文本 ...
随机推荐
- [MIT6.006] 9. Table Doubling, Karp-Rabin 双散列表, Karp-Rabin
在整理课程笔记前,先普及下课上没细讲的东西,就是下图,如果有个操作g(x),它最糟糕的时间复杂度为Ο(c2 * n),它最好时间复杂度是Ω(c1 * n),那么θ则为Θ(n).简单来说:如果O和Ω可以 ...
- BPMN开源工作流编辑器bpmn-js落地实践中文文档
BPMN是一套标准的业务流程建模符号规范,bpmn-js是基于此规范实现的一套渲染工具包和web建模器,可以实现拖拽生成工作流程图,效果大概如下 最近刚好用到,研究之后写了系列文章,分享给有需要的小伙 ...
- 双数组字典树(Double Array Trie)
参考文献 1.双数组字典树(DATrie)详解及实现 2.小白详解Trie树 3.论文<基于双数组Trie树算法的字典改进和实现> DAT的基本内容介绍这里就不展开说了,从Trie过来的同 ...
- HBuilderX SVN地址更改(SVN服务器IP地址变更)
HBuilderX编辑器中无法修改SVN地址,需要手动在SVN工具中修改 修改步骤: 1.右键编辑器中的SVN项目,选择打开文件所在目录 2.目录中空白处右键,选择TortoiseSVN --> ...
- JS逆向课程笔记
扩展知识 Sources-js代码格式化
- 学习笔记:[算法分析]数据结构与算法Python版[基本的数据结构-上]
线性结构Linear Structure ❖线性结构是一种有序数据项的集合,其中 每个数据项都有唯一的前驱和后继 除了第一个没有前驱,最后一个没有后继 新的数据项加入到数据集中时,只会加入到原有 某个 ...
- tp5 上传图片(自定义图片路径)
控制器调用 /** * [goods_addimg 图片上传] * @return [type] [description] */ public function addimg(){ if (requ ...
- div可以滚动但不显示滚动条
首先有3个div, 第1个,固定大小是200*200(单位为px,下同) 第2个,不固定大小,其大小要用第3个div把个撑开,但是这个div必需要有滚动条, 第3个,固定大小与第1个div保持一致20 ...
- Xrepo:一个现代化的跨平台 C/C++ 包管理器
xrepo 是一个基于 Xmake 的跨平台 C/C++ 包管理器. 项目源码 官方文档 它基于 xmake 提供的运行时,但却是一个完整独立的包管理程序,相比 vcpkg/homebrew 此类包管 ...
- python自动化测试pytest框架
pytest和unittest都是python中的测试框架,pytest相比unittest 更加的灵活,具体体现在 以下几点 1.写测试方法时不用继承类 2.前置后置放在一起 2.1如果是全局共享的 ...