54
使使 VC++6.0 使使使使

使用 VC++6.0 调试程序

  • Upload
    chika

  • View
    99

  • Download
    6

Embed Size (px)

DESCRIPTION

使用 VC++6.0 调试程序. 调试程序. 调试运行 单步跟踪 单步跳进跟踪 观察自动变量 观察其他变量 停止调试. 1 :打开 jiecheng 项目(双击 jiecheng.dsw 文件) 2 : build 该项目,确定程序可以运行 3 :调试运行阶乘程序 4 :设置断点 5 :再次调试运行程序 6 :使用单步执行程序到结束. 1 :打开 jiecheng 项目. 2 : Build 该项目,确定程序可以运行. Go. 3 :调试运行阶乘程序. 4 :设置断点. - PowerPoint PPT Presentation

Citation preview

Page 1: 使用 VC++6.0 调试程序

使用 VC++6.0 调试程序

Page 2: 使用 VC++6.0 调试程序

调试程序 调试运行 单步跟踪 单步跳进跟踪 观察自动变量 观察其他变量 停止调试

Page 3: 使用 VC++6.0 调试程序

1 :打开 jiecheng 项目(双击 jiecheng.dsw文件)

2 : build 该项目,确定程序可以运行 3 :调试运行阶乘程序 4 :设置断点 5 :再次调试运行程序 6 :使用单步执行程序到结束

Page 4: 使用 VC++6.0 调试程序

1 :打开 jiecheng 项目

Page 5: 使用 VC++6.0 调试程序

2 : Build 该项目,确定程序可以运行

Page 6: 使用 VC++6.0 调试程序

3 :调试运行阶乘程序Go

Page 7: 使用 VC++6.0 调试程序

4 :设置断点 将鼠标停留在程序的第 8 行,在第 8 行的任

意地方单击鼠标左键(第 8 行即“ i = i*4;” ) 在工具栏上选择 按钮,为第 8 行设置断点,

以便让程序在此处暂停运行

Page 8: 使用 VC++6.0 调试程序

5 :再次调试运行阶乘程序 注意观察,现在调试运行程序会如何?Go

Page 9: 使用 VC++6.0 调试程序

5 :再次调试运行阶乘程序(续)

程序暂停之处

调试( Debug )工具:控制程序前进步伐查看程序当前状态

Page 10: 使用 VC++6.0 调试程序

6 :使用单步执行到程序结束 设置断点以后,调试运行程序时,程序开始

执行,并且运行到断点处暂停下来,此时我们有机会观察程序的运行情况,并且诊断程序目前的状态是否如我们所预期的那样。

不过我们先不着急观察程序的状态,而是来看看如何控制程序的运行,以便在我们需要的时候让程序暂停下来,并且以我们需要的方式走走停停!

Page 11: 使用 VC++6.0 调试程序

6 :使用单步执行到程序结束 程序停下来了,如何让程序从暂停的地方继

续向前执行? 方法是使用单步执行手段( Step Over )让

程序向前走一步

停止调试停止调试并重新启动调试

单步执行当前位置

Page 12: 使用 VC++6.0 调试程序

熟悉调试工具栏和菜单(只在调试运行时出现)

对比调试运行时出现的调试菜单“ Debug” 和调试工具栏,根据图标查找对应项

Page 13: 使用 VC++6.0 调试程序

观察自动变量

自动变量

Page 14: 使用 VC++6.0 调试程序

观察变量的值及其随程序运行时的变化情况

设置断点,调试运行程序,此时程序暂停在断点处等待

选择 Debug 菜单,找到最后一项“ Quick Watch”

并点击

Page 15: 使用 VC++6.0 调试程序

输入想要观察的变量

变量名 变量的值

点击 Add Watch

Page 16: 使用 VC++6.0 调试程序

点击 Add watch ,看到如下画面

Page 17: 使用 VC++6.0 调试程序

调试观察每一步骤变量 i 的值 点击单步执行按钮或者菜单,程序则向前单

独运行一个步骤

每向前执行一步,就会暂停下来,这样我们就有充足的时间观察所关心的变量名称

观察变量 i 的值的情况

Page 18: 使用 VC++6.0 调试程序

注意在调试过程中 断点不能设置在空白行上面 添加断点和删除断点的方法一样 一个程序中可以设置多个断点 按下 F5 键可以让程序从当前位置向前执行,

直到遇见下一个断点或者程序结束

Page 19: 使用 VC++6.0 调试程序

相关 C 语言基础知识指针:

结构体:

Page 20: 使用 VC++6.0 调试程序

