三、编程题
7.15 输入一串字符,统计各字母出现的次数,不区分大小写。
【解答】
分析:统计26个英文字母出现的次数,必须声明一个具有26个元素的数组,每个元素的下标表示对应字母出现的次数。从输入的字符串中逐一取出字符,并将其转换成大写字母(使得大小写不分),再进行判断。设计步骤如下。
(1)建立用户界面和设置对象属性,如图7-1所示。
(a)(b)
图7-1 建立用户界面和程序运行结果
(2)编写事件代码。
编写“统计字母”命令按钮Command1的单击Click事件代码:
Private Sub Command1_Click( )
Dim a(1 To 26) As Integer
Dim i As Integer, j As Integer, c As String * 1
tot = Len(Text1) ' 求字符串的长度
For i = 1 To tot
c = UCase(Mid(Text1, i, 1)) ' 取一个字符,将其转换成相应的大写字母
If c >= "A" And c <= "Z" Then
j = Asc(c) – 65 + 1 ' 将A~Z大写字母转换成1~26的下标
a(j) = a(j) + 1 ' 对应数组元素加1
End If
Next i
For j = 1 To 26 ' 输出字母及其出现的次数
If a(j) > 0 Then
Label2.Caption = Label2.Caption & Chr$(j + 64) & "=" & a(j) & " "
End If
Next j
End Sub
程序运行结果如图7-1所示。
7.16 随机产生10个两位整数,找出其中的最大值、最小值和平均值。
【解答】
分析:问题可以分为两部分:一是产生10个随机整数,一是对这10个整数求最大、最小以及平均值。为此,需要使用数组。设计步骤如下。
(1)建立应用程序用户界面并设置对象属性。
新建一个工程,进入窗体设计器,首先增加一个框架Frame1,三个标签Label1~Label3,三个文本框Text1~Text3,三个命令按钮Command1~Command3。激活Frame1后,在其中增加一个标签Label4,并修改各个控件的属性,如图7-2所示。
图7-2 求最大值、最小值和平均值
(2)编写代码。
考虑到要在不同的过程中使用数组,所以首先在模块的通用段中声明数组:Dim a(1 To 10) As Integer
随机整数的生成由窗体的Load事件代码完成:
Private Sub Form_Load( )
Dim p As String
Randomize
p = ""
For i = 1 To 10
a(i) = Int(Rnd * 90) + 10
p = p & Str(a(i)) & ","
Next
Label1.Caption = LTrim(Left(p, Len(p) – 1))
End Sub
求最大、最小以及平均值由“确定”按钮Command2的Click事件代码完成:Private Sub Command2_Click( )
Dim n As Integer, m As Integer, s As Single
min = 100: max = 10: s = 0
For i = 1 To 10
If a(i) > n Then max = a(i)
If a(i) < m Then min = a(i)
s = s + a(i)
Next
Text1.Text = max
Text2.Text = min
Text3.Text = s / 10
End Sub
“重置”按钮Command1的Click事件代码:
Private Sub Command1_Click( )
Form_Load
Text1.Text = ""
Text2.Text = ""
Text3.Text = ""
End Sub
最后是“关闭”按钮Command3的Click事件代码:
Private Sub Command3_Click( )
Unload Me
End Sub
【说明】在“重置”按钮的Click事件代码中,可通过调用窗体的Load事件过程来重新产生随机数。
如果要求产生的随机整数互不相同,应改写窗体的Load事件代码:
Private Sub Form_Load( )
Dim p As String
Randomize
p = ""
For i = 1 To 10
Do
x = Int(Rnd * 90) + 10
yes = 0
For j = 1 To i - 1
If x = a(j) Then yes = 1: Exit For ' 如与前面元素相同,返到Do循环
Next ' 重新产生随机数
Loop While yes = 1
a(i) = x
p = p & Str(a(i)) & ","
Next
Label1.Caption = LTrim(Left(p, Len(p) - 1))
End Sub
其中,变量x用来存放刚产生的随机整数。变量yes用来作为标志,如果x与已放入数组中的某个随机整数相同,则yes为1,否则为0。当yes为0时将退出第二层Do…Loop 循环,即可把随机数放入数组之中:a(i)=x。
7.17 利用随机函数模拟投币结果。设共投币100次,求“两个正面”、“两个反面”、“一正一反”三种情况各出现多少次。
【解答】定义一个二维数组a(1,1),其中各元素的含义为:
a(0,0) ——累计“两个正面”的次数;
a(1,1) ——累计“两个反面”的次数;
a(0,1)和a(1,0) ——累计“一正一反”或“一反一正”的次数。
为简单起见,本题直接输出结果到窗体,如图7-3所示。
图7-3 模拟投币结果
编写命令按钮的Click事件代码如下:
Private Sub Command1_Click( )
Dim a(1, 1)
Dim n As Integer
n = Val(InputBox("n=", "请输入投币次数"))
Label1.Caption = "投币次数:" & n
Randomize Timer
For i = 1 To n
n1 = Int(Rnd * 2)
n2 = Int(Rnd * 2)
a(n1, n2) = a(n1, n2) + 1
Next i
Cls
CurrentY = Command1.Top + Command1.Height + 50
Print Tab(10); "~~~~~~~~~~"
Print Tab(14); "投币结果如下:"
Print Tab(10); "~~~~~~~~~~"
Print Tab(10); "两个正面的次数为:"; a(0, 0)
Print Tab(10); "两个反面的次数为:"; a(1, 1)
Print Tab(10); "一正一反的次数为:"; a(0, 1) + a(1, 0)
End Sub
请读者修改该题,在显示模拟投币结果时,可同时显示钱币图案(正面、反面)。
7.18 利用一维数组统计一个班学生0~9、10~19、20~29、…、90~99及100各分数段的人数。
【解答】定义一个有11个元素的一维数组a(0 To 10),把0~9分的学生人数存入a(0)中,把11~19分的学生人数存入a(1)中,…,把100分的人数存入a(10)中。
设计步骤如下:
(1) 设计程序界面和设置对象属性,参见图7-4。
图7-4 利用列表框统计各分数段的人数
(2) 编写代码。
首先在“通用”段声明动态数组:
Dim a(10) As Integer
命令按钮Command1的Click事件代码为:
Private Sub Command1_Click()
Dim i As Integer, p As Integer, n As Integer
Dim x As Single
n = InputBox("n=", "请输入学生数") ' 利用输入框输入学生数
Label1.Caption = "共有人数:" & n
For i = 1 To n
x = Val(InputBox("请输入第" & Str(i) & "名学生的成绩", ""))
If x >= 0 And x <= 100 Then ' 限制数据范围
p = Int(x / 10)
a(p) = a(p) + 1
Else
MsgBox "请输入正确分数!" ' 消息框
i = i – 1
End If
Next i
For p = 0 To 9
List1.AddItem p * 10 & "~" & (p * 10 + 9) & "分的人数为:" & a(p)
Next p
List1.AddItem "100分的人数为:" & a(10)
End Sub
程序运行结果如图7-15所示。
本题也可以不使用列表框控件,直接使用Print方法输出到窗体或图片框中,将命令按钮的Click事件代码改为:
Private Sub Command1_Click()
Dim p As Integer, n As Integer
Dim x As Single
n = InputBox("n=", "请输入学生数")
Label1.Caption = "共有人数:" & n
For i = 1 To n
x = Val(InputBox("请输入第" & Str(i) & "名学生的成绩", ""))
If x >= 0 And x <= 100 Then
p = Int(x / 10)
a(p) = a(p) + 1
Else
MsgBox "请输入正确分数!"
i = i – 1
End If
Next i
Cls
For p = 0 To 9
Print Tab(2); p * 10 & "~" & (p * 10 + 9) & "分的人数为:"; Tab(20); a(p)
Next p
Print Tab(2); "100分的人数为:"; Tab(20); a(10)
End Sub
程序运行结果如图7-5所示。
图7-5 直接在窗体上统计各分数段人数
7.19 设某班共10名学生,为了评定某门课程的奖学金,按规定超过全班平均成绩10%者发给一等奖,超过全班成绩5%者发给二等奖。试编制程序,输出应获奖学金的学生名单(包括姓名、学号、成绩、奖学金等级)。
【解答】由于对10名学生的数据需用两次(一次用于求平均成绩,另一次用于挑选获奖者),所以应定义描述其姓名、学号、成绩的三个一维数组。
设计步骤如下:
(1) 设计程序界面和设置对象属性参见图7-6。其中列表框控件的Sorted属性设为True。
图7-6 评定奖学金 (2) 编写代码。
首先在“通用”段声明动态数组:
Dim xm(10) As String, xh(10) As String, cj(10) As Single
命令按钮Command1的Click 事件代码为:
Private Sub Command1_Click()
For i = 1 To 10 ' 输入各学生数据
xm(i) = InputBox("输入第" & Str(i) & "个学生的姓名:")
xh(i) = InputBox("输入第" & Str(i) & "个学生的学号:")
cj(i) = InputBox("输入第" & Str(i) & "个学生的成绩:")
s = s + cj(i) ' 求总成绩
Next i
s = s / 10 ' 求全班平均成绩
sx1 = s * 1.1 ' 求一等奖标准
sx2 = s * 1.05 ' 求二等奖标准
Combo1(0).Clear: Combo1(1).Clear
For i = 1 To 10
If cj(i) > sx1 Then
Combo1(0).AddItem cj(i) & "," & xm(i) & "," & xh(i)
ElseIf cj(i) > sx2 Then
Combo1(1).AddItem cj(i) & "," & xm(i) & "," & xh(i)
End If
Next i
Label1.Caption = "平均分: " & s & ", 1等奖" & Combo1(0).ListCount & _
"名,2等奖" & Combo1(1).ListCount & "名"
Combo1(0).ListIndex = 0
If Combo1(1).ListCount = 0 Then
Combo1(1).Text = "无"
Else
Combo1(1).ListIndex = 0
End If
End Sub
程序运行结果如图7-6所示。
7.20 输出幻方阵。幻方阵也称魔方阵,是指由自然数1~n 2(n 为奇数)构成的方阵,其各行、各列以及对角线元素之和均相等。如图7-7所示。
(a)(b)(c)
图7-7 幻方阵
【解答】分析:先将数1放在第1行的当中一列,2~n2中的各数依次按以下规律排列:
①每一个数存放的行数比前一个数的行数减1,列数加1。
②若上一个数在第1行,则下一个数在第n行(最下一行),列数加1。
③若上一个数在第n列,则下一个数在第1列,而行数减1。
④若某数按以上规律应放的位置已被其他数占据,则该数放在上一数的下面一列。
设计步骤如下。
(1)设计程序界面并设置对象属性,如图7-10所示。其中单选钮控件数组中的第1个单选钮Option1(0)的Value属性必须设为True。
(2)编写代码。
首先在“通用”段声明动态数组:
Dim a( ) As Integer
窗体的Activate事件代码:
Private Sub Form_Activate( )
Select Case True ' 检查哪个按钮被选中
Case Option1(0)
n = 3
Case Option1(1)
n = 5
Case Option1(2)
n = 7
End Select
Picture1.Height = 350 * n ' 设置图片框的大小与位置
Picture1.Width = 350 * n
Picture1.Top = (Me.ScaleHeight – Picture1.Height) / 2
Picture1.Left = (Frame1.Left – Picture1.Width) / 2
ReDim a(n, n) ' 定义数组的大小
i = 1 ' 安排数1的位置
j = (n + 1) / 2
a(i, j) = 1
Picture1.Cls
For x = 2 To n * n ' 安排数2 ~ n * n的位置
If (x – 1) Mod n = 0 Then
i = i + 1
Else
i = IIf(i = 1, n, i – 1)
j = IIf(j = n, 1, j + 1)
End If
a(i, j) = x
Next
For i = 1 To n ' 输出数组
Picture1.CurrentY = (i – 1) * Picture1.Height / n + 60
Picture1.CurrentX = 15 * n
For j = 1 To n
Picture1.Print Format(a(i, j), "@@@");
Next
Picture1.Print
Next
End Sub
单选钮控件数组Option1( )的Click事件代码:Private Sub Option1_Click(Index As Integer)
Form_Activate
End Sub