[VS]实例讲解编译器中的常用调试方法

在这里插入图片描述

[VS]实例讲解编译器中的常用调试方法


一、前言

昨天晚上我正在看资料写博客时,我的同学在学习数据结构时遇到了疑点,让我看看,因为现在学校的学习的进度不快,所以没做什么准备就去了宿舍,心想应该不会太难,准备快速解决继续码博客。

在这里插入图片描述
但是当面对和我的代码风格不同,命名格式不规范,文件不分开创建的代码时,我有些蒙了,看着代码有些大脑空白的感觉,在同学面前又是分析,又是调试的,但都失败了,这个时候感觉自己想法失败了,装13失败了,但我认为自己面对这种代码应该是可以解决的,所以推辞一番,晚上又重新查找,心里暗较劲今晚一定要解决这个bug,要不然之前的学习就白学了。

在这里插入图片描述
最终在我对代码的调试之下,我发现了错误,并且这个错误多少有些简单了,但这也让我有所反思,一方面还是自己的基本知识不熟练,另一方面是调试时的粗心导致的。下面就让我们开始对代码调试的讲解


二、常用按键

在这里插入图片描述

这里我们将我们对代码进行调试时的常用按键进行讲述:

F10:
我们将代码进入调试模式;同时我们在调试中每按一次F10,我们程序就执行一次语句,当我们执行的语句是调用函数时,也是相同,直接将当前语句执行结束。

F11:
当我们在调试我们的代码是,就像我们上述情况,如果我们的执行的语句中含有调用函数,同时我们想进入调用函数中查看分析代码,我们按F11,我们就会进入我们当前语句中调用函数中。

F9:
如果我们的代码过长,而我们又执行执行部分代码查看情况,此时我们选择我们要执行的语句,按下F9,我们就对这一语句打下来一个断点,然后我们按下F5,我们的代码就会直接运行到我们打下断点的语句。

F5:
当我们代码中有打下断点的语句时,我们按下F5,既可以将我们代码直接运行到我们打下断点的地方。


三、举例分析

我们上面得知了调试时常用的按键,当然,实践出真知,我们先给出同学的代码让大家分析,如果基本功熟练的读者相信一眼就可以看出代码中的问题

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct DynamicArrayStack  //初始化栈结构体
{
	int top;
	int capacity;
	int* array;
}DynamicArrayStack;
DynamicArrayStack* InitStack()  //初始化栈
{
	DynamicArrayStack* S =(DynamicArrayStack*) malloc(sizeof(DynamicArrayStack));
	if (!S)
		return NULL;
	S->capacity = 1;
	S->top = -1;
	S->array = (int*)malloc(S->capacity * sizeof(int));
	if (!S->array)
		return NULL;
	return S;
}
int IsFullStack(DynamicArrayStack* S)  //判断栈是否已满
{
	return (S->top == S->capacity-1);
}
void DoubleStack(DynamicArrayStack* S)  //分配空间函数
{
	S->capacity *= 2;
	S->array = (int*)realloc(S->array, S->capacity);

}
void Push(DynamicArrayStack* S, int x)  //将元素data压入栈中
{
	if (IsFullStack(S))
		DoubleStack(S);
	S->array[++S->top]= x;  
	//->的优先级大于++ 先执行S->top,然后将S->top的值加1
}
int IsEmptyStack(DynamicArrayStack* S)  //判断栈是否为空
{
	return (S->top == -1);
}
int Pop(DynamicArrayStack* S)  //从栈中弹出栈顶元素
{
	if(IsEmptyStack(S))
		return INT_MIN;
	return S->array[S->top--];  //将S->top的值先返回,然后S->top减1
}
void DeleteStack(DynamicArrayStack* S)  //删除栈
{
	if (S)
	{
		if (S->array)
			free(S->array);
		free(S);
    }
}
void conversion()  //数制转换
{

}
void PrintStack(DynamicArrayStack* S)  //打印栈
{
	DynamicArrayStack* p= S;
	int i = 0;
	while (i <= p->top)
	{
		printf("%d ", p->array[i]);
		i++;
	}
}
int main()
{
	printf("初始化栈\n");
	DynamicArrayStack* L;
	L = InitStack();
	printf("现在栈为空\n");
	printf("请输入第一个要入栈的值:");
	int e;
	scanf_s("%d", &e);
	Push(L,e);
	printf("现在栈中有一个元素:");
	PrintStack(L);
	printf("\n请输入第二个要入栈的值:");
	scanf_s("%d", &e);
	Push(L, e);	
	printf("现在栈中有二个元素:");
	PrintStack(L);
}

此时我先对同学要实现的代码进行一下背景描述:我们要实现栈,同时实现栈的增删查改等基本接口

而我的同学在运算代码时出现的问题是:
在这里插入图片描述
那么这个时候我们进行调试之前,我们先对代码大体看一眼,这里我们就发现了一个错误:

①我们的main函数中,没有"return0"语句,这是一个非常明显的错误。

现在我们对代码也无法直观的看出什么内容了,那么这个时候我们选择进行调试,我们按下F10,开始我们的调试过程:
在这里插入图片描述
这个时候,我们继续根据我们上述的按键进行调试分析

(这里我们补充一点,关于监视窗口的展开)
在这里插入图片描述
当我们调用监视窗口之后
在这里插入图片描述