指针

Page 21: 使用 VC++6.0 调试程序

新建 Visual C++ 程序四、利用已有的程序编写新程序

无论是控制台程序,或者是 Windows 窗口程序, Visual C++ 都会要求有对应的项目文件。而且在大多数情况下, C 程序的基本框架都是一致的,例如:都有主函数等等。所以在编写一个新的程序时,可以利用以前编写过的程序,其操作方法有两种。

( 1 )程序复用操作

将已有的程序复用到新程序上的方法很简单,就是将程序内容通过“复制―粘贴”实现。

( 2 )项目复用操作

打开已有的项目文件,将原来的文件删除,利用项目管理增加新程序文件或资源元素等。

Page 22: 使用 VC++6.0 调试程序

新建 Visual C++ 程序

五、项目管理

无论项目是否建立,只要开始程序的编译、链接、运行或调试过程, Visual C++ 就会按项目管理方式进行控制。

例如:当使用文件新建方式建立一个源程序文件后,只要开始编译则 Visual C++ 会自动提示创建项目。

Page 23: 使用 VC++6.0 调试程序

新建 Visual C++ 程序

Page 24: 使用 VC++6.0 调试程序

地址和指针的概念一、指针概述:1、“ &” :地址运算符

2. “*” :指针运算符,取其指向的内容: exp:

&a: 变量 a的地址:

*p: 变量 p的内容;

注: “ &” 不能施加在常数,常量和表达式上;

Page 25: 使用 VC++6.0 调试程序

二、指针变量: 存放某种变量地址的变量称为指针变量。

10

35

….

a

b

2010

2012

p2010

q2012

因此,在 C 语言中,将地址形象化地称为指针

Page 26: 使用 VC++6.0 调试程序

定义一个指针变量 指针变量的定义一般形式为:

     基类型   * 指针变量名 ;例如:

   int i, j, *pi, *pj;

float x, y, *p1, *p2;

指针变量的赋值:使得指针变量指向变量

   指针变量名= &变量名 ;

如: pi=&i; pj=&j; p1=&y; p2=&x;注意:指针变量只能存放指针(地址),且只能是相同类型变量的地址。例如,指针变量 pi 、 pj ,只能接收 int 型、 p1, p2 只能接收 float 型的地址,否则出错。

Page 27: 使用 VC++6.0 调试程序

结构体

Page 28: 使用 VC++6.0 调试程序

指针变量的引用

  在程序中,可以用: * 指针变量名 代替其所指变量。

如若 :

    int i, *p;

p=&i;

则 i=5;  与 *p=5;  的作用相同,即可用 *p 代替 i, 这里 * 号称为指针运算符(或称为间接访问运算符)

Page 29: 使用 VC++6.0 调试程序

指针变量作为函数参数实参:变量地址或已赋值的指针变量,形参:指针变量

功能:地址传送方式,会将改变后的值带回。

例 10.3  通过函数调用实现例 10.2 的功能。swap(int *p1, int *p2){int temp;temp=*p1; *p1=*p2; *p2=temp;}main(){int a, b, *pointer1,*pointer2;scanf("%d%d",&a,&b);pointer1=&a; pointer2=&b;if(a<b) swap(&a,&b);printf("\n%d,%d",a,b);}

Page 30: 使用 VC++6.0 调试程序

 数组与指针1. 概念数组的指针──数组在内存中的起始地址,用数组名表示2.指向数组的指针变量 --- 赋于数组名的指针变量例如, int a [10], *p=a ( 或 *p=&a[0]);或者: int a [10], *p; p = a;

Page 31: 使用 VC++6.0 调试程序

3. 通过指针引用数组元素如果有“ int a [10],*p=a;” ,则:( 1) p+i==a+i==&a[i] 。 ( 2) *(p+i)==*(a+i)==a[i] 。( 3) p[i] == *(p+i) == a[i] 。注意: p+1 指向数组的下一个元素,而不是简单地使指针变量 p的值 +1 。其实际变化为 p+1*size(size 为一个元素占用的字节数)。例如,假设指针变量 p的当前值为 3000 ,则 p+1 为 3000+1*2=3002 ,而不是 3001

Page 32: 使用 VC++6.0 调试程序

用数组名作为函数参数形参:数组或指针变量实参:数组名或指向数组的指针变量传递方式:地址传送方式作用:若函数中对数组作了修改,则调用函数中的数组也会作同样的修改

Page 33: 使用 VC++6.0 调试程序

指向函数的指针

