delphi中case of问题
case a of 这个的a只能是整型数字呀!您可以这样做,用ComboBox1.ItemIndex属性来做:
i:= ComboBox1..ItemIndex;
case i of
0: ADOTable1.FieldByName('pid').AsString:= '0';//对应***部
1: ADOTable1.FieldByName('pid').AsString:= '1';//对应人事部
2: ADOTable1.FieldByName('pid').AsString:= '2';//财务部
3: ADOTable1.FieldByName('pid').AsString:= '3';//技术部
----------------------------------------------
针对您的补充,回答:
问题补充:i:=ComboBox1.ItemIndex; 报错Incompatible, types:'string' and 'Integer'//没有定义i,您必须先定义i:integer;
case i of 报错Ordinal type required
0: ADOTable1.FieldByName('pid').AsString:= 1; 报错Incompatible types:'string' and 'Integer'// 用‘’把1括起来,因为是字符串的。
1: ADOTable1.FieldByName('pid').AsString:= 2; 同上// 用‘’把2括起来,因为是字符串的。
2: ADOTable1.FieldByName('pid').AsString:= 3; 同上// 用‘’把3括起来,因为是字符串的。
?
===================================================================
?
?
?
只用过几天的vb, ? 不知道vb怎样.
对于in来判断一个字符串是否在集合中,你可以绕一下,不用集合,使用AnsiIndexStr。
比如:
S ? := ? 'ABC ';
case ? AnsiIndexStr(S, ? [ 'ABC ', ? 'DEF ', ? 'GHI ']) ? of
? ? 0: ? //ABC
? ? ;
? ? 1: ? //DEF
? ? ;
? ? 2: ? //GHI
? ? ;
end;
in是二进制操作符,相当于test指令,相当于判断(element ? and ? elements) ? > ? 0。如果允许string
作为集合的元素,那么首先集合会变成一个Variant ? array,因为集合的成员已经不能用位来
表示这么简单了,这样的话,你声明一个简单集合,在不支持字符串的情况下可能只需要1个
字节,如果支持string的话,就会大得多,而且集合操作极其低速,因为要对variant ? array
进行操作,要判断数组的长度,元素的类型。这当然比不上的位操作来得快,也许你到时候
又要抱怨为什么它的in操作为什么这么慢了,集合要占这么多内存,你甚至也会像这里的一
位大佬那样说,pascal太次了。
对于为什么case只接受有序类型(枚举也是有序类型),不接受其他类型如字符串,大概原因可
能和字符串不能作为集合元素的原因相同。
至于为什么不能使用:
case ? Sender ? of
? ? Button1: ? stmt1;
? ? Button2: ? stmt2;
? ? ...
end;
的原因,我想可能是语义问题。
如果不限制判别式为常量表达式,会导致语义二义性,
如果Button1或Button2是变量或函数调用,那么运行时,Button1和Button2有可能等值。那
么当Sender ? = ? Button1 ? = ? Button2时,到底执行stmt1, ? 还是执行stmt2呢?
你还是可以绕一下,这样调用:
if ? Sender ? is ? TComponent ? then
? ? case ? TComponent(Sender).Tag ? of
? ? ? ? 1: ? //Button1
? ? ? ? ;
? ? ? ? 2: ? //Button2
? ? ? ? ;
? ? ? ? ...
? ? end;
当然前提是各个Button的tag是unique的。
除了二义性,还有一个是优化的问题,如果限制使用常量表达式,则代码通常较为有效一点。
像这样的语句:
case ? TComponent(Sender).Tag ? of
? ? 1: ? stmt1;
? ? 3: ? stmt3;
? ? 5: ? stmt5;
? ? ...
? ? n: ? stmtn;
else
? ? stmt_else;
end;
当case分支足够长,编译的大概会像这样编指令序列:
编译器预先计算好这样一个指令偏移表:
jmp_offset[1..n] ? = ? (
? ? ? ? addr_of_stmt1 ? - ? addr_of_stmt_else, ? ? ? ? ? ? //for ? case ? 1
? ? ? ? 0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , ? ? ? ? ? ? //for ? case ? 2
? ? ? ? addr_of_stmt3 ? - ? addr_of_stmt_else, ? ? ? ? ? ? //for ? case ? 3
? ? ? ? 0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , ? ? ? ? ? ? //for ? case ? 4
? ? ? ? addr_of_stmt5 ? - ? addr_of_stmt_else, ? ? ? ? ? ? //for ? case ? 5
? ? ? ? ...,
? ? ? ? addr_of_stmtn ? - ? addr_of_stmt_else ? ? ? ? ? ? ? //for ? case ? n
); ? //如果else的机会较小则可能会以addr_of_stmt1来作为基地址
register ? := ? TComponent(Sender).Tag;
compare ? register, ? 0
if ? less_or_equal ? then ? goto ? stmt_else
compare ? register, ? n
if ? great_than ? then ? goto ? stmt_else
goto ? addr_of_stmt_else ? + ? jmp_offset[register]
但是允许变量判别式的话,
case ? Sender ? of
? ? Button1: ? stmt1;
? ? Button3: ? stmt3;
? ? Button5: ? stmt5;
? ? ...
? ? ButtonN: ? stmtN;
else
? ? stmt_else;
end;
则指令序列类似于:
register ? := ? Sender;
compare ? register, ? button1
if ? equal ? then ? goto ? stmt1
compare ? register, ? button3
if ? equal ? then ? goto ? stmt3
compare ? register, ? button5
if ? equal ? then ? goto ? stmt5
...
compare ? register, ? ButtonN
if ? equal ? then ? goto ? stmtN
?