提交 b677d28c 创建 作者: 宋海霞's avatar 宋海霞

modify

上级 352bc4e9
请读者按照下面的步骤完成实验内容,同时,仔细体会DS Lab的基本使用方法。在本实验题目中,操作步骤会编写的尽量详细,并会对DS Lab的核心功能进行具体说明。但是,在后面的实验题目中会尽量省略这些内容,而将重点放在实验相关的源代码上。如有必要,读者可以回到本实验题目中,参考DS Lab的基本使用方法。
# 下载安装包
# 启动DS Lab
在安装有DS Lab的计算机上,可以使用两种不同的方法来启动DS Lab:
- 在桌面上双击“Engintime DS Lab”图标。
或者
- 点击“开始”菜单,在“程序”中的“Engintime DS Lab”中选择“Engintime DS Lab”。
# 登录
DS Lab每次启动后都会弹出一个“登录”对话框,可以进行以下操作:
- 使用已有 CodeCode 帐号进行登录
读者可以在“登录”对话框中填写在 CodeCode 平台中的用户名、密码完成登录。登录成功后,DS Lab的标题栏会显示出读者用来登录的用户名@姓名。
# 主窗口布局
DS Lab的主窗口布局由下面的若干元素组成:
- 顶部的菜单栏、工具栏。
- 停靠在左侧和底部的各种工具窗口。
- 余下的区域用来放置“起始页”和“源代码编辑器”窗口。
>
**`提示:`**菜单栏、工具栏和各种工具窗口的位置可以随意拖动。如果想恢复窗口的默认布局,选择“窗口”菜单中的“重置窗口布局”即可。
>
# 新建实验项目
**新建一个实验项目的步骤如下:**
1. 在“文件”菜单中选择“项目”中的“从 Git 远程库新建项目”菜单项,打开“从 Git 远程库新建项目”对话框。
2. 在“从 Git 远程库新建项目目”对话框中,输入 Git 远程库的URL。
3. 在“项目文件夹名称”中输入新项目使用的文件夹名称“lab1”。
4. 在“项目位置”中输入新项目保存在磁盘上的位置“C:\dslab”。
5. 点击“确定”按钮。
新建完毕后, DS Lab 会自动打开这个新建的项目。在“项目管理器”窗口中(如图1-1所示),根节点是项目节点,各个子节点是项目包含的文件夹或者文件。读者也可以使用“Windows资源管理器”打开磁盘上的“C:\dslab\lab1”文件夹,查看项目中包含的源代码文件。
提示:右键点击“项目管理器”窗口中的项目节点,选择快捷菜单中的“打开所在的文件夹”,即可使用“Windows资源管理器”打开项目所在的文件夹。
![项目管理器](./img/1.png)
# 阅读实验源代码
该实验包含了一个头文件“LinearList.h”和一个C源文件“main.c”。下面对这两个文件的主要内容、结构和作用进行说明:
**main.c文件**
在“项目管理器”窗口中双击“main.c”打开此文件。此文件主要包含了以下内容:
1. 在文件的开始位置,使用预处理命令“#include "LinearList.h"”,包含了LinearList.h文件。
2. 定义了main函数。在其中实现了线性表的初始化,然后调用了两次线性表的插入函数InsertBefore,第一次调用插入成功,第二次调用插入失败。
3. 在main函数的后面,定义了线性表的插入函数InsertBefore。关于此函数的功能、参数和返回值,可以参见其注释。注意,此函数的函数体还不完整,留给读者完成。
**LinearList.h文件**
在“项目管理器”窗口中双击“LinearList.h”打开此文件。此文件主要包含了以下内容:
1. 包含用到的C标准库头文件。目前只包含了标准输入输出头文件“stdio.h”。
2. 包含其他模块的头文件。目前没有其他模块的头文件需要被包含。
3. 定义重要的数据结构。定义了与线性表相关的数据结构。
4. 声明函数。由于在“main.c”文件中,InsertBefore函数定义在main函数之后,而且在main函数中又调用了InsertBefore函数,所以必须在头文件中声明InsertBefore函数,否则无法通过编译。
>
**`提示:`**请读者认真理解这部分内容,其他实验中的源代码文件也严格遵守这些约定,如无特殊情况将不再进行如此详细的说明。
>
# 生成项目
使用“生成项目”功能可以将程序的源代码文件编译为可执行的二进制文件,操作如下:
1. 在“生成”菜单中选择“生成项目”(快捷键是F7)。
在项目生成过程中,“输出”窗口会实时显示生成的进度和结果。如果源代码中不包含语法错误,会在生成的最后阶段提示生成成功。
![生成项目后的“输出”窗口](./img/2.png)
生成项目的过程,就是将项目所包含的每个C源代码文件(.c文件)编译为一个对象文件(.o文件),然后再将多个对象文件链接为一个目标文件(.exe文件)的过程。以本实验为例,成功生成项目后,默认会在“C:\dslab\lab1\Debug" 目录下生成 “main.o”文件和 “LinearList_InsertBefore.exe”文件。
>
**`提示:`**读者可以通过修改项目名称的方法来修改生成的.exe文件的名称。方法是在“项目管理器”窗口中右键点击项目节点,选择快捷菜单中的“重命名”。待项目名称修改后,需要再次生成项目才能得到新的.exe文件。
>
# 解决语法错误
如果在源代码中存在语法错误,在生成项目的过程中,“输出”窗口会显示相应的错误信息(包括错误所在文件的路径,错误在文件中的位置,以及错误原因),并在生成的最后阶段提示生成失败。此时,在“输出”窗口中双击错误信息所在的行,DS Lab会使用源代码编辑器自动打开错误所在的文件,并定位到错误所在的代码行。
**可以按照下面的步骤进行练习:**
1. 在源代码文件中故意输入一些错误的代码(例如删除一个代码行结尾的分号)。
2. 生成项目。
3. 在“输出”窗口中双击错误信息来定位存在错误的代码行,并将代码修改正确。
4. 重复步骤2、3,直到项目生成成功。
# 观察点和演示模式
这里介绍DS Lab提供的两个重要功能:观察点和演示模式。
**观察点**
一个观察点对应一个函数的起始位置和结束位置(称这个函数为观察点函数)。在调试过程中,当程序执行到观察点函数的起始位置和结束位置时就会发生中断,就好像在这两个位置上添加了断点一样。并且,只要在观察点函数内部发生中断(包括命中断点、单步调试等),就会在“转储信息”窗口中显示观察点函数正在操作的数据信息,如果在“演示模式”下,还会在“演示流程”窗口中显示观察点函数的流程信息。
以本实验为例,“观察点”窗口(在“调试”菜单的“窗口”中选择“观察点”,可以打开“观察点”窗口),说明InsertBefore函数是一个观察点函数。
![观察点窗口(未启动调试)](./img/3.png)
启动调试后,在main.c文件InsertBefore函数的开始位置和结束位置的左侧空白处,会显示观察点图标(与“观察点”窗口中左侧的图标一致),当程序执行到InsertBefore函数的开始位置和结束位置时会发生中断。启动调试后,观察点窗口可以显示出观察点所在的“文件”和“地址”。
![观察点窗口(启动调试)](./img/4.png)
**演示模式**
当DS Lab工具栏上的“演示模式”按钮高亮显示时,DS Lab处于演示模式。当在演示模式下调试观察点函数时,会忽略掉其函数体中的所有代码和断点,取而代之的是使用DS Lab提供的演示功能对观察点函数的执行过程和返回值进行演示。此特性可使观察点函数在还未完整实现的情况下,让读者了解到其应该具有的功能和执行过程,从而帮助读者正确实现此函数。
![工具栏上的“演示模式”按钮](./img/5.png)
当工具栏上的“演示模式”按钮没有高亮显示时(鼠标点击工具栏上的“演示模式”按钮可以使其切换状态),DS Lab处于非演示模式。在非演示模式下调试观察点函数时,会使用其函数体中的代码和断点。
# 在演示模式下调试项目
读者可以按照下面的步骤,练习在演示模式下调试项目(主要是调试观察点函数):
1. 保证工具栏上的“演示模式”按钮高亮显示。
2. 在“调试”菜单中选择“启动调试”(快捷键是F5)。
启动调试后,程序会在观察点函数的开始位置处中断。源代码编辑器左侧空白处显示了相应的图标,分别标识了观察点函数的起始位置和结束位置,以及下一行要执行的代码(黄色箭头)。
![启动调试后,在观察点函数的开始位置中断](./img/6.png)
在“可视化数据”窗口中(可以选择“调试”菜单“窗口”中的“可视化数据”打开此窗口),用可视化的方式显示了观察点函数正在操作的数据信息。
![在观察点函数运行时的“可视化数据”窗口](./img/7.png)
在“可视化数据”窗口中主要包含了如下内容:
- 由于使用了线性表的顺序表示(使用数组存储),所以可以发现数据元素在内存中的地址是连续的,两个相邻地址间的差值与一个元素占用的字节数(4个字节)相同。
- 下标从0开始计数,位序从1开始计数。
- 线性表长度范围内的值使用十进制表示,这些值是线性表(数组)在初始化时存储的有效的值;范围外的值使用十六进制表示,由于未被初始化,所以使用了内存中的随机值,该记录所在表格的填充色为灰色。注意,在不同的计算机上调试时,内存中的随机值可能会不同。
- 并且使用带有绿色边框的记录指定出了元素的插入位置。
- 在调试的过程中,可以看到游标的移动,如果对应元素的当前值与上一次值不同时,该元素的值用红色的字体显示出来。
同时,在“转储信息”窗口中(可以选择“调试”菜单“窗口”中的“转储信息”打开此窗口),使用文本的方式显示了观察点函数正在操作的数据信息。
![在观察点函数开始位置中断时的“转储信息”窗口](./img/8.png)
在“转储信息”窗口中主要包含了如下内容:
1. 函数调用信息。对本次观察点函数的调用信息进行了描述,并显示了参数i和参数Elem的值。
2. 函数返回信息。由于此时刚刚进入观察点函数,所以还无法显示其返回信息。当在观察点函数结束位置中断时,即可显示其返回信息。主要对观察点函数的返回值或者操作结果进行描述。
3. 重要的数据信息。主要是对线性表(pList)的信息进行了描述,包括:
- 线性表中元素在内存中的地址。由于使用了线性表的顺序表示(使用数组存储),所以可以发现数据元素在内存中的地址是连续的,两个相邻地址间的差值与一个元素占用的字节数(4个字节)相同。
- 线性表中元素在数组中的下标。从0开始计数。
- 线性表中元素的值。线性表长度范围内的值使用十进制表示,这些值是线性表(数组)在初始化时存储的有效的值;范围外的值使用十六进制表示,由于未被初始化,所以使用了内存中的随机值。注意,在不同的计算机上调试时,内存中的随机值可能会不同。
- 线性表中元素的位序。从1开始计数。如果是还未被占用的数组项,就显示为“空闲”。
- 标识出了元素的插入位置和要插入的元素值。
**按照下面的步骤继续调试:**
1. 在“调试”菜单中选择“继续”(快捷键是F5)。
由于是在“演示模式”下调试观察点函数,DS Lab会忽略掉函数体中的所有代码,取而代之的是使用DS Lab提供的演示功能对观察点函数的执行过程进行演示。所以DS Lab会自动打开“演示流程”窗口(可以选择“调试”菜单“窗口”中的“演示流程”打开此窗口),在其中显示观察点函数的演示流程。观察点函数的演示流程通常采用简洁、直观的语言进行描述(一行描述可能会对应多行C源代码),偶尔也会在读者理解起来比较困难的地方提供C源代码的提示或者直接使用C源代码,目的就是为了方便读者将演示流程快速转换为C源代码。在“演示流程”窗口左侧的空白处,同样使用黄色箭头标识出了下一行要执行的代码(流程)。
![“演示流程”窗口](./img/9.png)
**按照下面的步骤继续调试:**
1. 在“调试”菜单中重复选择“继续”,直到在观察点函数的结束位置中断。DS Lab会单步执行“演示流程”窗口中的每一行(包括循环)。
在调试的过程中,每执行“演示流程”窗口中的一行后,仔细观察“可视化数据”窗口内容所发生的变化,例如:线性表元素的复制,当前的内存值与上一次的内存值进行比较,如果发生了变化,用红色的字体标识出来;游标的移动过程等,进而深入理解在线性表中插入元素的执行过程。
**按照下面的步骤继续调试观察点函数被第二次调用的过程,理解在线性表中插入元素失败的执行过程:**
1. 在“调试”菜单中重复选择“继续”,直到再次在观察点函数的结束位置中断。
**按照下面的步骤结束此次调试:**
1. 在“调试”菜单中重复选择“继续”,直到调试结束。或者,在“调试”菜单中选择“停止调试”。
读者可以在演示模式下重新启动调试,再次执行以上的步骤,仔细体会在“演示模式”下调试观察点函数的过程,以及在线性表中插入元素的过程。
# 验证项目(失败)
这里介绍DS Lab提供的另外一个重要功能:验证功能。
之前提到了main.c文件中的InsertBefore函数还不完整,是留给读者完成的。而当读者完成此函数后,往往需要使用调试功能、或者执行功能,来判断所完成的函数是否能够达到预期的效果,即是否与演示时函数的转储信息、执行过程和返回值完全一致。DS Lab提供的验证功能可以自动化的、精确的完成这个验证过程。
验证功能分为下面三个阶段:
1. 在“演示模式”下执行观察点函数(与工具栏上的“演示模式”按钮是否高亮无关),将产生的转储信息自动保存在文本文件ValidateSource.txt中。
2. 在“非演示模式”下执行观察点函数,将产生的转储信息自动保存在文本文件ValidateTarget.txt中。
3. 自动使用DS Lab提供的文本文件比较工具来比较这两个文件。当这两个文件中的转储信息完全一致时,报告“验证成功”;否则,报告“验证失败”。
当读者完成的函数与演示时函数的执行过程和返回值完全一致时,就会产生完全一致的转储信息,验证功能就会报告“验证成功”;否则,验证功能就会报告“验证失败”,并且允许读者使用DS Lab提供的文本文件比较工具,来查看这两个转储信息文件中的不同之处,从而帮助读者迅速、准确的找到验证失败的原因,进而继续修改源代码,直到验证成功。
**按照下面的步骤启动验证功能:**
- 在“调试”菜单中选择“开始验证”(快捷键是Alt+F5)。在验证过程中,“输出”窗口会实时显示验证各个阶段的执行过程(如清单1-1所示),包括转储信息文件的路径、观察点函数的调用信息和返回信息、以及验证结果。由于InsertBefore函数还不完整,所以验证失败。
------ 已启动验证: 项目: LinearList_InsertBefore, 配置: Debug ------
验证第一阶段:正在使用“演示模式”生成转储信息,并写入源文件...
源文件路径:C:\dslab\lab1\Debug\ValidateSource.txt
InsertBefore 函数的调用信息:在 i=4 位置前面插入元素 Elem=18
InsertBefore 函数的返回信息:插入成功,返回 1
===========================================================================
InsertBefore 函数的调用信息:在 i=11 位置前面插入元素 Elem=20
InsertBefore 函数的返回信息:插入失败,返回 0
===========================================================================
验证第二阶段:正在使用“非演示模式”生成转储信息,并写入目标文件...
目标文件路径:C:\dslab\lab1\Debug\ValidateTarget.txt
InsertBefore 函数的调用信息:在 i=4 位置前面插入元素 Elem=18
InsertBefore 函数的返回信息:插入失败,返回 0
===========================================================================
InsertBefore 函数的调用信息:在 i=11 位置前面插入元素 Elem=20
InsertBefore 函数的返回信息:插入失败,返回 0
===========================================================================
验证第三阶段:正在比较转储信息源文件与目标文件的内容...
比较结果:转储信息源文件与目标文件的内容不同
==================== 验证结果:失败 ====================
- 使用“输出”窗口工具条上的“比较”按钮,查看两个转储信息文件中的内容,即它们之间的不同之处。
![“输出”窗口工具栏上的“比较”按钮](./img/10.png)
>
**`提示:`**
- 在转储信息文件中,只保存了观察点函数开始位置和结束位置的转储信息,并使用单线进行分隔。观察点函数多次被调用的转储信息之间,使用双线进行分隔。
- 在转储信息文件中,为了确保验证功能的准确性,某些信息会被忽略掉(不再显示或使用“N/A”替代),例如内存中的随机值等。
>
# 实现InsertBefore函数
参考以下代码,实现InsertBefore函数。
```c
int InsertBefore(SqList* pList, ElemType Elem, int i)
{
int nIndex;
if((*pList).nLength >= MAX_LENGTH)
return 0;
if(i < 1 || i > (*pList).nLength)
return 0;
nIndex = (*pList).nLength;
while(nIndex >= i)
{
(*pList).Elements[nIndex] = (*pList).Elements[nIndex - 1];
nIndex--;
}
(*pList).Elements[i - 1] = Elem;
(*pList).nLength++;
return 1;
}
```
>
**`提示:`**
- 在“观察点”窗口中,可以在函数名称上点击右键,选择快捷菜单中的“查看演示流程”,DS Lab会打开“演示流程”窗口,并显示观察点函数的演示流程。这样,即使在没有启动调试的情况下,读者也可以方便的查看观察点函数的演示流程。
- 源代码使用“(*pList)”来回避指针操作,如果读者熟悉指针操作,可以进行改写。
>
# 在非演示模式下调试项目
读者在实现了InsertBefore函数后,可以按照下面的步骤,练习在非演示模式下调试项目(主要是调试由读者实现的观察点函数):
1. 在“生成”菜单中选择“生成项目”。如果读者编写的源代码中存在语法错误,修改这些错误,直到可以成功生成项目。
2. 鼠标点击工具栏上的“演示模式”按钮,使其切换到非高亮显示状态。
3. 在“调试”菜单中选择“启动调试”。程序会在观察点函数的开始位置处中断。
4. 在“调试”菜单中重复选择“逐过程”(快捷键是F10),直到在观察点函数的结束位置中断。DS Lab会单步执行观察点函数中的每一行源代码。在调试的过程中,每执行一行源代码后,仔细观察“可视化数据”窗口内所发生的变化,例如线性表元素的复制,游标的移动等,理解在线性表中插入元素的执行过程。
5. 在“调试”菜单中选择“继续”,直到再次在观察点函数的开始位置中断(第二次调用InsertBefore函数)。
6. 在“调试”菜单中重复选择“逐过程”,直到在观察点函数的结束位置中断。理解在线性表中插入元素失败时的执行过程。
以上的练习说明,DS Lab可以让读者在非演示模式下调试项目,并观察“可视化数据”窗口内容所发生的变化,从而理解每一行源代码对内存数据的操作结果。如果读者发现所编写的源代码存在异常行为(例如死循环、数组越界访问或者验证失败),可以在非演示模式下单步调试项目,来查找异常产生的原因。
# 验证项目(成功)
**按照下面的步骤启动验证功能:**
1. 在“调试”菜单中选择“开始验证”。
如果验证失败,读者可以参考之前的内容来查找原因并修改源代码中的错误,直到验证成功。
# 总结
**读者使用DS Lab进行数据结构实验的步骤可以总结如下:**
1. 启动DS Lab。
2. 使用已有的 CodeCode 帐号进行登录。
3. 使用“从 Git 远程库新建项目”功能来新建项目。
4. 在演示模式下调试项目,理解观察点函数的执行过程(通常观察点函数还未完整实现)。
5. 结合观察点函数的演示流程,修改观察点函数的源代码,实现其功能。
6. 生成项目(排除所有的语法错误)。
7. 执行自动化验证。如果验证失败,可以使用“比较”功能在执行结果中查找问题,或者在“非演示模式”下调试项目,从而定位错误的位置,然后回到步骤5。
8. 将当前项目推送到 CodeCode 平台。
9. 退出DS Lab。
# 获得帮助
如果读者在使用DS Lab的过程中遇到问题需要专业的解答,或者有一些心得体会想和其他DS Lab用户分享,欢迎加入DS Lab网上论坛:
- 选择DS Lab“帮助”菜单中的“提交问题或建议”。
或者
- 直接访问https://www.codecode.net/engintime/ds-lab/ds-lab/issues
这里列出了读者在使用DS Lab的过程中可能遇到的一些问题和使用技巧,用于帮助读者更好的使用DS Lab,获得最佳的实验效果。
1. 读者时常会遇到在自己编写的源代码中存在死循环的情况,这就会造成DS Lab的调试功能,特别是验证功能无法自行结束。此时,读者可以选择“调试”菜单中的“停止调试”(快捷键是Shift+F5)来强制结束这些功能。随后,读者可以检查自己编写的源代码,或者在非演示模式下单步调试项目,从而找到造成死循环的原因。
2. 读者时常会遇到的另外一个情况是“数组越界访问”。此时,DS Lab会弹出一个调试异常对话框,读者只要选择对话框中的“是”按钮,就可以立即定位到异常所在的代码行。
3. DS Lab作为一个IDE环境,提供了强大的调试功能,包括单步调试、添加断点、查看变量的值、查看调用堆栈等。读者在调试过程中可以灵活使用这些功能,提高调试效率。注意,在演示模式下,观察点函数中的断点会被忽略。
4. 在演示模式下,对观察点函数只能进行单步调试(无论是按快捷键F5,还是F10),如果观察点函数中存在多次循环,会造成调试过程比较缓慢。此时,读者可以选择“调试”菜单中的“结束观察”(快捷键是Shift+Alt+F5),直接跳转到观察点函数的结束位置中断。
5. 在“可视化数据”窗口中点击右键,选择菜单中的“图像保存为文件”菜单项,可以很方便的将图像保存成文件,用于完成实验报告等工作。
6. “输出”窗口、“演示流程”窗口以及“转储信息”窗口中的文本信息可以被选中并复制(但是不能修改),“可视化数据”窗口中的内容可以被保存为图片(在“可视化数据”窗口中的右键菜单选择“图像保存为文件”菜单项,可以将“可视化数据”窗口中的内容保存为图片),读者可以很方便的将这些信息保存下来,用于完成实验报告等工作。
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论