在這個程序里面由於用到了上篇文章中所說的字符串切割,而用到了Goto強制跳轉語句
但是在程序中使用的時候卻發現一個錯誤,當把這個字符切割的代碼段如果直接作為非嵌套語句執行正常
但是一旦放到for循環的復合語句中就會發現for循環只執行一次之后for循環就退出了,而且臨時變量%%x的值就變成空了
換句話說就是goto跳轉和目標地:labe不能同時出現在一個for語句中
例如下示例:
for /f %%i in ("abc") do ( :show echo %%i & pause goto :show )
直接看代碼含義很簡單就是一直去顯示abc這個字符串,但是實際執行結果卻是:
只有第一次循環正確的執行的我們想要的結果,顯示了abc,但是后面的所有都是顯示%i
換句話說,當goto跳轉后%i失去了原本for循環的臨時遍歷變量的作用,成了一個普通的字符串
至於為什么會這樣我是這樣理解的:
因為goto語句是無條件強制跳轉,並且無視程序流程,即不管目標標簽地是否是復合語句都會強制去順着標簽地向下執行,也許標簽地是主流程語句,也許是其他if的復合語句塊,也許是與goto是同屬一個復合語句塊,如果是跳轉到外側或其他語句塊,那么當前for循環肯定是要退出的。
但是CMD是邊解釋邊執行,他沒有辦法也沒有義務去檢查goto的標簽所在地是在哪,從理論上來講,如果跳轉到主流程沒有什么問題,如果跳轉到另一復合語句塊中肯定目標語句塊的臨時變量(%i)肯定是無效的,因為根本不知道從什么位置直接跳轉過來的,根本沒有執行主循環語句,何談臨時變量,臨時變量是由主循環語句賦予的。
唯獨goto和標簽同屬一個語句塊時臨時變量應該起效。但是作為邊解釋邊執行的解釋器,壓根無法預知下一條根本沒有輸入的語句的內容。
所以(結論):
在for語句中一旦遇到goto,則cmd認為這是break了,不管你跳轉到哪,當前for循環肯定是停止了,那么由for循環賦予的臨時變量(%i)也就隨之無效了。在剛才的例子中雖然跳轉完成了還是在for語句中,但cmd已經認為for循環已經退出,這是獨立語句了,而不是復合語句
解決方法:
把要進行goto的語句塊寫成一個函數,寫成一個獨立模塊,再在for中用Call去調用,就正常了
上面的例子改一下:
for /f %%i in ("abc") do ( call :show %%i ) :show echo %1 & pause goto :show
結果,如我們想要的,一直去顯示abc字符串
—— 原文發表於2012-3-11 08:57