VB编程题精析:从语法肌肉记忆到算法思维训练
简介本资源是一份面向VB初学者与高校编程课程学习者的经典题库及详解PDF聚焦基础语法巩固与算法思维训练。涵盖素数判断、字符串反转、闰年判定、数组操作、矩阵处理、排序算法、杨辉三角等33道典型编程题每题均配标准VB代码答案与关键逻辑说明覆盖循环控制、条件分支、函数过程调用、二维数组遍历、字符编码转换等核心知识点。资源为单文件PDF格式共1个文件大小1.3MB内容精炼、排版清晰便于离线查阅与代码复现。已有218人下载学习适合作为课后练习、期末复习、上机考试备考及自学自测的实用参考资料帮助读者系统掌握VB编程基本功与常见问题解决路径。1. 这不是过时的练习册而是 VB 语法肌肉记忆的锻造锤很多人看到“VB 编程题及答案.pdf”第一反应是VB 过时了为什么还要学但真实情况恰恰相反——这份 2020 年底修订的题集覆盖了从基础控制流到二维数组索引、从字符串切片到内存级数组重定义的完整能力图谱。它不教你如何搭 Web 框架而是逼你在Dim a%(3, 3)和ReDim Preserve a(j)之间建立条件反射它不谈云原生却用第 14 题“删除数组第 5 个元素”让你亲手操作内存偏移与边界收缩它甚至在第 26 题“求两条对角线之和”里把a(i, i)和a(i, 3 - i)的下标映射关系刻进你的直觉。这不是怀旧是训练一种底层编程通感当你在 Python 里写arr.pop(4)或在 Java 里调用ArrayList.remove(4)时背后那个被隐去的“元素搬移长度重置”过程正是 VB 这些题强制你显式写出的逻辑。适合三类人高校《程序设计基础》课程助教可直接拆解为课堂 demo、转岗测试/运维需快速掌握脚本逻辑的工程师VB 的InputBox/MsgBox/Text1 ...是最贴近业务场景的 GUI 脚本原型以及准备算法导论期末或 CSP-J 初赛的学生第 9 题“被 3/5/7 除余 1 的最小 5 个数”本质是同余方程组暴力枚举第 30 题杨辉三角是二维 DP 入门。它不提供现代工程范式但把“循环怎么设初值、边界怎么取、嵌套怎么缩进、变量作用域在哪失效”这些易被高级语言掩盖的细节全摊开在For i 0 To 3的每一行里。2. 素数判断与闰年逻辑从试除法到布尔代数的硬编码落地VB 的Mod运算符和短路And/Or是这类判断题的基石。但真正区分新手与熟手的是参数化封装意识和边界处理精度。以第 1 题“求 100 以内素数”原始代码为例其内层循环For a 2 To Sqr(i)存在两个关键隐患Sqr(i)返回Double类型而For循环变量a是整型VB 会隐式截断导致a实际只遍历到Int(Sqr(i))当i100时Sqr(100)10.0截断无损但i97时Sqr(97)≈9.848截断为 9漏检a10的可能性——而 97 是素数此漏洞不影响结果却暴露了对浮点转整型风险的忽视。更致命的是第 4 题闰年判断中If n Mod 4 0 And n Mod 100 0 Or n Mod 400 0这一表达式因 VB 中And优先级高于Or实际等价于((n Mod 4 0) And (n Mod 100 0)) Or (n Mod 400 0)逻辑正确但若开发者误以为Or优先级更高就会写出错误分支。这正是必须显式加括号的铁律。2.1 封装为可复用函数避免重复造轮子将素数判断抽离为独立函数不仅提升代码复用性更强制你思考接口契约。以下为健壮版实现 判断 n 是否为素数返回 True/False Public Function IsPrime(n As Long) As Boolean If n 2 Then IsPrime False Exit Function End If If n 2 Then IsPrime True Exit Function End If If n Mod 2 0 Then IsPrime False Exit Function End If 只需检查到 Int(Sqr(n)) 1防止 Sqr 浮点误差 Dim limit As Long limit CLng(Int(Sqr(n))) 1 Dim i As Long For i 3 To limit Step 2 If n Mod i 0 Then IsPrime False Exit Function End If Next i IsPrime True End Function注意CLng(Int(Sqr(n))) 1是关键防护。Int()向负无穷取整Sqr()永远非负Int()在此处安全但1确保上界不因浮点舍入而遗漏。Step 2跳过所有偶数效率翻倍。n As Long支持更大范围输入避免Integer溢出。2.2 闰年判断的布尔代数重构原始代码用标志位i 1表示闰年这是典型的过程式思维。现代写法应直接返回布尔值并用括号明确逻辑分组 判断 year 是否为闰年返回 True/False Public Function IsLeapYear(year As Integer) As Boolean IsLeapYear (year Mod 4 0 And year Mod 100 0) Or (year Mod 400 0) End Function提示VB 支持将布尔表达式直接赋值给函数名无需If...Then...Else。year Mod 100 0中的是 VB 唯一的不等于运算符不可写作!。此函数可直接用于第 33、39 题的区间素数求和中例如For i 1000 To 1100: If IsPrime(i) And IsLeapYear(i) Then sum sum i组合逻辑清晰。2.3 综合应用第 33 题区间素数求和的完整流程题目要求“编写一个过程计算并输出区间100,1000内所有素数的和”且强调“判断素数使用过程来实现”。这意味着主逻辑与判断逻辑必须分离Private Sub Command1_Click() Dim sum As Long sum 0 Dim i As Long For i 100 To 1000 If IsPrime(i) Then sum sum i End If Next i MsgBox 100-1000 内素数之和为 sum End Sub逻辑说明sum初始化为0而非1是累加器基本规范For循环变量i声明为Long防止Integer在大区间溢出IsPrime(i)调用已封装函数主流程专注聚合逻辑。若需调试可在If内添加Debug.Print i查看具体素数。3. 字符串反转与数组操作从内存拷贝到动态重定义的底层实践VB 的字符串操作看似简单实则暗藏内存管理玄机。第 2 题“字符串倒置”原始代码用Mid()函数直接修改字符串内容这本质上是就地in-place内存覆盖比新建字符串更省内存。而第 14 题“删除数组第 5 个元素”则涉及ReDim Preserve的核心机制它会创建新数组、复制旧数据、释放旧内存是 VB 中少数显式暴露内存重分配的操作。这两类题共同构成对“数据结构动态性”的双重训练。3.1 字符串反转的三种实现与性能对比原始代码用双指针交换Mid()但存在i / 2的浮点除法隐患i为奇数时i/2非整数VB 自动取整。更安全写法是For a 1 To i \ 2\为整除运算符Private Sub Command1_Click() Dim n As String, i As Long, a As Long, b As String n InputBox(输入字符) i Len(n) 使用整除 \ 避免浮点误差 For a 1 To i \ 2 b Mid(n, a, 1) Mid(n, a, 1) Mid(n, i 1 - a, 1) Mid(n, i 1 - a, 1) b Next a Print n End Sub参数说明Mid(n, a, 1)中a是起始位置从 1 开始1是提取长度i 1 - a是对称位置当a1时对应末尾ia2时对应i-1以此类推。i \ 2确保循环次数为整数如i7时循环 3 次位置 1↔7, 2↔6, 3↔5中间字符4自然不动。替代方案构建新字符串更直观内存开销略高Private Sub Command1_Click() Dim n As String, reversed As String, i As Long n InputBox(输入字符) reversed For i Len(n) To 1 Step -1 reversed reversed Mid(n, i, 1) Next i Print reversed End Sub对比说明连接符每次都会创建新字符串对象时间复杂度 O(n²)而Mid()就地修改为 O(n)。对于长字符串如 10KB前者可能触发频繁 GC后者更优。但后者要求字符串可变后者更符合函数式编程习惯。3.2 数组删除ReDim Preserve的精确边界控制第 14 题数组a() {12,6,4,89,75,63,100,20,31}删除第 5 个元素即索引 4值为 75原始代码For i 5 To j: a(i - 1) a(i)存在严重越界风险j UBound(a)初始为 8循环i5 To 8时a(i-1)a(i)将a(4)覆盖为a(5)63a(5)覆盖为a(6)100a(6)覆盖为a(7)20a(7)覆盖为a(8)31最后jj-1为 7ReDim Preserve a(j)将数组截断为 8 个元素索引 0-7原a(8)被丢弃。但若未执行ReDima(7)仍保留旧值逻辑错误。健壮写法必须严格配对Private Sub Command1_Click() Dim a As Variant a Array(12, 6, 4, 89, 75, 63, 100, 20, 31) Dim j As Long, i As Long j UBound(a) 初始上界 8 打印原数组 Debug.Print 原数组: ; For i 0 To j: Debug.Print a(i); ; : Next i: Debug.Print 删除索引为 4 的元素第5个 For i 4 To j - 1 a(i) a(i 1) Next i 关键重定义数组长度减1 ReDim Preserve a(j - 1) 打印新数组 Debug.Print 删除后: ; For i 0 To j - 1: Debug.Print a(i); ; : Next i: Debug.Print End Sub参数说明ReDim Preserve a(j - 1)中j-1是新上界因删除一个元素长度从j1变为j上界即为j-1。For i 4 To j - 1确保移动a(4)到a(j-1)覆盖原a(4)至a(j-1)原a(j)被丢弃。Preserve保留原数据无此关键字则数组清空。3.3 二维数组的上/下三角输出索引模式的数学建模第 15 题“以上三角形式输出”和第 28 题“以下三角形式输出”本质是矩阵索引的几何约束。上三角要求j i列号 ≥ 行号下三角要求j i列号 ≤ 行号。原始代码用Tab(j * 5)控制缩进但更通用做法是计算空格数 上三角输出4x4 数组 Private Sub UpperTriangleOutput() Dim a(3, 3) As Integer, i As Long, j As Long 初始化数组示例 For i 0 To 3 For j 0 To 3 a(i, j) Int(Rnd * 11 10) [10,20] Next j Next i 输出上三角 For i 0 To 3 每行前导空格i 个制表符或空格 Debug.Print Space(i * 4); 用空格替代 Tab更可控 For j i To 3 Debug.Print Format(a(i, j), 00); ; Next j Debug.Print Next i End Sub逻辑说明Space(i * 4)生成i*4个空格使第i行0-indexed首元素左移i倍宽度形成阶梯效果For j i To 3保证只输出ji的元素。下三角只需将内层循环改为For j 0 To i并移除Space()即可。4. 矩阵处理与评分计算从双重循环到极值追踪的工程化思维VB 的二维数组操作是算法能力的试金石。第 16 题“输出每行最大值及下标”和第 29 题“评委打分去最高最低求平均”表面是简单循环实则考验你对状态变量、边界初始化、多目标追踪的掌控力。原始代码常犯的错误包括imax未初始化导致随机值参与比较、For循环范围错误、ReDim后未更新UBound。这些坑在真实项目中会导致静默错误。4.1 矩阵行极值追踪避免未初始化陷阱第 16 题原始代码imax 0后直接进入For j 0 To 3但若该行所有元素均小于a(i, 0)imax将保持0输出错误下标。正确做法是将imax初始化为当前行首列索引并用a(i, imax)作为初始比较基准Private Sub RowMaxWithIndex() Dim a(3, 3) As Integer, i As Long, j As Long, imax As Long, maxVal As Integer 初始化数组示例 For i 0 To 3 For j 0 To 3 a(i, j) Int(Rnd * 31 20) [20,50] Next j Next i 输出矩阵 Debug.Print 矩阵 A: For i 0 To 3 For j 0 To 3 Debug.Print Format(a(i, j), 00); ; Next j Debug.Print Next i 每行找最大值及下标 Debug.Print 每行最大值及下标: For i 0 To 3 初始化假设第0列最大 imax 0 maxVal a(i, 0) 从第1列开始比较 For j 1 To 3 If a(i, j) maxVal Then maxVal a(i, j) imax j End If Next j Debug.Print 第 (i 1) 行: 最大值 maxVal , 下标( i , imax ) Next i End Sub参数说明imax 0和maxVal a(i, 0)是成对初始化确保比较有基准内层For j 1 To 3避免与自身比较Format(a(i,j), 00)保证两位数对齐便于阅读。此模式可直接复用于第 17、27 题的全局极值查找只需将外层循环扩展为For i 0 To 3: For j 0 To 3。4.2 评委评分的鲁棒实现排序与遍历的权衡第 10 题和第 29 题都要求“去掉一个最高分和一个最低分后求平均”。原始代码用冒泡排序两次先升序排找最小再降序排找最大效率低且易错。更优解是单次遍历追踪极值Private Sub JudgeScoreRobust() 第29题数据a {98,97,95,91,90,99,93,94,93,96} Dim scores(9) As Integer scores(0) 98: scores(1) 97: scores(2) 95: scores(3) 91 scores(4) 90: scores(5) 99: scores(6) 93: scores(7) 94 scores(8) 93: scores(9) 96 Dim minVal As Integer, maxVal As Integer, sum As Long, i As Long 初始化为第一个元素 minVal scores(0) maxVal scores(0) sum scores(0) 单次遍历同时找极值并累加 For i 1 To 9 If scores(i) minVal Then minVal scores(i) If scores(i) maxVal Then maxVal scores(i) sum sum scores(i) Next i 减去一个最高分和一个最低分 sum sum - minVal - maxVal 剩余8个分数求平均 Dim average As Double average sum / 8 Debug.Print 原始分数: ; For i 0 To 9: Debug.Print scores(i); ; : Next i: Debug.Print Debug.Print 最高分: maxVal , 最低分: minVal Debug.Print 去掉后平均分: Format(average, 0.00) End Sub逻辑说明minVal和maxVal初始为scores(0)sum初始也为scores(0)然后从i1开始遍历避免重复计算。sum sum - minVal - maxVal直接减去极值无需排序。若存在多个相同极值如两个 99 分此方法只减去一个符合题目“去掉一个最高分和一个最低分”的要求。时间复杂度 O(n)空间 O(1)。4.3 矩阵对角线求和主副对角线的坐标映射第 26 题“求两条对角线上元素之和”原始代码sum sum a(i, i) a(i, 3 - i)对 4x4 矩阵正确但未考虑奇偶阶矩阵中心元素重复计算问题。对于 n x n 矩阵主对角线为a(i,i)副对角线为a(i, n-1-i)当 n 为奇数时中心元素a((n-1)/2, (n-1)/2)同时属于两条对角线会被加两次。因此需根据矩阵阶数调整Private Sub DiagonalSum() Dim a(3, 3) As Integer, i As Long, j As Long, sum As Long, n As Long n 4 4x4 矩阵 初始化 For i 0 To n - 1 For j 0 To n - 1 a(i, j) Int(Rnd * 31 20) [20,50] Next j Next i sum 0 主对角线 a(i,i) For i 0 To n - 1 sum sum a(i, i) Next i 副对角线 a(i, n-1-i) For i 0 To n - 1 sum sum a(i, n - 1 - i) Next i 若 n 为奇数中心元素被加了两次减去一次 If n Mod 2 1 Then Dim center As Long center (n - 1) \ 2 sum sum - a(center, center) End If Debug.Print 对角线元素之和: sum End Sub参数说明n 4为矩阵阶数n Mod 2 1判断奇偶(n-1)\2计算中心索引整除。此代码可无缝适配任意 n x n 矩阵只需修改n值。原始代码省略了奇偶判断因其固定为 4x4但工程化思维要求代码具备泛化能力。5. 杨辉三角与字符串排序从递推关系到稳定排序的算法内功第 30 题“输出 n 行杨辉三角”和第 20 题“字符串按递减次序排列”是算法思维的分水岭。前者考察你能否将数学递推式C(n,k) C(n-1,k-1) C(n-1,k)转化为二维数组的填充逻辑后者则检验你对排序稳定性、比较函数、以及 VB 字符串比较规则ASCII 序的理解。原始代码用冒泡排序但未处理字符串长度相同时的字典序也未考虑空字符串等边界。5.1 杨辉三角的动态规划实现二维数组的逐层填充杨辉三角第i行0-indexed有i1个元素每个元素triangle(i,j) triangle(i-1,j-1) triangle(i-1,j)边界triangle(i,0) triangle(i,i) 1。关键在于数组声明和填充顺序Private Sub PascalTriangle(n As Long) 声明 n 行的三角形第 i 行有 i1 列 Dim triangle() As Long ReDim triangle(n - 1, n - 1) 最大行需要 n 列但只用前 i1 列 填充 Dim i As Long, j As Long For i 0 To n - 1 每行首尾为 1 triangle(i, 0) 1 triangle(i, i) 1 中间元素上一行相邻两数之和 For j 1 To i - 1 triangle(i, j) triangle(i - 1, j - 1) triangle(i - 1, j) Next j Next i 输出居中对齐 Debug.Print 杨辉三角 n 行: For i 0 To n - 1 左侧空格(n-i-1)*2 个空格 Debug.Print Space((n - i - 1) * 2); For j 0 To i Debug.Print Format(triangle(i, j), 00); ; Next j Debug.Print Next i End Sub逻辑说明ReDim triangle(n-1, n-1)声明足够大的二维数组外层For i逐行填充内层For j 1 To i-1填充中间元素j-1和j确保不越界Space((n-i-1)*2)实现居中使第i行比第i1行少 2 个空格。调用PascalTriangle 5即可输出 5 行标准杨辉三角。5.2 字符串递减排序冒泡排序的稳定实现与优化第 20 题原始代码If a(j) a(j 1) Then t a(j): a(j) a(j1): a(j1) t是标准冒泡但未处理a(j)或a(j1)为空字符串的情况VB 中空字符串在比较时小于任何非空字符串。更健壮版本应加入空值检查并利用 VB 内置StrComp函数进行大小写敏感比较Private Sub StringSortDescending() Dim n As Long, i As Long, j As Long, t As String n 5 输入字符串个数 Dim a() As String ReDim a(1 To n) 输入字符串 For i 1 To n a(i) InputBox(请输入第 i 个字符串) Next i 冒泡排序递减 For i 1 To n For j 1 To n - i 使用 StrComp 比较-1 表示 a(j) a(j1)即递减序 If StrComp(a(j), a(j 1), vbBinaryCompare) 0 Then t a(j) a(j) a(j 1) a(j 1) t End If Next j Next i 输出 Debug.Print 递减排序结果: For i 1 To n Debug.Print a(i) Next i End Sub参数说明StrComp(string1, string2, compare)返回-1string1string2、0相等、1string1string2vbBinaryCompare表示二进制比较区分大小写ASCII 序 0即a(j) a(j1)满足递减条件。此写法比直接a(j) a(j1)更明确且可轻松切换为vbTextCompare实现不区分大小写排序。5.3 进阶技巧用Collection对象实现高效字符串排序对于大量字符串冒泡排序 O(n²) 效率低。VB 的Collection对象虽无内置排序但可结合Key属性模拟索引。不过更实用的是利用Scripting.Dictionary需引用 Microsoft Scripting Runtime的Keys属性但本题集聚焦原生 VB故推荐一个轻量技巧预计算字符串长度并用Select Case分组再对每组内部排序减少比较次数。但针对本题 5 个字符串冒泡已足够重点在于理解比较逻辑的精确性。本文还有配套的精品资源点击获取