现在,我们就行我们代码的调试工作
在这里插入图片描述
此时我们输入元素1;然后继续运行我们的代码
在这里插入图片描述
此时我们监视窗口中关于变量的数值与地址等信息如图,这个时候按照代码中的定义我们得出下面的图解
在这里插入图片描述
我们继续运行我们的代码
在这里插入图片描述
我们按照上述讲解的内容,F10运行当前代码语句,F11进入我们调用函数内部,我们得出下面图解
在这里插入图片描述
我们按照上述讲解的内容,F10运行当前代码语句,F11进入我们调用函数内部,就行我们的代码调试,我们得出下面图解
在这里插入图片描述

这个时候我们得知,当前代码中内存分配函数出现了问题,并且我们得知,当我们的数组容量已满的时候,函数并没有将我们的数组容量翻倍,所以我们回看代码时发现:

②这里的主动内存realloc函数使用错误;

②realloc函数的使用时,两个参数,第一个参数是我们要改变空间大小的地址,一般用指针来作为参数;第二个参数是我们想要的空间大小,这里他直接写的是int类型数据,也就是他想要的对应int类型的空间个数,但我们的大小是:空间个数乘每个数据类型所占的空间,所以我们应该改为sizeof(int * ) * S->capacity,这个时候才是我们真正想要的空间大小


现在我们就解决了我们的代码问题,让我们当前的代码成功运行,但我对上述的代码仍要修改一下,因为当前的代码可读性较差,部分函数的参数设置不友好,可读性较差。

我们在实现他当前的程序时,我们一般创建三个文件

test.c文件:用来测试main()函数

Stack.c文件:用来实现我们栈中的各种函数的具体代码

Stack.h文件:用来声明我们的结构体,声明函数,包含头文件等

还有这里,他在创建之初使用的是指针去接受我们的初始化函数的返回值,这里他的初始化函数的返回值,而里面是先创建一个结构体,再将结构体中数据改变后返回这个结构体的指针;我们应该在main函数中实现的是创建一个结构体变量,然后我们想初始化函数中创递我们这个变量的地址,去改变这个参数的数据内容,这样比较符合我们的代码习惯,以及我们代码的可读性。

Stack.h

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

typedef struct DynamicArrayStack  //初始化栈结构体
{
	int top;
	int capacity;
	int* array;
}DynamicArrayStack;

DynamicArrayStack* InitStack();  //初始化栈
int IsFullStack(DynamicArrayStack* S);  //判断栈是否已满
void DoubleStack(DynamicArrayStack* S);  //分配空间函数
void Push(DynamicArrayStack** S, int x);  //将元素data压入栈中
int IsEmptyStack(DynamicArrayStack* S);  //判断栈是否为空
int Pop(DynamicArrayStack* S);  //从栈中弹出栈顶元素
void DeleteStack(DynamicArrayStack* S);  //删除栈
void PrintStack(DynamicArrayStack* S);  //打印栈

Stack.c

#include"stack.h"

DynamicArrayStack* InitStack()  //初始化栈
{
	DynamicArrayStack* S = (DynamicArrayStack*)malloc(sizeof(DynamicArrayStack));
	if (!S)
		return NULL;

	S->capacity = 1;
	S->top = -1;
	S->array = (int*)malloc(S->capacity * sizeof(int));
	if (!S->array)
		return NULL;
	return S;
}
int IsFullStack(DynamicArrayStack* S)  //判断栈是否已满
{
	return (S->top == S->capacity - 1);//
}

void DoubleStack(DynamicArrayStack* S)  //分配空间函数
{
	S->capacity = S->capacity * 2;
	S->array = (int*)realloc(S->array, sizeof(int*)*S->capacity);

}
void Push(DynamicArrayStack* S, int x)  //将元素data压入栈中
{
	if (IsFullStack(S))//判断是否空间已满,满了则空间翻倍
		DoubleStack(S);

	S->array[++S->top] = x;
	//->的优先级大于++ 先执行S->top,然后将S->top的值加1
}
int IsEmptyStack(DynamicArrayStack* S)  //判断栈是否为空
{
	return (S->top == -1);
}
int Pop(DynamicArrayStack* S)  //从栈中弹出栈顶元素
{
	if (IsEmptyStack(S))
		return INT_MIN;
	return S->array[S->top--];  //将S->top的值先返回,然后S->top减1
}
void DeleteStack(DynamicArrayStack* S)  //删除栈
{
	if (S)
	{
		if (S->array)
			free(S->array);
		free(S);
	}
}
void conversion()  //数制转换
{

}
void PrintStack(DynamicArrayStack* S)  //打印栈
{
	DynamicArrayStack* p = S;
	int i = 0;
	while (i <= p->top)
	{
		printf("%d ", p->array[i]);
		i++;
	}
}

test.c

#include"stack.h"
int main()
{
	printf("初始化栈\n");
	DynamicArrayStack* L;
	L = InitStack();
	printf("现在栈为空\n");
	printf("请输入第一个要入栈的值:");
	int e;
	scanf_s("%d", &e);
	Push(L, e);
	printf("现在栈中有一个元素:");
	PrintStack(L);
	printf("\n请输入第二个要入栈的值:");
	scanf_s("%d", &e);
	Push(L, e);
	printf("现在栈中有二个元素:");
	PrintStack(L);

	return 0;
}

四、总结

关于调试的方式与内容,我就进行这些讲解,我们在这里最重要知道四个调试常用按键,同时当我们的代码遇到问题时,不要凭感觉随意修改,要养成调试的好习惯,知道自己是什么地方出现的问题;
关于调试中还有其他的监视窗口,我们后续会继续讲解

以上就是我对代码调试的个人理解

上述内容如果有错误的地方,还麻烦各位大佬指教【膜拜各位了】【膜拜各位了】
在这里插入图片描述

  • 13
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr、Jerry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值