iT邦幫忙

2

c/c++新手常犯的幾個語法錯誤,初學者請進

c/c++的語法嚴謹,但學習起來不易,
有時候一個小語法錯誤可能會讓人除錯找半天,
那我們來看看有哪些新手容易踩到的地雷吧

註: 為了文章撰寫的方便,
我們假設程式的開頭有加上這兩行引入寫c++輸出需要的標頭檔

#include <iostream>
using namespace std;

一、忘記加分號

分號在c++語言裡面蠻重要的,
就像寫作時一句話裡面的「句號」一樣,
每寫完一句話都必須要加分號,
譬如宣告整數、印出文字、…
例如:

int a;
int b = a+1;

每句話的結束都需要加分號哦

二、for迴圈內的分號誤用為逗號

c++裡面的for迴圈基礎語法形式為:

for(起始述句; 終止條件; 迭代述句)
    statement;

其中for裡面每個述句用一個分號隔開,
經典的例子是用for迴圈在螢幕上印出數字1~100:

for(int i=1; i<=100; i++)
    cout << i << endl;

for(int i=1; i<=100; i++)的部分稱為for標頭
新手容犯的錯誤是,
分號既然是一句話裡面的「句號」,
for標頭內的句子都寫在同一行,
看起來一句話並沒有結束,
不是應該用逗號隔開寫成for(int i=1, i<=100, i++)比較合理嗎?

因為for迴圈其實可以給多個變數初始值(雖然平時不太會這樣寫),
例如for(int i=1, j=0; i<=100; i++)
int i=1, j=0;整個都算是「起始述句」,
你全部用「逗號」隔開的話程式無法知道哪一塊是「起始述句」、「終止條件」、「迭代述句」

三、不加大括號區分程式區塊

很多新手在寫c++程式的時候,
可能會忘記為程式加上大括號,
以為只要縮排就可以了(如果一開始先學python語言可能尤其容易忘記),
例如:

int num;
for(int i=1; i<=3; i++)
    cin >> num;
    cout << num << endl;

作者的原意可能是想讀入3個數字,
每讀入一個數字時把它印出來,
但在c++語言中,若沒有加大括號,
程式無法得知哪些句子是包在for迴圈裡的,
上述程式會被解讀為

int num;
for(int i=1; i<=3; i++)
    cin >> num;
cout << num << endl;

效果是讀入三個數字,
但是印出最後一個讀入的數字
(實際上想寫的可能是讀三個數字,印出三個數字)

因此小馬建議只要碰上for, while, if, else
一律使用大括號把程式碼區塊包起來,修改如下:

int num;
for(int i=1; i<=3; i++){
    cin >> num;
    cout << num << endl;
}

四、if內的相等條件判斷寫成「=」

if(a = b)...是撰寫c++程式一個惡名昭彰的大臭蟲,
這樣的程式編譯是會過的,
所以相當難找出這個錯誤。
通常寫程式的人寫if(a = b)的時候,
他的原意應該是想判斷a是否和b相等

然而「=」和「==」在c++裡是不同的意思(在許多程式語言也是),
「=」是賦值的意思,例如

int a = 20;
int b = 30;
a = b;  // a = 30

這邊a = b的意思是說把b的值給a
所以a的值會變成30

「==」是邏輯上的判斷相等,a==b的值要嘛是true要嘛是false
所以判斷a是否和b相等要寫if(a == b)
如果寫成if(a = b)的意思是先將b的值給a
再判斷a的值是否為true(0視為false,非0都視為true),
與原意相差甚遠

五、if內「鏈式」不等式?

假設我們想要判斷int型別的整數a是否大於0且小於100,
新手可能會誤以為可以這樣寫

if(0 < a < 100){
    // do something
}

因為數學上不也常看到0 < a < 100的寫法嗎?
(註: 如果是python語言還真的可以寫0 < a < 100,但c++語言會解讀成別的意思)
但事實上if(0 < a < 100)會被解讀成if((0 < a) < 100)
首先比較是否0 < a,得到true(1)或false(0),
在把(0 < a)這個值跟100比較,由於1001大,
0 < a < 100的值永遠為true

正確的寫法為:

if(0 < a  && a < 100){
    // do something
}

六、switch-case中忘記加break

switch-case可視為是if-else的另一種簡便寫法,
例如底下的程式想用來檢測使用者輸入的英文字母母音(即a, e, i, o, u)各出現幾次:

unsigned aCnt=0, eCnt=0, iCnt=0, oCnt=0, uCnt=0;
char ch;
while(cin >> ch){
    //警告: 這是刻意寫錯的程式碼
    switch(ch){
        case 'a':
            aCnt++;
        case 'e':
            eCnt++;
        case 'i':
            iCnt++;
        case 'o':
            oCnt++;
        case 'u':
            uCnt++;
    }
}

但每個case後忘記加上break
這樣一來,當使用者輸入a時,
底下的程式仍然會繼續執行,
aCnteCntiCntoCntuCnt的值全部加一

<正確寫法>

unsigned aCnt=0, eCnt=0, iCnt=0, oCnt=0, uCnt=0;
char ch;
while(cin >> ch){
    switch(ch){
        case 'a':
            aCnt++;
            break;
        case 'e':
            eCnt++;
            break;
        case 'i':
            iCnt++;
            break;
        case 'o':
            oCnt++;
            break;
        case 'u':
            uCnt++;
            break;
    }
}

七、while迴圈多加分號(for, if語法同理)

新手學c++會學到「分號」表示一句話的結束,
所以習慣在每一句話的後面加上分號,
但未必總是對的,
例如:

int i = 0;
while(i<100);
    i++;

我們可以猜測寫這段程式碼的原意是說,
「當i<100的時候,我們就把i的值加1
請注意while的口語是「當(某條件)成立時,就一直做某件事」,

因此只有「當i<100的時候,我們就把i的值加1」才是一句完整的話,
你若寫while(i<100);直接加上分號的語意就成了「當i<100的時候,(不做任何事情)」,
因此i永遠會小於100而形成無窮迴圈,
正確的寫法:

int i = 0;
while(i<100)
    i++;

其實最建議的做法還是只要碰上for, while, if, else
一律使用大括號把程式碼區塊包起來,(如第三點所述)
比較知道自己在寫什麼

以上就是新手可能在c++語法上常犯的幾個錯誤啦~
祝大家也早日成為c++高手哦


尚未有邦友留言

立即登入留言