二、用配置好的VSCode实战做一道算法题

青梧·2026-09-29 16:53

多说无益,直接开干

以这道题为例

一道用来练手的算法题
P5720 【深基4.例4】一尺之棰

P5720 【深基4.例4】一尺之棰

题目描述

《庄子》中说到,“一尺之棰,日取其半,万世不竭”。第一天有一根长度为 a 的木棍,从第二天开始,每天都要将这根木棍锯掉一半(每次除 2,向下取整)。第几天的时候木棍的长度会变为 1?

输入格式

输入一个正整数 a,表示木棍长度。

输出格式

输出一个正整数,表示要第几天的时候木棍长度会变为 1。

输入输出样例 #1

输入 #1

100

输出 #1

7

说明/提示

数据保证,1 ≤ a ≤ 109。

0. 建立基本工作空间,打开VSCode,新建源文件

在桌面右键VSCode图标,打开VSCode在VSCode中打开文件夹

备注 · 随便打开一个空文件夹即可,这个文件夹就是我们写这道算法题的地方

新建main.c源文件

1. 自信编码,谁都不爱

说明 · 然后根据题目要求,享受你的编码过程,你会发现,你有语法错误,拓展会帮你纠正,写scanf等函数调用时,拓展会有补全和参数信息提示,虽然在AI盛行的当下,这算古法编程,但这也确实是科班出身的必经之路。

开始写算法代码

说明 · 然后凭着直觉写下这道题的解法,自信满满地提交。

第一印象WA

反例 · 我靠,劳资居然也会错?

提示 · 接下来,终于轮到我们配置好的VSCode出场了,让我们通过一步步调试来看看,我们第一印象的这种解法错在哪里?为什么不对?

2. 开始调试自己的程序

2.1 在循环处打断点

打断点

左边那个小红点就是断点:程序跑到这一行会停下来等你。点一下行号左侧的空白就能打上,再点一下取消。

2.2 把程序送进调试器

点右上角那个向下的小箭头(就在「运行」图标旁边),会弹出一个菜单,里面有两项:

点击调试按钮

选下面那一项 —— 调试 C/C++ 文件。VSCode 会先让你选一个调试配置,它已经自动扫到了你本机的 gcc:

选调试配置

点下去,程序就跑起来了。

注意 · 这里有个所有人的第一反应都会踩的坑

你并没有生成 launch.json。

进入调试界面

没有配置文件,程序怎么也跑起来了?往下看,这件事正是这一节最该弄明白的地方。

2.3 喂给它数据,然后看它停在哪

程序起来之后不会自己动,它在等你输入。点一下下方终端,把样例里那个 100 敲进去,回车:

说明 · 输完之后,左侧多了些东西

你会发现左侧面板里冒出了 变量、监视、调用堆栈、断点 四栏,而且程序很明显停在了 while 循环那一行 —— 那一行整个被高亮成了黄色。这就是断点生效的样子。

调试中

2.4 单步:让它一次只走一行

现在点工具条上那个拐着弯的箭头(悬停显示「单步调试 (F11)」),代码就会往下走一行:

说明 · 代码一行一行地执行,变量一格一格地变

每点一次,左边的 length 和 day 就跟着变一次。自己试着多点几下,盯着那两个数看 —— 这就是「变量在程序里怎么变」这件事第一次变得肉眼可见。

调试中-2

2.5 找到问题:day 是 6,不是 7

一直点到循环跳出去,停在了 printf 那一行。这时候看左边的 变量 栏:

变量

值

你以为的

length

1

1 ✅

day

6

7 ❌

找到原因

循环确实跑了 6 次,但 day 是从 0 开始数的。 从第一天算起一共 7 天,程序只数出来 6 —— 答案当然是错的。

找到原因就好办了。先让它继续跑完,退出调试:

放程序继续执行

2.6 回头看看:launch.json 去哪了?

先把这件事说透 —— 因为它是这一整节里最容易被误解的地方。

