我读到使用Goto
命令是非常糟糕的,可能会弄乱你的代码。我还读到有一项民意调查显示,如果他们看到goto
命令和delphi在一起,而另外40%的人甚至不知道goto
命令,那么40%的Delphi开发人员会非常交叉那是为什么?
但无论如何,我正在制作一个程序,通过获得两个分数并获得这两个分数的平均值来检查你是否有资格获得助学金。为了获得助学金,您需要达到90%或更高的平均值,它将在标签中显示您的平均值,如果您符合其他标签的资格。我最近也了解了If
命令,现在我正忙着玩它。
这是我的代码:
procedure TForm1.btnCalcClick(Sender: TObject);
var
iMaths, iScience, iAvarage : integer;
begin
iScience := sedScience.value;
iMaths := sedMath.value;
iAvarage := round((iMaths+iScience)/2);
if iMaths = 0
then
begin
showmessage ('Sorry, please put a propper value in the Maths and Science box!');
end;
if iAvarage >= 90
then
begin
lblAvarage.caption := 'Your avarage is: ' + IntToStr (iAvarage);
lblOutput.caption := 'You qualify for an Einstein Bursary!';
end
else
begin
lblAvarage.Caption := 'Your avarage is ' + IntToStr (iAvarage);
lblOutput.caption := 'Sorry, you do not qualify for an Einstein bursary.';
end;
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
sedMath.value := 0;
sedScience.value := 0;
lblAvarage.caption := ' ';
lblOutput.caption := ' ';
sedMath.setfocus
end;
end.
我说if iMaths = 0
只是确保SpinEdit中有一个值,如果没有,它必须在ButtonClick处理程序中重新启动,并显示一条消息Please insert a proper value
。一切正常,但它仍然显示标签中的平均值(lblOutput和lblAvarage),我不希望它这样做!
如果我使用goto
命令,我认为它应该是这样的:
procedure TForm1.btnCalcClick(Sender: TObject);
var
iMaths, iScience, iAvarage : integer;
label
lRestart;
begin
lRestart;
iScience := sedScience.value;
iMaths := sedMath.value;
iAvarage := round((iMaths+iScience)/2);
if iMaths and iScience = 0
then
begin
showmessage ('Sorry, please put a propper value in the Maths and Science box!');
goto lRestart;
end;
(顺便说一句,我知道上面的代码错了,我试过了!)
我用Google搜索goto
,但我找到的东西与我需要的东西不同。
非常感谢有关如何使用goto
命令的任何帮助或建议!
答案 0 :(得分:6)
goto
的语法不正确。它应该是:
procedure TForm1.btnCalcClick(Sender: TObject);
....
label
lRestart;
begin
lRestart:
....
goto lRestart;
....
end;
但是如果你想做这样的事情,你肯定会通过这样写出来避免goto
:
repeat
// do something
until OkToContinue;
那就是说,你的代码应该是:
procedure TForm1.btnCalcClick(Sender: TObject);
var
iMaths, iScience, iAverage: integer;
begin
iScience := sedScience.value;
iMaths := sedMath.value;
iAverage := round((iMaths+iScience)/2);
if (iMaths=0) or (iScience=0) then
begin
ShowMessage('Sorry, please put a propper value in the Maths and Science box!');
exit;
end;
// do the calculation
end;
您的事件处理程序中不需要循环或goto
。您必须在发现错误时退出,并让用户有机会修复错误并再次单击该按钮。因此,您只需要完全错误地认为您需要goto
。
我猜你还没有完全掌握事件驱动编程的概念。如果你回到开头而不是退出程序,用户就没有机会修改旋转编辑控件的值,你会一次又一次地显示消息。试一试,看看我的意思。
另请注意,我在您的代码中修复了许多其他错误。
至于goto
,我相信你永远不会需要它。我只发现goto
在不支持结构化异常的语言中有用。德尔福不属于那个阵营。
答案 1 :(得分:2)
您不需要在程序中使用goto
。
不使用它的一些原因,因为在大多数情况下:
repeat .. until
或while ..
结构,这些结构通常具有相同的精确时序(将编译为汇编程序jmp ..
操作码。有时,将repeat .. until
或while ..
结构的条件表达式放在循环中可能会稍快一些,并使用{ {1}}和break
以及continue
或repeat .. until false
:
while true do ..
将使用非常优化的汇编程序编译:
function GotoEndOfJSONString(P: PUTF8Char): PUTF8Char;
begin // P^='"' at function call
inc(P);
repeat
if P^=#0 then
break else
if P^<>'\' then
if P^<>'"' then
inc(P) else
break else
inc(P,2);
until false;
result := P;
end; // P^='"' at function return
但这对于非常低级别的代码来说可能是值得的,并且会降低其可读性。编写这样的代码非常接近直接编写汇编程序代码:您知道 inc eax
@s: mov dl,[eax]
test dl,dl
jz @e
cmp dl,$5c
je @2
cmp dl,$22
je @e
inc eax
jmp @s
@2: add eax,2
jmp @s
@e: ret
和break
将转换为直接continue
汇编程序操作码。
我使用jmp ..
的唯一情况是在一些明确定义的条件下:
goto
内部块之间或从一个循环到另一个循环之间需要分支时; case .. of
可以用goto
本地过程替换。一些例子:
inline
作为结论,在纯粹的pascal或某些低级代码的 FastCode质询之外,您不应再看到任何procedure TTextWriter.AddJSONEscape(P: Pointer; Len: PtrInt);
var c: PtrUInt;
label Esc, nxt;
begin
if P=nil then exit;
if Len=0 then
Len := MaxInt;
if B>=BEnd then
Flush;
repeat
inc(B);
// escape chars, according to http://www.ietf.org/rfc/rfc4627.txt
c := PByte(P)^;
if c>=32 then begin
if c in [ord('\'),{ord('/'),}ord('"')] then goto Esc;
B^ := AnsiChar(c);
nxt: if Len=1 then
break;
dec(Len);
inc(PByte(P));
if B<BEnd then
continue;
Flush;
end else
case c of
0: begin
dec(B); break; end;
8: begin
c := ord('b'); goto Esc; end;
9: begin
c := ord('t'); goto Esc; end;
$a: begin
c := ord('n'); goto Esc; end;
$c: begin
c := ord('f'); goto Esc; end;
$d: begin
c := ord('r');
Esc: B^ := '\';
if B>=BEnd then // inlined: avoid endless loop
Flush;
B[1] := AnsiChar(c);
inc(B);
goto nxt;
end;
else begin // characters below ' ', #7 e.g. -> // 'u0007'
B^ := '\';
AddShort('u00');
Add(HexChars[c shr 4],HexChars[c and $F]);
goto nxt;
end;
end;
until false;
end;
。