上一章
不知你在之前的章節中做練習時,電腦是否莫名其妙地說你寫錯呢?
舉個例子
還記得第6章的練習題嗎?
題目是這樣的:
「輸入一個整數n,然後輸入n個數字
最後把這n個數字的順序顛倒,然後輸出」
當你學完陣列之後,馬上就興高采烈地寫下了程式碼:
#include<cstdio> int main() { int n; scanf("%d",&n); int a[n]; int i=0; while(i<n) { scanf("%d",&a[i]); i=i+1; } int i=n-1; while(i>=0) { printf("%d ",a[i]); i=i-1; } printf("\n"); }
然後,電腦就說你寫錯了
然後,電腦就說你寫錯了XD |
p.s. 雖然之前的章節完全沒有提到,這個命名不能重複的規則請讀者務必了解,仔細想想應該就會發現這個規則合情合理,否則最後會分不清楚「i」到底是指哪一個變數
如果你還是搞不懂發生了甚麼事,將上面的程式碼和第6章提供的程式碼解答比對一下,看看有甚麼差別吧~
現階段,這種問題是很好解決的
以目前的知識,可以想到的方法有2種:
1. 重複利用「i」這個變數 (也就是第6章採用的方法):
#include<cstdio> int main() { int n; scanf("%d",&n); int a[n]; int i=0; while(i<n) { scanf("%d",&a[i]); i=i+1; } i=n-1; while(i>=0) { printf("%d ",a[i]); i=i-1; } printf("\n"); }
2. 用不同的名稱宣告一個新的變數 (例如將新變數取名為「j」):
#include<cstdio> int main() { int n; scanf("%d",&n); int a[n]; int i=0; while(i<n) { scanf("%d",&a[i]); i=i+1; } int j=n-1; while(j>=0) { printf("%d ",a[j]); j=j-1; } printf("\n"); }
你可能覺得這樣沒有問題
但是,當你的程式稍微複雜一點的時候
你會很容易搞不清楚,對於特定的一個變數,現在到底有沒有在「使用中」 (假如你使用了方法1.)
或者記不住每一個變數的用途 (假如你使用了方法2.)
難道我們就是沒辦法「用相同的名稱宣告一個新的變數」嗎?
可以的!
我們只要設定好每一個變數的「作用範圍 (Scope)」(或者說「有效範圍」)
也就是說,對於每一個變數,我們可以設定程式碼的哪幾行可以使用它
方法是使用「大括號」框出「作用範圍」
這樣一來,在這個「大括號」裡面宣告的變數,都不能在「大括號外面」使用
事實上,連「if」和「while」的大括號,都有這個功能
廣泛地講,只要出現「大括號」,都會發揮同樣的作用
這樣說你可能還沒有畫面,我們來看看要怎麼利用這個特性來解決上面的問題:
#include<cstdio> int main() { int n; scanf("%d",&n); int a[n]; { int i=0; while(i<n) { scanf("%d",&a[i]); i=i+1; } } { int i=n-1; while(i>=0) { printf("%d ",a[i]); i=i-1; } } printf("\n"); }
可以看到,我們宣告了兩個名稱相同的變數「i」,但是是在不同的大括號裡面宣告,因此它們互不影響
另外,在這兩個大括號外面也無法使用這兩個「i」
甚麼意思呢?
我們來做個測試:
#include<cstdio> int main() { int n; scanf("%d",&n); int a[n]; { int i=0; while(i<n) { scanf("%d",&a[i]); i=i+1; } } { int i=n-1; while(i>=0) { printf("%d ",a[i]); i=i-1; } } printf("%d\n",i); printf("\n"); }
可以發現,在新加的那一行「printf("%d\n",i);」發生錯誤了!
電腦說你這行寫錯了 |
因此,對於「printf("%d\n",i);」來說,你根本沒有宣告過「i」這個變數!
當然,你可以在「printf("%d\n",i);」前面補宣告「i」,讓電腦可以順利讀完你的程式碼:
#include<cstdio> int main() { int n; scanf("%d",&n); int a[n]; { int i=0; while(i<n) { scanf("%d",&a[i]); i=i+1; } } { int i=n-1; while(i>=0) { printf("%d ",a[i]); i=i-1; } } int i; printf("%d\n",i); printf("\n"); }
再次提醒,這個程式碼中的3個「i」,它們的作用範圍都是不同的,因此是互不影響的
也就是說,當你修改其中一個「i」的數值,另一個「i」的數值是保持不變的
所以,你應該把這3個「i」當作不同的變數,只是名稱相同而已
那麼,如果作用範圍「重疊」了
怎麼辦?
例如,我把程式碼修改成這樣:
#include<cstdio> int main() { int n; scanf("%d",&n); int a[n]; { int i=0; while(i<n) { scanf("%d",&a[i]); i=i+1; } } int i; { int i=n-1; while(i>=0) { printf("%d ",a[i]); i=i-1; } } printf("%d\n",i); printf("\n"); }
可以發現,「第3個『i』(『int i=n-1;』那一行) 的作用範圍」包含在「第2個『i』(『int i;』那一行) 的作用範圍」裡面!
那麼,對於
while(i>=0) { printf("%d ",a[i]); i=i-1; }
這段程式碼
它用到的會是哪一個「i」呢?
答案是「第3個『i』」
這是C++的隱藏規則 (非潛規則,見註5)
當多個相同名稱的變數的作用範圍重疊的時候,會以「最後被宣告」的那一個變數為優先 (也就是「作用範圍最小」的那個變數)
仔細想想,其實規則這樣定可以帶來很多方便
不過,我還是強烈建議,盡量不要讓「作用範圍重疊」的情況發生
因為這種情況常常會造成別種不必要的麻煩,也就是「無法使用外面相同名稱的變數」
不知道你目前覺得本章教的知識有沒有用
但是,我相信
你總有一天會想要用到它
對了,還記得我們提過「for迴圈」嗎?
來介紹一下吧~
我們可能常常要用迴圈做到 (或類似) 下面這件事:
#include<cstdio> int main() { { int i=1; while(i<=10) { printf("i=%d\n",i); i=i+1; } } { int i=10; while(i>=1) { printf("i=%d\n",i); i=i-1; } } return 0; }
注意到
我們需要用大括號把「int i=?;」和「while迴圈」框起來,限制變數「i」的作用範圍,才能在兩個不同迴圈使用相同名稱 (都是「i」) 的變數
這可以用「for迴圈」來精簡成這樣:
#include<cstdio> int main() { for(int i=1;i<=10;i++) { printf("i=%d\n",i); } for(int i=10;i>=1;i--) { printf("i=%d\n",i); } return 0; }
哇塞,太讚了吧!連限制作用範圍的大括號都可以省了!
看得出來,你很快就會愛上它!(註12)
下一章
感謝:李旺陽學長
(版權所有 All copyright reserved)
補宣告i的那個程式碼會多輸出一個0喔
回覆刪除還有 想問一下
{int n=2;} int n; printf("%d",n);
為什麼補宣告n卻會輸出1
而如果去掉前面的大括號變成:
int n; printf("%d",n);
就會輸出0?
如果這樣不能補宣告的話為什麼文章中的i就可以
還有 如果大括號內的互不影響
刪除為什麼把前面的大括號去掉後面的數值會改變