上一篇里,你亲手生成了一份 launch.json,还逐个字段读过。所以到了这一篇,你多半会以为刚才那一路调试,是 VSCode 读了那份配置才跑起来的。

不是。 这次它连文件都没生成,你真去 .vscode/ 目录里翻,只有 tasks.json。调试面板标题栏写的也是「没有配置」。

原因在 C/C++ 扩展身上:它内置了一份兜底配置。当它发现你没有 launch.json、或者配置列表是空的时候,它不等你配置,直接按自己的默认值把调试器拉起来 —— 就用当前打开的那个源文件。这就是菜单里那句「调试 C/C++ 文件」的含义:不用你配置,我来处理这一份文件。

直接调试(默认兜底)

  • 触发方式:运行 → 调试 C/C++ 文件

  • 它用谁:当前正在编辑的那个源文件,${file}

  • launch.json:不生成、不存在,标题栏显示「没有配置」

  • 编译:先按 tasks.json 里 group.isDefault 为 true 的那个任务编一遍

  • 适合:随手试一段代码、跟教程走一遍。快,但什么都留不下

用 launch.json

  • 触发方式:F5,或标题栏那个绿色三角

  • 它用谁:launch.json 里 program 字段写死的那张路径

  • launch.json:必须是现成的,且能对上一个 configurations 条目

  • 编译:按配置里的 preLaunchTask 去执行对应任务,名字对不上就报错

  • 适合:一个项目反复调试。慢一点,但配置能跟着文件夹走,换台电脑打开就是同一套

重点 · 一句话记住它们的区别

「调试 C/C++ 文件」是「帮我调这一个文件」;launch.json 是「我规定好以后都这么调」。
前者省事,后者省心 —— 你现在写的这点代码用哪个都行,但等你手里有一个正经项目,那就必须得上配置了。

那 launch.json 到底怎么来?在运行和调试面板里点「创建 launch.json 文件」,VSCode 会把上面那份兜底配置原样写成一份文件交给你,之后你就可以在上面逐字改了。

2.7 改一行,再验一遍

错误原因已经清楚了:循环里数的是「第二天往后」,第一天没人数。 所以在循环外面补一句 day++:

修正程序

存盘,按 F5 再走一遍。这次 day 停在 7,符合预期 —— 提交给洛谷试试:

AC

冷静一下:刚才到底发生了什么

代码跑完了,AC 也拿到了。但在关掉这篇文章之前,回头看一眼刚才那一小段路 —— 你会发现它和你以为的不太一样。

第一版代码,VSCode 一个字都没报。没有红线,没有波浪线,Ctrl + Shift + B 编译得干干净净。编辑器认可它,编译器认可它,只有洛谷那一排绿色的 AC 不认可它。

因为你的程序语法完全正确,只是逻辑错了。

这是初学者最容易卡住的一个坎,也是本文最想让你记住的一件事:

出错类型

谁会发现

你看到什么

怎么修

语法错误

编辑器 / 编译器

红线、波浪线、终端里一串 error:

顺着报错改就行,最省事

逻辑错误

只有你自己

什么都没报,结果是错的

只能靠调试,靠盯着变量一步一步看

顺手复习一遍编译器的四个参数:

参数

它替你做了什么

少了会怎样

-fdiagnostics-color=always

让报错带颜色

一整屏白字,读起来费劲

-g

往可执行文件里塞进行号、变量名

断点是灰色的,点不动 —— 没有调试信息,gdb 只能看到一堆内存地址

-Wall

打开所有常用警告

一些明显的可疑代码(比如赋值写成比较)它不会再提醒你

-O2

开优化,让程序跑得更快

你反而不该要它:优化会打乱代码和行号的对应关系,调试时看到的位置会对不上

${env:DEBUGINFOD_URLS}=''; & 'C:\Users\Soleaf\.vscode\extensions\ms-vscode.cpptools-1.34.4-win32-x64\debugAdapters\bin\WindowsDebugLauncher.exe' ...