1. 函数指针的概念  一个函数在编译时,被分配了一个入口地址,这个地址就称为该函数的指针。

  可以用一个指针变量指向一个函数,然后通过该指针变量调用此函数。

Page 34: 使用 VC++6.0 调试程序

2. 指向函数的指针变量 ( 1)定义格式 函数类型 (* 指针变量 )( ) ; 注意:“ *指针变量”外的括号不能缺,否则成了返回指针值的函数。 例如, int (*fp)(); /* fp 为指向 int函数的指针变量 */

Page 35: 使用 VC++6.0 调试程序

( 2)赋值 函数名代表该函数的入口地址。因此,可用函数名给指向函数的指针变量赋值。 指向函数的指针变量= [&] 函数名 ; 注意:函数名后不能带括号和参数;函数名前的“ &”符号是可选的。

Page 36: 使用 VC++6.0 调试程序

(3) 调用格式 (* 函数指针变量 )([ 实参表 ])

3. 指向函数的指针变量作函数参数 指向函数的指针变量的常用用途之一,就是将函数指针作参

数,传递到其它函数。 注意:对指向函数的指针变量,诸如 p+i 、 p++/p-- 等运算

是没有意义的。

例 10.24  

设有一个函数 process ,在调用它时,每次实现不同的功能。输入 a 和 b 两个数,第一次调用时找出 a 与 b 中的大者,第

二次找出小者,第三次求和。

Page 37: 使用 VC++6.0 调试程序

#include<stdio.h>void main(){int max(int,int);int min(int,int);int add(int,int);int process(int, int, int (*fun)());int a,b;printf("enter a and b:");scanf("%d%d",&a,&b);printf("\nmax=");process(a,b,max);printf("\nmin=");process(a,b,min);printf("\nsum=");process(a,b,add);}

Page 38: 使用 VC++6.0 调试程序

max(int x, int y)

{return x>y?x:y;}

min(int x, int y)

{return x>y?y:x;}

add(int x, int y)

{return x+y;}

process(int x, int y, int (*fun)(int,int)) /*fun 是一个指向函数的指针,该函数是一个有两个整型参数的返回整型值的函数 */

{int result;

result=(*fun)(x,y);

printf("%d\n",result);

}

Page 39: 使用 VC++6.0 调试程序

返回指针值的函数  一个函数可以返回一个 int 型、 float 型、char 型的数据,也可以返回一个指针类型的数据。 返回指针值的函数(简称指针函数)的定义格式如下: 函数类型 * 函数名 (形参表列 )

 例如:

  int *a(int x,int y);

该函数的函数名为 a,返回的是一个整型的指针。

Page 40: 使用 VC++6.0 调试程序

指针数组

指针数组的概念 数组的每个元素都是一个指针数据。指针数组比较适合用于指向多个字符串,使字符串处理更加方便、灵活。 数据类型 * 数组名 [元素个数 ]

例如: int *p[4]; char *string[10];

Page 41: 使用 VC++6.0 调试程序

p 指向数组 a 易混淆的问题

*p++,*p(++),*(++p),(*p) 设 P 指向 a 数组中的第 i 个元素: *(p--)==a[i--];

*(--p)==a[--i];

*(++p)==a[++i].

Page 42: 使用 VC++6.0 调试程序

结 构 体

Page 43: 使用 VC++6.0 调试程序

例:描述一个学生的姓名、学号、性别、年龄。每个学生都有这样的属性,它们构成一个描述学生具体情况的一个整体。而每个属性又是一个基本的类型,本例中可分别用字符数组、长整型、字符型、和整型来描述。

一、结构体类型的定义结构体概念的引入

数据的描述:基本类型:整型、实型、字符型。数组:属于同一种类型的元素的集合。有时,需要用不同的数据类型来描述一个事物的各方面属性,故此, C 语言引入了结构体的概念。

Page 44: 使用 VC++6.0 调试程序

struct 结构体类型名{ 类型标识符 成员名 1; 类型标识符 成员名 2; …… 类型标识符 成员名 n;};

结构体类型的定义

如:struct student { char name[10]; long id; char gender; int age;}

注意: struct student 应作为一个类型整体, name[10] 、 id 、 gender 、 age 都是其成员。 struct 及花括号后的“;”不能省。

Page 45: 使用 VC++6.0 调试程序

定义结构体类型, 描述下列数据

struct student{ int no ; /* 学号 */ char name [ 10 ]; /* 姓名 */ char sex ; /* 性别 */ int age ; /* 年龄 */ float score[10] ; /* 成绩 */} ;

结构体类型的举例

