-
goto語句
鎖定
- 中文名
- 無條件轉移
- 外文名
- goto
- 領 域
- 網路
- 作 用
- 編寫程序
goto語句語句舉例
goto語句也稱為無條件轉移語句,其一般格式如下:
goto 語句標號;
label: i++; loop: while(x<7); goto loop;
goto 語句通常與條件語句配合使用。可用來實現條件轉移, 構成循環,跳出循環體等功能。
goto語句C# 語言
using System; using static System.Console; class Program { public static Int32 Main(String[]args){ int n = 0; WriteLine("input a string :\n"); judge: if (Read()!= '\r') { n++; goto judge; } WriteLine("{0}", n); return 0; } }
goto語句C語言
統計從鍵盤輸入一行字符的個數。
#include<stdio.h> int n=0; int main(void) { printf("input a string: "); judge: if (getchar()!='\n') { n++; goto judge; } printf("output: %d\n",n); }
例如輸入:abcdefghijklmnopqrstuvwxyz
然後回車Enter
輸出:26
然後轉移至if語句循環執行,直至輸入字符為'\n'才停止循環。
goto語句彙編語言
1+2+3........+8+9+10
NASM描述:
mov ax,1 mov bx,0 start:add bx,ax inc ax cmp ax,11;比較指令 jzend ;零轉移 jmp start end: ; ;start: end:是標號
goto語句Pascal
格式 goto <標號>;
其中標號需要申請,在程序開頭寫label <標號1>,<標號2>,……;
其中,標號必須為四位以內的正整數。
在該段落內還需要有<標號>:語句 表示將要轉向的方向。
goto語句delphi
//Goto語句用在跳轉行號, 可以跳轉到當前結構層內任意位置. //必須在聲明處用label關鍵字聲明行號. //由於Goto語句會破壞程序的結構, 不推薦使用. var a,b: Integer; label X,Y; begin if a > b then goto X else goto Y; X: WriteLn('a > b'); Y: WriteLn('b > a'); end;
goto語句批處理
使用冒號標記
:start goto start
goto語句按鍵精靈
使用rem做標記,可以用中文
rem 開始
goto 開始
goto語句VBA
使用冒號做標記,但是跟批處理的不一樣,冒號在後面
start: goto start
goto語句發展歷程
問題起源
20世紀60年代中期以後,計算機硬件技術日益進步,計算的存貯容量、運算速度和可靠性明顯提高,生產硬件的成本不斷降低。計算機價格的下跌為它的廣泛應用創造了極好的條件。在這種形勢下,迫切要求計算機軟件也能與之相適應。因而,一些開發大型軟件系統的要求提了出來。然而軟件技術的進步一直未能滿足形勢發展的需要,在大型軟件的開發過程中出現了複雜程度高、研製週期長、正確性難以保證的三大難題。遇到的問題找不到解決辦法,致使問題堆積起來,形成了人們難以控制的局面,出現了所謂的“軟件危機”。為了克服這一危機,一方面需要對程序設計方法、程序的正確性和軟件的可靠性等問題進行系列的研究;另一方面,也需要對軟件的編制、測試、維護和管理的方法進行研究,從而產生了程序設計方法學。
goto語句是有害的觀點
1968年,Edsger Wybe Dijkstra首先提出“goto 語句是有害的”論點,向傳統程序設計方法提出了挑戰,從而引起了人們對程序設計方法討論的普遍重視。
goto語句的爭論
在20世紀60年代末和70年代初,關於 goto 語句的用法的爭論比較激烈。主張從高級程序語言中去掉 goto 語句的人認為,goto 語句是對程序結構影響最大的一種有害的語句,他們的主要理由是: goto 語句使程序的靜態結構和動態結構不一致,從而使程序難以理解,難以查錯。去掉 goto 語句後,可直接從程序結構上反映程序運行的過程。這樣,不僅使程序結構清晰,便於理解,便於查錯,而且也有利於程序的正確性證明。
持反對意見的人認為, goto 語句使用起來比較靈活,而且有些情形能提高程序的效率。若完全刪去 goto 語句,有些情形反而會使程序過於複雜,增加一些不必要的計算量。
關於goto語句的解決方法
1974年,高德納對於 goto 語句爭論作了全面公正的評述,其基本觀點是:不加限制地使用 goto 語句,特別是使用往回跳的 goto 語句,會使程序結構難於理解,在這種情形,應儘量避免使用 goto 語句。但在另外一些情況下,為了提高程序的效率,同時又不至於破壞程序的良好結構,有控制地使用一些 goto 語句也是必要的。用他的話來説就是:“在有些情形,我主張刪掉 goto 語句;在另外一些情形,則主張引進 goto 語句。”從此,使這場長達10年之久的爭論得以平息。
後來,Corrado Böhm及Giuseppe Jacopini從理論上證明了:任何程序都可以用順序、分支和重複結構表示出來。這個結論表明,從高級程序語言中去掉 goto 語句並不影響高級程序語言的編程能力,而且編寫的程序的結構更加清晰。
goto語句的結果
在C/C++等高級編程語言中保留了 goto 語句,但被建議不用或少用。在一些更新的高級編程語言,如Java不提供goto語句,它雖然指定goto作為關鍵字,但不支持它的使用,使程序簡潔易讀;儘管如此後來的c#還是支持 goto 語句的, goto 語句一個好處就是可以保證程序存在唯一的出口,避免了過於龐大的 if嵌套。
可以考慮使用goto的情形
1.從多重循環中直接跳出
很多人建議廢除C++/C的goto語句,以絕後患。但實事求是地説,錯誤是程序員自己造成的,不是 goto 的過錯。goto 語句至少有一處可顯神通,它能從多重循環體中一下子跳到外面,用不着寫很多次的break語句。例如:
for(......){ for(....){ for(.....){ // 如何衝出重重包圍? } } }
break; 只能跳出單層的循環,return 將整個函數都返回了,沒法再繼續了,顯然也不行,所以我們想到了 goto 。如果是在陷入了很深層次的循環裏想要跳出最外層的循環,用 goto 直接跳出卻比用 break 一個循環一個循環地跳出要好得多。有人甚至形象比喻説:“就像樓房着火了,來不及從樓梯一級一級往下走,可從窗口跳出火坑。” 其實,你可以將 break 和 continue 理解成弱化了的 goto 語句。
2. 出錯時清除資源
如果一個函數有多個出口,則在每個出口處,會產生巨大的退出代碼,如下例一,每個函數只能有一個出口,所有的資源釋放必須放在出口統一解決,那全部使用大括號,十幾個,幾十個 if 判斷條件下來,大括號深得數不清。這種代碼可讀性不好,一旦寫錯了,難於尋找錯誤。所有這些問題,一個 goto 就解決了。
當程序要分配和清除資源時(像內存、或處理字形、窗口、打印機),這種情形下用 goto 通常是為了複製代碼或清除資源。若遇到這種情況,程序員就要掂量是 goto 的缺點更討厭,還是複製代碼那令人頭痛的維護更討厭,最後還是認為 goto 的缺點更可忍受。
例子一:不用 goto ,想想需要申請的指針是10個的話,程序怎麼寫?
void Func(void) { char* p1=null; char* p2=null; char* p3=null; p1=(char*)malloc(10); if(!p1) return; p2=(char*)malloc(10); if(!p2) { free(p1); p1=null; return; } p3=(char*)malloc(10); if(!p3) { free(p1); p1=null; free(p2); p2=null; return; } …… //指針使用過程 if(p1) { free(p1); p1=null; } if(p2) { free(p2); p2=null; } if(p3) { free(p3); p3=null; } }
例子二:用 goto
void Func(void) { char* p1=null; char* p2=null; char* p3=null; p1=(char*)malloc(10); if(!p1) goto Func_End_Process; p2=(char*)malloc(10); if(!p2) goto Func_End_Process; p3=(char*)malloc(10); if(!p3) goto Func_End_Process; … //指針使用過程 Func_End_Process: if(p1) { free(p1); p1=null; } if(p2) { free(p2); p2=null; } if(p3) { free(p3); p3=null; } }
3.可增加程序的清晰度的情況。
若不使用goto語句會使功能模糊,有時候使用 goto 語句,一眼就看清楚了程序的意圖,可用那些對應的循環break語句等實現的語句段,要想老半天才搞清楚程序意圖的情況,也可考慮使用 goto 語句。
不加限制地使用 goto 帶來的弊端
1.很明顯,不加限制地使用goto破壞了清晰的程序結構,使程序的可讀性變差,甚至成為不可維護的"麪條代碼"。例如下例:
A: //code section A //code goto B; //code goto C; B: //code section B //code goto A; //code goto C; C: //code section C //code //goto B; //code goto A;
這樣好像已經能夠説明問題了,隨着標籤的增多,帶來的混亂局面是很難扭轉的,對調試、走讀、理解代碼都會造成很大的障礙,如果寫這樣的代碼,那代碼維護絕對會是一場噩夢。
2.不加限制地使用goto經常帶來錯誤或隱患。它可能跳過了某些對象的構造、變量的初始化、重要的計算等語句,例如:
goto state; String s1, s2; // 被goto 跳過 int sum = 0; // 被goto 跳過 …… …… state: ……
如果編譯器不能發覺此類錯誤,每用一次 goto 語句都可能留下隱患。
goto語句與結構化程序設計
goto語句問題的提出直接推動了結構化程序設計(structured programming)的思想和程序設計方法學的誕生和發展。結構化程序設計方法引入了工程思想和結構化思想,使大型軟件的開發和編程都得到了極大的改善。
- 自頂向下:程序設計時,應先考慮總體,後考慮細節;先考慮全局目標,後考慮局部目標。不要一開始就過多追求眾多的細節,先從最上層總目標開始設計,逐步使問題具體化。
- 逐步求精:對複雜問題,應設計一些子目標作為過渡,逐步細化。
- 模塊化:一個複雜問題,肯定是由若干稍簡單的問題構成。模塊化是把程序要解決的總目標分解為子目標,再進一步分解為具體的小目標,把每一個小目標稱為一個模塊。
- 限制使用 goto 語句
結構化程序設計方法的起源來自對 goto 語句的認識和爭論。肯定的結論是,在塊和進程的非正常出口處往往需要用 goto 語句,使用 goto 語句會使程序執行效率較高;在合成程序目標時,goto 語句往往是有用的,如返回語句用goto。否定的結論是,goto 語句是有害的,是造成程序混亂的禍根,程序的質量與 goto 語句的數量呈反比,應該在所有高級程序設計語言中取消 goto 語句。取消 goto 語句後,程序易於理解、易於排錯、容易維護,容易進行正確性證明。作為爭論的結論,1974年高德納發表了令人信服的總結,並證實了:
- goto 語句確實有害,應當儘量避免;
- 完全避免使用 goto 語句也並非是個明智的方法,有些地方使用 goto 語句,會使程序流程更清楚、效率更高。
- 爭論的焦點不應該放在是否取消 goto 語句上,而應該放在用什麼樣的程序結構上。其中最關鍵的是,應在以提高程序清晰性為目標的結構化方法中限制使用 goto 語句
關於 goto 使用語句的一些建議
goto 語句在結構化編程技術出來後,被當作破壞結構化程序的典型代表,可以説,在結構化程序設計年代,goto 語句就像洪水猛獸一樣,程序員都唯恐避之不及;可後來在微軟的一些例子程序中經常把 goto 語句用來處理出錯,當出錯時,goto 到函數要退出的一個label那裏進行資源釋放等操作。goto 語句也不是隻可以用於出錯處理,其它地方都不可以用了。下列關於使用 goto 語句的原則可以供讀者參考。
- 使用 goto 語句只能 goto 到同一函數內,而不能從一個函數里goto到另外一個函數里。
- 使用 goto 語句在同一函數內進行 goto 時,goto 的起點應是函數內一段小功能的結束處,goto 的目的label處應是函數內另外一段小功能的開始處。
- 應該避免向兩個方向跳轉。這樣最容易導致"麪條代碼"。