一长串,看着就头大。但你把参数一个个挑出来读,会发现每个参数都能对上一样东西:--stdin= 对应你敲进去的 100 该往哪儿送,--debugExe= 后面跟的就是 gdb.exe,--interpreter=mi 表示它用的是机器接口。
而你什么都没配置,它却知道该送哪个文件、该调哪个 gdb —— 因为你点的那一下「调试 C/C++ 文件」,就是这份兜底配置的开关。
前两篇文章讲的那个规律,在这一行里又出现了一次:图形界面不是魔法,它只是把你的配置翻译成了一条很长的命令,然后替你敲下去。 只不过这一次,那份「配置」是它自带的。

该轮到你上手了

把 100 换成这几个数,重新跑一遍,看看 day 也跟着变:

你输入

正确答案

你的程序输出

1

1

?

100

7

?(就是你刚才那个)

2

2

?

1000000000

30

?

第二行你已经验证过了。第 1 行和第 3 行是专门给你挖的坑 —— 想想为什么输入 1 的时候答案应该是 1 而不是 0。

顺手再改一个地方:while (length != 1) 这行里,如果长度本来就小于 1 会怎样?把 int length 换成 float 试试?这些改动都不需要重学任何东西 —— 你已经有了工具,改完按 F5,看变量,就这么简单。

实在想不出来,点开看提示

while 的条件是 length != 1,只要长度不等于 1 就继续循环。

输入 1 的时候,条件从一开始就是假 —— 循环一次都不会执行,day 还是初始的 0,程序直接打印 0。但题目说得很清楚:第一天木棍长度就是 1,答案应该是 1。

这就是那个 day++ 为什么必须补在循环外面 —— 它管的是第一天,循环里那次自增管的是第二天往后。两件事,别混。

写在最后

摘要 · 你真正拿到手的东西

不是「学会了一道洛谷题」。这道题你明天就会忘掉。

你真正拿到手的是:代码跑不对的时候,你知道该往哪儿看。
你可以让程序停在任何一行,看着 length 和 day 一格一格地变,亲手确认是哪一步跟你想的不一样。你不再需要盯着代码发呆、猜哪里错了,也不再需要到处插 printf 然后一条条删掉。

走到这里,一条完整的链路已经握在你手里了:

一条完整的链路: 〇 · 认识编译器(装 MinGW、配 PATH)→ 一 · 搬进 VSCode(tasks.json + launch.json)→ 二 · 实战一道题(写代码 → WA → 调试找 bug → AC)

  • 第〇篇解决的是「程序是怎么跑起来的」;

  • 第一篇解决的是「怎么让工具替我跑」;

  • 这一篇解决的是「跑错了怎么办」。

三件事凑齐,你就不再是那个「照着步骤抄一遍、跑出 Hello World 就不知道下一步该干嘛」的人了。你是一个能自己找出问题在哪的人 —— 这是往后的所有语言、所有框架、所有项目都绕不开的底子。

基础不牢,地动山摇。
别急着追新技术。你刚才用的这些东西 —— 编译器、断点、单步、看变量 永远都有用,相信我,这套流程会贯穿你计算机学习的整个生涯。

参考文献

题目和工具链的官方来源,需要查证细节时来这里:

  1. —— 本文使用的那道题,题面和数据范围以这里为准。

  2. —— 微软官方调试文档:断点、单步、变量面板、调用堆栈的完整说明,launch.json 里每个字段的官方定义。

  3. —— tasks.json 与 launch.json 的生成流程,含 MinGW 下的完整示例。

  4. —— 侧栏「运行和调试」面板本身的说明:什么是调试配置、为什么标题栏会显示「没有配置」、以及「创建 launch.json 文件」按钮会写出什么。本文 2.6 节那个坑,答案在这一页。

  5. —— 想搞清楚 VSCode 那个调试按钮背后究竟敲了什么,答案在这里。

  6. —— -g、-Wall、-O2、-fdiagnostics-color 这些参数的权威解释。