撰寫 C 程式時常發生的語法錯誤

 

  內容



程式撰寫時常發生的語法錯誤

 

程式錯誤範例:

以下測試一些常常遇見的語法錯誤, 讓你看一下編譯器 (g++ 或是 gcc) 的錯誤訊息, 通常這些錯誤訊息都是可以解釋的, 你應該要嘗試去瞭解為什麼編譯器會給你那樣的錯誤訊息, 它在看到什麼樣的程式時會給你那樣的訊息, 這樣子你才會看到編譯器是藉由語法檢查來幫助你完成一個正確的程式, 而不是在找你麻煩, 這個也不認得, 那個也不認得..., 千萬不要忽視這些錯誤訊息, 盲目地用嘗試錯誤的方法修改程式, 或是道聽途說地修改程式, 做過這些練習以後, 自己打進去(或是拷貝進去)的程式, 自己應該要能夠預期它的語法是否正確, 清楚瞭解它的功能是什麼!!

1.

語法錯誤一

看一個錯誤訊息最重要的是看它在程式裡出現的位置, 上面第一個錯誤 Dev-C++ 顯示暗紅色區塊第5列printf的地方, 當然你第一個直覺可能會認為這裡怎麼有錯呢? 明明是在前面第 3 列少了東西, 編譯器指著第 5 列的地方說 "發現錯誤" 其實是有原因的, C 的程式編排是 格式自由 (free format) 的, 在程式裡每一個元素的順序是很重要的, 例如 int 之後接 main, 之後接左側小括號 (, 之後接 void, 之後接右邊小括號 ), 然後接大括號 {, ..., 你可以打成

int    main   (    void    ) {
或是
int
main(void)
{

順序是重要的, 但是空白字元, 換列, 怎麼對齊是自由的, 所以編譯器看到 void 時都還認為是對的, 編譯器根據語法預期接下來可能有右邊小括號 ) 或是逗點 , 但是不幸的是它在第四列發現接下來的是左大括號 {, 所以在這個地方編譯器才能確定這個程式的語法出現錯誤 , dev-C++ 界面顯示又落後了一列, 以暗紅色顯示第 5 列

另外有一件事很重要, 當編譯器發現語法錯誤以後, 它會嘗試去猜你漏掉了什麼, 你打錯了什麼, 然後儘可能去回復, 跳過一些錯誤的程式元素, 繼續檢查剩下程式碼的語法, 不過因為要編譯器正確地跳過所有的錯誤是相當困難的, 因此常常編譯器的第二個以後的錯誤都沒有太大的參考價值...建議你由第一個錯誤開始改, 一次只改一個錯誤, 改完以後立刻重新編譯, 一個一個錯誤往下修改...不要貪心想要一次就改很多個錯誤, 像這個例子中, 出現在第 5 列『少掉分號』的錯誤你就暫時不需要太在意它。

2.

語法錯誤二

在第 5 列的地方編譯器看到 printf, 看到左小括號 (, 接下來編譯器預期應該是一個 字串 或是 字元陣列變數, 編譯器看到 Hello 時, 會去檢查先前的變數定義, 看看有沒有 Hello 的定義, 因為沒有看到, 所以它就說 `Hello' was not declared in this scope, 前面那個 stray '\' 和 missing terminating " character 的訊息就請你暫時略過, 等你修改完前面這個, 重新編譯以後再來檢視

3.

語法錯誤三

第 5 列少了分號, 編譯器繼續往下尋找分號, 看到第 6 列的 return 時, 就知道程式缺了分號了, 訊息寫 expected ';' before return 就還蠻精確的, 雖然 Dev-C++ 所使用的編譯器 gcc/g++ 的訊息都是英文, 但是通常都還蠻簡短的, 試著去熟悉它常用的字, 會讓你可以很快地修正程式的語法錯誤。

4.

語法錯誤四

編譯器在第 5 列最後找不到第二個雙引號 ", 於是告訴你程式有錯誤, 這也告訴你語法上每一個 字串 都要在同一列裡, 根據這個錯誤訊息, 你應該可以很快改過來, 可是你也許會有一個疑問? 如果我要打的訊息很長, 打在一列裡很難看, 可以分開多列打嗎? 基本上有三種方式可以完成:

1. 分成多次 printf 呼叫敘述

printf("Hello World!\n");
printf("Hello World!\n");

2. 在前一列最後用反斜線 \ 字元表示下一列繼續

printf("Hello World!\n\
Hello World!\n");

3. 編譯器自動將連續的多個 字串常數 合併

printf("Hello World!\n"
       "Hello World!\n");
測試一下吧!

5.

語法錯誤五

在第 5 列出現了 print 函式的呼叫, 但是這個函式並沒有定義在 stdio.h 引入標頭檔案裡面, 所以出現 `print' was not declared in this scope 的訊息, 請注意你在輸入程式的時候不要忽略了變數名稱以及函式名稱的『大寫與小寫字母是不同的』這件重要的事情, 否則大小寫一打錯, 通常就出現 `xxxx' was not declared 訊息。

另外編譯記錄窗格顯示的資訊是編譯器產生的原始訊息, 會包含編譯器訊息窗格顯示的資訊, 也還會出現更精確的位置指示, 就是下圖那個 ^ 符號指示的地點, print() 函式結束的地方就在它的右邊小括號, 編譯器告訴你看到這個地方它沒有辦法瞭解了...

6.

語法錯誤六

這是上面談到的變數大小寫打錯了

7.

連結錯誤

上面訊息裡面小小的字 ld 指的是『連結器』, 連結器的目的是由函式庫裡找到你所用到的工具函式 (例如 printf, system 等等), 讓你的程式能夠使用那些程式碼, 另外也要在你的程式裡找到 main 函式, 這個函式是 Windows 系統要執行你的程式時的進入點, 所以當連結器來尋找這個函數卻發現找不到的時候, 就給你這個 undefined reference 訊息。

程式設計課程 首頁

製作日期: 09/06/2012 by 丁培毅 (Pei-yih Ting)
E-mail: pyting@mail.ntou.edu.tw TEL: 02 24622192x6615
海洋大學 電機資訊學院 資訊工程學系 Lagoon