❶ VB或VC编译的DLL文件可以部分反编译嘛
分类: 电脑/网络 >> 程序设计 >> 其他编程语言
问题描述:
MD5("DIONNELLE");
如题,如果程序中包含一个MD5加密的字符串来当作密码的话! 并编译成DLL文件!
请问通过反编译,或者跟踪等黑客技术,可以得到MD5加密方式嘛? (因为我有可能是其它的加密方式)?还有可以得到里面的常量参数"DIONNELLE"嘛?
如果都可以得到,那请问如果加个变量$PS="DIONNELLE",然后再MD5($PS);
呢?
我知道经过VB\BC等编译过的DLL文件,目前还不能完全反编译! 但是通过部分反编译或跟踪等黑客技术不知道能不能得到加密的参数字符常量等!???
希望能详细说明!谢谢!如果可以得到,有什么办法可以防止!?
解析:
"DIONNELLE" 为常量,所以会放在程序的某个地方,有一个地址。
md5(md5(md5("DIONNELLE"))); 这样子是没有什么作用的。
反汇编出来也是几个push和call而已,没有什么作用
VB\BC等编译过的DLL文件,目前还不能完全反编译
无论是exe还是dll都可以反汇编,即使静态不行,也可以动态调试。
破解反汇编就行 了,不一定要反编译。
可以得到字符串的话,有可能得到是MD5三次循环嘛?
根据call的调用地址,绝对可以看出你是对同一个函数的三次调用。
至于看出你是否采用的是md5算法。这是根据代码的特征分析的。
如果要防止破解,最好给程序加上自己写的强壳,技术有很多我也说不了
,我也是略知一二而已,就不多说了。
❷ 急!关于VB,简单的程序设计
分类:电脑IT
四、数组中常见错误和注意事项
1.静态数组声明下标出现变量
n = InputBox("输入数组的上界")
Dim a(1 To n) As Integer
2.数组下标越界
引用的下标比数组声明时的下标范围大或小。
Dim a(1 To 30) As Long, I as integer
a(1) = 1: a(2) = 1
For i = 3 To 30
a(i) = a(i - 2) + a(i - 1)
Next I
3.数组维数错
数组声明时的维数与引用数组元素时的维数不一致。
Dim a(3, 5) As Long
a(I)=10
4.Aarry函数使用问题
只能对Variant 的变量或动态数组赋值。
5.获得数组的上界、下界
UBound 、Lbound函数
1.Dim数组声明
有时用户为了程序的通用性,声明数组的上界用变量来表示,如下程序段:
n=InputBox("输入数组的上界")
Dim a(1 To n)As Integer
程序运行时将在Dim语句处显示"要求常数表达式"的出错信息。即Dim语句中声明的数组上、下界必须是常数,不能是变量。
解决程序通用的问题,一是将数组声明的很大,这样浪费一些存储空间;二是利用动态数组,将上例改变如下:
Dim a()As Integer
n=InputBox ("输入数组的上界")
ReDim a(1 To n) As Integer
2.数组下标越界
引用了不存在的数组元素,即下标比数组声明时的下标范围大或小。例如,要形成有如下30项的斐波那契数列:
1,1,2,3,5,8,13,21,34,…,317811,514229,832040
正确的程序段如下:
Dim a(1 To 30) As Long, i%
若将For i=3 To 30改为For i=1 To 30,程序运行时会显示"下标越界"的出错信息,因为开始循环时i=l,执行到循环体语句a(i)=a(i-2)+a(i-1),数组下标i-2、i-1均小于下界1。
同样若将上例:a(i)=a(i-2)+a(i-1)语句改为:a(i+2)=a(i)+a(i+1)。
程序运行时也会显示"下标越界"的出错信息,这时是数组下标大于上界30。
3.数组维数错
数组声明时的维数与引用数组元素时的维数不一致。例如,下程序段为形成和显示3×5的矩阵:
Dim a(3,5) As Long
For i=1 To 3
For j=1 To 5
a(i)=i*j
Print a(i);"";
Next j
Print
Next i
程序运行到a(i)=i*j语句时出现"维数错误"的信息,因为在Dim声明时是二维数组,引用时的一个下标。
4.Array函数使用问题
Array函数可方便地对数组整体赋值,但此时只能声明Variant的变量或仅由括号括起的动态数组。赋值后的数组大小由赋值的个数决定。
例如,要将1,2,3,4,5,6,7这些值赋值给数组a,表2.5.1列出了三种错误及相应正确的赋值方法。
表2.5.1 Array函数表示方法
错误的Array函数赋值
改正的Aarry函数赋值
Dim a(1 To 8)
a=Array(1,2,3,4,5,6,7,8)
Dim a( ) a=Array(1,2,3,4,5,6,7)
Dim a As Integer a=Array(1,2,3,4,5,6,7)
Dim a a=Array(1,2,3,4,5,6,7)
Dim a
a()=Array(1,2,3,4,5,6,7)
Dim a a=Array(1,2,3,4,5,6,7)
5.如何获得数组的上界、下界
Array函数可方便地对数组整体赋值,但在程序中如何获得数组的-上界、下界,以保证访问的数组元素在合法的范围内,可使用UBound和LBound函数来决定数组访问。
在上例中,若要打印a数组的各个值,可通过下面程序段实现:
For i=Lbound(A) To Ubound(A)
Print a(i)
Next i
6.给数组赋值
VB6.0提供了可对数组整体赋值的新功能,方便了数组对数组的赋值操作。但真正使用不那么方便,有不少限制。数组赋值形式如下:
数组名2=数组名1
我们就此形式作讨论:这里的数组名2,实际上在前面的数组声明时,只能声明为Variant的变量,赋值后的数组2的大小、维数、类型同数组名1;否则,若声明成动态或静态的数组,例如:
Dim数组名2()或Dim数组名2 (下标)
程序在运行到上述赋值语句时显示"不能给数组赋值"的出错信息。
所以,为了程序的安全、可靠,建议读者还是忍痛割爱,少用VB6.0的这一新功能,使用传统的循环结构来给数组赋值。基于此原因,我们也就在教程中不作展开。
五、过程中常见错误和注意事项
1.程序设计算法问题
该章程序编写难度较大,主要是算法的构思有困难,这也是程序设计中最难学习的阶段。经验告诉每一位程序设计的初学者,没有捷径可走,多看、多练、知难而进。上机前一定要先编写好程序,仔细分析、检查,才能提高上机调试的效率。每当一个程序通过艰苦的努力调试通过时,那苦尽甘来的喜悦令你一言难尽。
2.确定自定义的过程是子过程还是函数过程
实际上过程是一个具有某种功能的独立程序单位,供多次调用。子过程与函数过程的区别是前者子过程名无值,后者函数过程名有值。若过程有一个返回值,则习惯使用函数过程;若过程无返回值,则使用子过程,若过程返回多个值,一般使用子过程,通过实参与形参的结合带回结果,当然也可通过函数过程名带回一个,其余结果通过实参与形参的结合带回。
3.过程中形参的个数和传递方式的确定
对初学者,在定义过程时不能确定形参的个数和传递方式。
过程中参数的作用是实现过程与调用者的数据通信。一方面,调用者为子过程或函数过程提供初值,这是通过实参传递给形参实现的,另一方面,子过程或函数过程将结果传递给调用者,这是通过地址传递方式实现的,因此,决定形参的个数就是由上述两方面决定的。对初学者,往往喜欢把过程体中用到的所有变量作为形参,这样就增加了调用者的负担和出错概率,也有的初学者全部省略了形参,则无法实现数据的传递,既不能从调用者得到初值,也无法将计算结果传递给调用者。
VB中形参与实参的结合有传值和传地址两种方式。区别如下:
(1)在定义形式上前者在形参前加即ByVal关键字。
(2)在作用上值传递只能从外界向过程传入初值,但不能将结果传出,而地址传递既可传入又可传出。
(3)如果实参是数组、自定义类型、对象变量等,形参只能是地址传递。
4.实参与形参类型对应问题
在地址传递方式时,调用过程实参与形参类型要一致。例如:
函数过程定义如下:
Public Function f!(x!)
f=x+x
End Function
主调程序如下:
Privme Sub Commandl_Click()
Dim y%
y=3
Print f(y)
End Sub
上例形参x是单精度型、实参y是整型,程序运行时会显示"ByRef参数类型不符"的编译出错信息。
在值传递时,若是数值型,则实参按形参的类型将值传递给形参。例如:
函数过程定义如下:
Public Function f!(ByVal x%)
f=x+x
End Function
主调程序如下:
Priva~SubCommandI_Click()
Dim y!
Y=3.4
Print f(y)
End Sub
程序运行后显示的结果是6。
5.变量的作用域问题
局部变量,在对该过程调用时,分配该变量的存储空间,当过程调用结束,回收分配的存储空间,也就是调用一次,初始化一次,变量不保值,窗体级变量,当窗体装入,分配该变量的存储空间,直到该窗体从内存卸掉,才回收该变量分配的存储空间。
例如,要通过文本框输入若干个值,每输入一个按Eeter键,直到输入的值为9999,输入结束,求输入的数的平均值。
Private Sub Textl_Key Press(Key Ascii As Integer)
Dim sum!,n%
If KeyAscii=13 Then
If Val(Text1)=9999 Then
sum=sum/n
Print sum
Else
Sum=sum+Text1
n=n+1
Text1=""
End If
End If
End Sub
该过程没有语法错,运行程序可输入若干个数,但当输入9999时,程序显示"溢出"的错误。原因sum和n是局部变量,每按一个键,局部变量初始化为0,所以会有上述错误产生。
改进方法:将要保值的局部变量声明为Static静态变量或声明为窗体级变量。也可将要保值的变量在通用声明段进行声明为窗体级变量。
6.递归调用出现"栈溢出"
如下求阶乘的递归函数过程:
Public Functionfac(n As Integer)As integer
If n=1 Then
fac=1
Else
fac=n*fac(n-1)
End If
End Function
Private Sub Commandl_Click() '调用递归函数,显示出fac(5)=120
Print "fac(5)";fac(5)
End Sub
当主调程序调用时,n的值为5时,显示120结果;当n的值为-5时,显示"溢出堆栈空间"的出错信息。
实际上每递归调用一次,系统将当前状态信息(形参、局部变量、调用结束时的返回地址)压栈,直到到达递归结束条件。上例当n=5时,每递归调用一次,参数n-l,直到n=l递归调用结束,然后不断从栈中弹出当前参数,直到栈空。而当n=-5时,参数n-1为-6、压栈,再递归调用、n-1永远到不了n=l的终止条件,直到栈满,产生栈溢出的出错信息。
所以设计递归过程时,一定要考虑过程中有终止的条件和终止时的值或某种操作,而且每递归调用一次,其中的参数要向终止方向收敛,否则就会产生栈溢出。
六、常用控件常见错误和难点分析
1.遗漏对象名称
在VB程序设计时,初学者常犯的一个错误是遗漏对象名称,特别是在使用列表框时。例如,如果要引用列表框(List1)中当前选定的项目,Listl.list(Listlndex)是错误的。即使当前焦点在Listl上,VB也不是认为Listlndex是List l的属性,而是一个变量。所以正确的引用方式是:Listl. 1ist(Listl.Listlndex)。
2.列表框的Columns属性
列表框的Columns属性决定列表框是水平还是垂直滚动以及如何显示列中的项目。如果水平滚动,则Columns属性决定显示多少列,如表2.7.2所示。图2.7.1是一个水平滚动两列显示的列表框。
在程序运行期间,该属性是只读的,也就是说,不能在运行时,将多列列表框变为单列列表框或将单列列表框变为多列列表框。
表2.7.2 列表框的Columns属性
列数 属 性
0(默认值)1到n 项目安排在一列中,且列表框竖直滚动项目安排在多个列中,先填第一列,再填第二列……列表框水平滚动并显示指定数目的列
3.域级验证
域级验证是指输入到某独立域的数据的验证,在域级验证的过程中一般不考虑窗体一般其他域的内容。进行域级验证的合适时间是:
(1)当往某域中输入某个键时,此时涉及键盘事件(KeyDown、KeyUp和KeyPress)。
(2)当用户企图离开某域时,此时涉及CansesValidate属性和Validate事件。
(3)当某域的内容发生变化时,此时涉及Change事件。
CausesValidation属性和Validate事件通常是协同工作的。
CausesValidate属性决定Validate事件是否发生。如果控件的CausesValidate属性为False,该控件的Validate事件永远不会发生。如果控件的CausesValidate属性为Tree,当焦点企图移到(还没有离开,也可以说离开之前)另一个CausesValidate属性为True的控件时,原控件的Validate事件发生:当焦点企图移到另一个CausesValidate属性为False的控件时,原控件的Validate事件暂时不发生,什么时候发生?直到焦点移到一个CausesValidate属性为True的控件上时才发生。
例如,假定有如图2.7.2所示的程序。当焦点企图从Textl移到Text2时,Textl的Validate事件发生,同样当焦点企图从Text2移到Textl时,Text2的Validate事件发生。当焦点企图从Textl移到Text3时,TextI的Validate事件暂时没有发生,因为Text3的CausesValidate为False,然后如果焦点企图继续移动到Text2时,Textl的Validate事件才发生。
图2.7.2 CausesValidate属性和Validate事件
CausesValidate属性和Validate事件的这一特性常常应用在如图2.7.3所示的程序中。当在文本框中输入了无效数据时而又不知道如何输入有效数据时,用户往往选择Help命令寻求帮助或选择Cancel命令结束数据输入,此时不希望执行验证程序。因为如果执行验证程序且发现了无效数据,则无法选择Help或Cancel了,用户就这样被套住了。现在只要将文本框的CausesValidate属性设为True,命令按钮的CausesValidate属性为False,验证程序放在 Validate过程中,问题就解决了。在默认情况下,所有控件的CausesValidation属性都为Tree。
图2.7.3 命令按钮的CausesValidate属性和Validate事件
并不是所有的控件都有Validate事件。只有那些能用于输入数据的控件(如文本框、复选框、滚动条等)才有这个事件。Validate事件过程如下:
Privme Sub object_Validate(Cancel As Boolean)
…
EndSub
其中,当参数Cancel被设为Tree后,焦点将不会离开对象。
如果要将实验七第1题改用Validate事件和CausesValidation属性实现数据验证,则应有如下的程序。
Sub txtMath_Validate(Cancel As Boolean)
If Val(txtMath.Text)<0 Or _
Val(txtMath.Text)>100 Then
Cancel=True
End If
End Sub
1.窗体顶部菜单栏中的菜单项与子菜单中的菜单项的区别
窗体顶部菜单栏中的菜单项与子菜单中的菜单项都是在菜单编辑器中定义的,但是它们是有区别的。
(1)窗体顶部菜单栏中的菜单项不能定义快捷键,而子菜单中的菜单项可以有快捷键。
(2)当有热键字母(菜单标题中"&"后的字母)时,按Alt+热键字母选择窗体顶部菜单栏中的菜单项,按热键字母选择子菜单中的菜单项(当子菜单打开时)。子菜单没有打开时,按热键字母无法选择其中的菜单项。
(3)尽管所有的菜单项都能响应Click事件,但是窗体顶部菜单栏中的菜单项不需要编写事件过程。
2.在程序中对通用对话框的属性设置不起作用
在程序中对通用对话框的属性设置不起作用,多数情况是因为在弹出对话框后才进行属性设置。例如,下面的程序代码就存在这样的问题,改正方法是将弹出对话框语句放到最后,即把CommonDialogl.Action=l放在所有属性设置语句的后面。
CommonDialog1.Action=1
ConmaonDialog1.FileName="*.Bmp"
CommonDialogl.InitDir="C:\Windows"
CommonDialog1.Filter="Pictures(*.Bmp)|*.Bmp|All Files(*.*)|*.*"
CommonDialog1.FilterIndex=1
3.在工程中添加现有窗体时发生加载错误
在使用"工程"菜单中的"添加窗体"命令添加一个现存的窗体时经常发生加载错误,绝大多数是因为窗体名称冲突的缘故。例如,假定当前打开了一个含有名称为Forml的工程,如果想把属于另一个工程的Forml窗体装入则肯定会出错。
[注意]
窗体名与窗体文件名的区别。在一个工程中,可以有两个窗体文件名相同的窗体(分布在不同的文件夹中),但是绝对不能同时出现两个窗体名相同的窗体。
4.实时菜单的创建
实时菜单是由应用程序根据需要动态创建的。在VB中,常见的实时菜单是"文件"菜单,该菜单显示了最近所使用的工程。
创建实时菜单必须结合控件数组,用Load语句创建菜单项,用UnLoad清除菜单项。
创建实时菜单的步骤:
(1)在菜单编辑器中建立样本菜单项
样本菜单项的属性设置见表2.8.4所示。设置Index为0,表明样本菜单项是控件数组的一个元素,其下标为0。样本菜单项的Name属性是必须的,它将作为控件数组的名称。在下面假定数组名为NameArray。Visible可以设为True,设为False表示初始时该菜单项不可见。
表2.8.4 实时菜单样本菜单项
属性 Name Caption Index Visible
设置值 必需的 可以没有 0 False
(2)在程序中用Load语句创建菜单项
例如,Load NameArray(1)创建一个新的菜单项(在控件数组中的下标为1,然后将其 Visible属性设置True,同时设置Caption属性。
动态创建的菜单项继承了除了Index之外的绝大部分属性,所以要对Caption和Visible属性进行设置。另外,样本菜单项在菜单系统中的位置决定了新菜单项出现的位置。
(3)为实时菜单项编写代码
每个实时菜单项都是控件数组的一个成员,具有相同的名称,并且共享事件过程。
下面是一个实时菜单项代码示例:
SubNameArray_Click(Index As Integer)
Select Case Index
Case 0
MsgBox("NameArmy(0)(样本菜单项) is clicked!")
Case 1
MsgBox("NameArray(1)(第一个实购菜单项) is clicked!")
Case 2
MsgBox("NameArray(2)(第二个实时菜单项) is clicked!")
End Select
End Sub
(4)删除实时菜单项
尽管把Visible设为False,程序运行时实时菜单项不会显示,然而有时还是需要把实时菜单项从内存中销毁。删除实时菜单使用UnLoad语句。例如,LoadNameArray(1)。
有关建立实时菜单的详细内容请参阅教程第4.3节。
5.通用对话框的CancelError属性和Err对象
当通用对话框的CancelError属性为True时,无论何时选择"取消"按钮,均产生 32755(cdlCancel)号错误,即将Err的Number属性设置为32755。
Err是VB的一个系统对象,它记录了程序运行期间所发生的错误。
Err对象的重要属性有Number(默认属性)和Description。当错误发生后,错误的生成者把错误号和有关错误的说明分别存放在Number和Description属性中。例如,当在 CancelError属性为True的通用对话框中选择"取消"按钮时,产生一个错误,Err对象的Number和Description属性将被设置为32755和"选择'取消'"。
在程序运行期间,经常会发生各种各样的错误。有关错误处理的详细内容请参阅教程第 9.6节。
下面是当程序产生cdlCancel错误时结束程序的运行。
SubForm_ClickO
CommonDialogl.CancelError=True
On Error GoTo ErrorHandler
CommonDialogl.Action=l
' 处理文件的语句
ErrorHandler:
If Err.Number=cdlCancel Then
End
Endlf
End Sub
6.与窗体有关的事件
在首次用Load语句将窗体(假定该窗体在内存中还没有创建)调入内存之时依次发生 Initialize和Load事件。再用UnLoad将窗体从内存中卸载时依次发生QueryUnLoad和Unload事件,再使用Set窗体名=Nothing语句解除初始化时发生Terminate事件。
Initialize是在窗体创建时发生的事件。在窗体的整个生命周期中,Initialize事件只触发一次。用户可以将一个窗体装入内存或从内存中删除很多次,但窗体的建立只有一次。也就是说,在用Load语句将窗体装入内存时会触发Load事件,但并不一定触发Initialize事件。
在用UnLoad语句卸载窗体后,如果没有使用Set窗体名=Nothing解除初始化,则在下次使用Load语句时不会触发Initialize事件,否则会引起Initialize事件。
假定有Forml和Form2两个窗体,并且有下列事件过程:
' Forml窗体事件过程
Sub Form_Click()
Debug.Print"窗体首次装入内存时发生的事件:"
Load Form2
Debug.Print"用Unload卸载窗体时发生的事件:"
UnloadForm2
Debug.Print "窗体第二次装入内存时发生的事件:"
Load Form2
Debug.Print "用Unload卸载窗体时发生的事件:"
Unload Form2
Debug.Print "用Set窗体名=Nothing语句解除初始化时发生的事件:"
Set Form2=Nothing
Debug.Print "窗体第三次(解除初始化后)装入内存时发生的事件:"
Load Form2
End Sub
'Form2窗体事件过程
Sub Form_Initialize()
Debug.Print"Initialize事件"
End Sub
Sub Form_Lond()
Debug.Pnnt"Load事件"
End Sub
Sub Form_QueryUnload(Cancel As hteger, UnloadMode As Integer)
Debug.Print"QueryUnload"
End Sub
Sub Form_Unlond(Cancel As Integer)
Debug.Print"Unload"
End Sub
Sub Form_Terminate()
Debug.Print"Terminate"
End Sub
当用户在Form1上单击时,在Debug窗口显示下列信息:
窗体首次转入内存时发生的事件:
Initialize事件
Load事件
用Unload卸载窗体时发生的事件:
Query Unload
Unload
窗体第二次装入内存时发生的事件:
Load事件
用Unload卸载窗体时发生的事件:
QueryUnload
Unload
用Set窗体名=Nothing语句解除初始化时发生的事件:
Terminate
窗体第三次(解除初始化后)装入内存时发生的事件:
Initialize事件
Load事件
7.MouseDown、MOUSeUp和C1ick事件发生的次序
当用户在窗体或控件上按下鼠标按钮时MouseDown事件被触发,MouseDown事件肯定发生在MouseUp和C1ick事件之前。但是,MouseUp和Click事件发生的次序与单击的对象有关。
当用户在标签、文本框或窗体上作单击时,其顺序为:
(1)MouseDown
(2)MouseUp
(3)Click
当用户在命令按钮上作单击时,其顺序为:
(1)MouseDown
(2)Click
(3)MouseUp
当用户在标签或文本框上作双击时,其顺序为:
(1)MouseDown
(2)MOuseUp
(3)Click
(4)DblCUck
(5)MouseUp
七、文件常见错误和难点分析
1.文件系统的三个控件不能产生关联
也就是当驱动器改变时,目录列表框不能跟着相应改变;或者当目录列表框改变时,文件列表框不能跟着相应改变。要三个控件产生关联,使用下面两个事件过程:
Private Sub Drivel_Change()
Dirl.Path=Drivel.Drive
End Sub
Private Sub Dirl_Change()
Filel.Path=Dirl.Path
End Sub
2.如何在目录列表框表示当前选定的目录
在程序运行时双击目录列表框的某目录项,则将该目录项改变为当前目录,其Diirl. Path的值作相应的改变。而当单击选定该目录项时,Diirl. Path的值并没有改变。有时为了对选定的目录项进行有关的操作,与ListBox控件中某列表项的选定相对应,表示如下:
Dirl.List(Dirl.Listlndex)
3.当使用文件系统控件对文件进行打开操作时,显示"文件未找到"出错信息。
例如,如下语句:
Open Filel.Path+Filel.File Name For Input As#1
当选定的目录是根目录,上述语句执行正确,而当选定的目录为子目录,上述语句执行时显示"文件末找到"出错信息。
其中:Filel.Path表示当前选定的路径,Filel.File Name表示当前选定的文件,合起来表示文件的标识符。
当选定的文件在根目录下(假定驱动器为C),Filel.Path的值为"C:\1",假定选定的文件名为"t1.txt",则Filel.Path+Filel.FileName的值为"C:\t1.txt"为合法的文件标识符。
当选定的文件在子目录下(假定驱动器为C,子目录为my),Filel.Path的值为"C:\my" Filel.Path+Filel.FileName的值为"C:\my tl.txt",子目录与文件名之间少了一个"\"分隔符。
为了保证程序正常运行,
Open Filel.Path+Filel.FileNameForlnput As #1改为:
Dun F$
If Right(Filel.Path,1)"\" Then ' 表示选定的足根目录
F=Filel.Path+Filel.FileName
Else ' 表示选定的是子目录,子目录与文件名之间加"\"
F=Filel.Path+"\"+Filel.FileName
End If
Open F For Input As # 1
4.Open语句中欲打开的名是常量也可以是字符串变量,但使用者概念不清,导致出现"文件未找到"出错信息
如在从盘上读入文件名为"C:\my\t1.txt",
正确的常量书写如下:
Open "C:\my\t1.txt"For Input As#1 ' 错误的书写常量两边少双引号
或正确的变量书写如下:
Dim F$
F="C:\my\t1.txt"
Open F For Input As #1 ' 错误的书写变量F两边多了双引号
5.文件没有关闭又被打开,显示"文件已打开"的出错信息
如下语句:
Open"C:\my\t1.txt" For Input As #1
Print F
Open "C:\my\t1.txt" For Input As #1
Print "2";F
执行到第二句Open语句时显示"文件已打开"的出错信息。
6.如何读出随机文件中的所有记录,但又不知道记录号。
不知道记录号而又要全部读出记录,则只要同顺序文件的读取相似,采用循环结构加无记录号的Get语句即可,程序段如下:
Do While Not EOF(1)
Get #1, , j
Print j;
Loop
随机文件读写时可不写记录号,表示读时自动读下一条记录,写时插入到当前记录后。