
3.2 常规数据操作方法
虽然一种数据类型对应多种数据操作方法,但是被实例化的各种数据结构操作也有一些常规的操作方法。
当基本控件(或类对象)被拖放至前、后面板或设计人员在前面板完成了数组或簇的构建时,控件对应的数据结构就实现了实例化。实例化的数据结构按其取值是否可改变分为常量和变量两种。在程序执行过程中,其值不发生改变的量称为常量,其值可变的量称为变量。此外它们可与数据类型结合起来分类。例如,可分为整型常量、整型变量、浮点常量、浮点变量、字符常量、字符变量、枚举常量、枚举变量。在设计过程中,常量、变量以及它们的类型均可以通过控件的右键菜单项来选定或创建,参见图3-3。

图3-3 LabVIEW中创建变量或常量,并指定类型
换个角度来看,由于常量在程序执行过程中值不发生改变,因此具有只读访问权限。输入控件仅用于传递用户输入的数据给应用程序(后面板),虽然程序运行过程中它的值可不断变化,但输入控件自身仅相当于一个具有只读权限的局部变量;同理,显示控件自身仅为一个具有写权限的局部变量。任何放置在前面板的控件或显示控件在后面板中仅对应一个端子,程序将通过控件在后面板上的端子与前面板进行数据交换。然而,往往需要在程序多处读和写某个输入控件或显示控件的值,后面板仅有的一个端子无法满足要求,这时候就可以使用控件对应的局部变量(Local Variable)或值属性节点(Value Property Nodes,创建方法与局部变量创建方法类似)。
如果从作用域来分,变量可分为全局变量(Global Variable)和局部变量(Local Variable)两类。全局变量在整个应用程序中都可访问,常用于在程序中的多个VI之间进行数据传递和访问。全局变量是LabVIEW内置对象,当从函数面板上选择创建全局变量时,后面板上将生成一个“全局变量节点”(Global Variable Node,),LabVIEW同时自动创建一个仅有前面板的全局VI,双击全局变量节点打开此VI,随后就可以添加程序中需要的数据类型。一旦添加完成,就可以将全局变量节点与某一数据类型绑定,并可在不同VI中访问此全局变量,如图3-4所示。

图3-4 全局变量的创建
与全局变量不同,局部变量仅可在单个VI中访问。控件对应的局部变量始终与其自身的值保持同步,然而从读写权限来看却与控件稍有差别。输入控件自身在程序中为只读权限的局部变量,显示控件为只写权限的局部变量,但是无论对于输入控件还是显示控件,都可在程序中创建用于数据访问的“只读局部变量”和“只写局部变量”。如图3-3所示,这可以通过在控件右键菜单中选择“创建”(Create)→“局部变量”(Local Variable)选项来实现。默认情况下,创建的局部变量读写权限根据控件自身是输入控件还是显示控件而定,如果是输入控件,则为只读局部变量;若是显示控件,则为只写局部变量。如果想创建一个与输入控件或显示控件自身访问权限相反的局部变量,则需在创建具有默认读写权限的局部变量后,再通过选择所创建局部变量的右键菜单的“变更为只读”(Change To Read)或“变更为只写”(Change To Write)选项来进行转换。例如前面板上有一个名为Control的控件(其默认权限为只读),若想为其创建一个写权限的局部变量,则可以先通过选择其右键菜单中“创建”(Create)→“局部变量”(Local Variable)选项,生成一个具有只读权限的局部变量,随后再选择所创建变量的右键菜单中的“变更为只写”(Change To Write)选项,将其读写权限变为“只写”即可,如图3-5所示。

图3-5 改变局部变量的读写权限
在读写权限这一点上,控件的“值属性节点”与控件对应的局部变量相同。可以在程序中创建对应于控件的“读属性节点”和“写属性节点”,并可通过属性节点的右键菜单中的“变更为只读”(Change To Read)或“变更为只写”(Change To Write)选项变更其读写属性。
LabVIEW使用连线在对象之间进行数据传递。每个连线有单独的数据源(Data Source),但可以将数据源与多个读取数据的对象相连。根据所传递数据类型的不同,连线颜色、粗细也会不同。当出现错误时,连线会显示为断开,同时在连线中显示红色的交叉。在LabVIEW中使用连线时,一般会用到线段(Wire Segment)、拐点(Bend)和交叉点(Junction)的概念。线段是指一段纵向或横向的连线,拐点是两个线段的交汇点,而交叉点是指数据的分叉点,如图3-6所示。