(1) 学生情况 : 包含学生的学号、 姓名、 性别、 年龄、 10 门课程成绩:

结构体类型可以嵌套定义 即一个结构体类型中的某些成员又是其他结构体类型

注意

Page 46: 使用 VC++6.0 调试程序

例如,对已定义的结构体类型 struct student ,可以定义结构体变量:

struct student zhang ,stu1 ;

二、结构体变量结构体变量的定义

1. 先定义结构体类型, 再定义结构体变量

格式: struct 结构体名 结构体变量名表;

三种方法:

Page 47: 使用 VC++6.0 调试程序

2. 在定义结构体类型的同时定义变量

例如: struct student { char name[10]; char sex; int age; float score; } stu1,stu2;

格式: struct 结构体类型名 { 类型标识符 成员名 1; 类型标识符 成员名 2; …… 类型标识符 成员名 n; } 变量名表 ;

Page 48: 使用 VC++6.0 调试程序

3. 用匿名形式直接定义结构体类型变量(不出现结构体名)

例如: struct { char name[10]; char sex; int age; float score; } stu1,stu2;

格式:struct{ 类型标示符 成员名 1; 类型标示符 成员名 2; …… 类型标示符 成员名 n; } 变量名表 ;

( 1)类型与变量是不同的概念,不要混同。对结构体变量来说,在定义时一般先定义一个结构体类型,然后定义变量为该类型。只能对变量赋值、存取或运算,而不能对一个类型赋值、存取或运算。在编译时,对类型是不分配存储空间的,只对变量分配存储空间。( 2)对结构体中的成员,可以单独使用,它的作用相当于普通变量。( 3)成员也可以是一个结构体变量。( 4)成员名可与程序中的变量同名,两者不代表同一对象。

结构体的说明

Page 49: 使用 VC++6.0 调试程序

例。定义结构体变量 stu1: struct student stu1; stu1.age=20; scanf("%f",&stu1.score);

stu1.age 表示引用结构体变量 stu1 中的 age 成员,因该成员的类型为 int 型,所以可以对它执行任何 int 型变量可以执行的运算。

结构体变量的使用结构体变量一般不整体引用,而是引用其成员变量。

成员变量引用格式结构体变量名 .成员名

其中的圆点运算符称为成员运算符,它的运算级别是最高的。

Page 50: 使用 VC++6.0 调试程序

(1) 结构体类型变量的各成员(分量)必须单独引用 ,成员运算符“•”具有最高优先级。(2) 不允许对结构体变量进行整体的输入输出 如: scanf(“%s%c%d%f”,&stu1); (3) 如果结构体变量类型相同,可以互相赋值。 stu1=stu2; (4) 严格区分类型与变量的概念。

(5) 如果结构体成员本身又是结构体类型的,则可继续使用成员运算符取结构体成员的结构体成员,逐级向下,引用最低一级的成员。程序只能对最低一级的成员进行运算。例如,对 stu1某些成员的访问: stu1.birthday.day=23 ; stu1.birthday.month=8; stu1.birthday.year=1985;

说明

Page 51: 使用 VC++6.0 调试程序

结构体变量的初始化结构体变量可以在定义时初始化。

格式struct 结构体名{ 成员表; } 结构体变量 ={初始化数据表 };

例 struct student { char name[10]; char sex; int age; float score; }stu1,stu2={“Wangwu”,’m’,20,88.5};

Page 52: 使用 VC++6.0 调试程序

一个结构体变量的指针就是该变量所占据的内存段的起始地址。可以定义一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址 。

四、结构体类型指针

Page 53: 使用 VC++6.0 调试程序

例如: struct student *pstu, stu; pstu=&stu; 定义了一个指针变量 pstu,并使指针指向结构体变量 stu 。*pstu 表示指针 pstu所指示的结构体变量(对象) stu ,因而,其成员表示为( *pstu).name ,(*pstu).age 。

指向结构体变量的指针

定义格式

struct 类型名 * 指针变量名;

为方便起见, C语言定义了结构体的指针变量引用结构体成员的特殊形式:

指针变量名 ->成员名

“->”为指向运算符

上面示例( *pstu).name,(*pstu).age 。可以等价表示为:

pstu->name, pstu->age

Page 54: 使用 VC++6.0 调试程序

请分析下列几种运算:①p->n②p->n++③++p->n

总结:结构体成员变量引用方式

①结构体变量 .成员名②(*p). 成员名③p->成员名其中, ->称为指向运算符

可转换为:①p->n②(p->n)++③++(p->n)