图3-6 LabVIEW中的连线
基于上述内容不难归纳出控件数据访问以及变量和属性节点赋值的方法。以图3-7为例,在前面板中有一个控件Control和一个显示控件Indicator,那么可以通过直接将Control与Indicator相连、Control只读局部变量与Indicator只写局部变量相连、Control只读值属性与Indicator只写值属性相连以及直接将常量与Indicator相连来显示控件Indicator赋值。有时程序还需进行控件数据的访问,例如使用显示控件的值来改变控件的值,那么直接连线的方法就不能奏效,可以使用显示控件的只读局部变量与控件的只写局部变量相连、显示控件的只读值属性与控件的只写值属性相连来达到目的。

图3-7 控件数据读写和变量赋值
虽然使用连线、全局变量、局部变量和属性节点都可以达到数据传递的目的,但是从使用效率上来看却大相径庭。LabVIEW会为局部变量创建独立于控件的数据缓冲区,如果使用局部变量在程序中传递大量的数据,通常会消耗大量的内存。与局部变量类似,全局变量也会为存储在其中的数据创建单独的备份。当使用全局变量进行大数组或字符串操作时,对内存和时间的消耗极为可观,这是因为即使修改数组或字符串中任意一个元素或字符,程序都会重新保存,更新整个数组或全部字符串。此外,如果在多个VI中访问全局量,则会创建多个数据的备份,这会大大降低程序的效率。属性节点在操作上与变量类似,但是使用属性节点时,程序会迫使用户界面线程用前面板的数据更新内存缓冲。相比较而言,直接连线是最为有效的数据传递方式,因此在后面板中应尽量使用连线方式进行数据传递。此外,在程序运行时使用寄存器(Shift Register)也是比较好的数据传递方式,这部分内容将在后续章节介绍。
LabVIEW会自动为拖放至前面板的输入控件或显示控件分配默认值(表3-1),如果不在设计时或程序初始化过程中更改这些默认值,那么程序启动后控件的数值将使用默认值。很多情况下,需要为控件指定一个与系统默认值不同的初始值或默认值,例如一个代表电压的数值控件,其初始值可能不是0.0V而是3.5V,可以通过以下办法实现:
(1)设计时在控件中输入希望的默认值,然后选择控件的右键菜单中的“数据操作”(Data Operations)→“设置为默认值”(Make Current Value Default)选项,参见图3-8。

图3-8 设置控件默认值
(2)在程序运行之初,通过常量为控件赋值,例如。
(3)使用变量的赋值方法使控件的初始值与其他控件相同。
在程序中为控件明确指定初始值是一个非常好的习惯。很多程序运行时的问题,都与程序未正确初始化有关,而且因此带来的问题往往比较隐晦,很难排除。不仅是初始化,在程序设计的各部分坚持清晰明确的数据传递也是保证程序健壮性的重要手段。
在LabVIEW中,不同类型的数据分别对应多种数据操作,例如整型数据可进行加、减、乘、除等多种操作。反过来看,某一操作也有可能适应多种数据类型,例如可以进行加法操作的不仅有整型数、浮点数,甚至数组和字符串也可以进行加法操作,这种可以接受不同输入数据类型的能力称为“多态”。在LabVIEW中函数和VI用于实现各种对数据的操作方法,能接受不同输入数据的函数和VI被称为多态函数或多态VI。函数和VI的多态能力可强可弱。例如,有些函数或VI可能根本不具备多态能力,有些只有部分输入参数具有多态能力,有些则所有输入参数都具有;有些输入可以接受数值或布尔量,有些则接受数值、字符串、数组、簇甚至元素为数组的簇,等等。图3-9展示了加法操作和“逻辑与”操作的多态性。

图3-9 加法操作和“逻辑与”操作的多态性
虽然以上提到的变量创建、赋值、初始化操作和多态性均以数值控件为例进行讲解,然而这些操作几乎对所有类型的数据、函数和VI都适用。从这个角度来说,初学者不要仅仅将这些操作局限在基本数据类型上,要学会举一反三。例如,类对象实例可通过类似操作,赋值给其他类对象的变量,如图3-10所示。

图3-10 将类对象常量赋值给类对象变量