2023年5月31日 星期三

C/C++ 學習筆記 : 基本語法

今天繼續整理 C& C++ 的基本語法筆記. 本系列之前的文章參考 :


C++ 是 C 語言的延伸, 基本語法幾乎完全一樣, 可參考以前學 Arduino 時整理的筆記 :


本篇參考書籍如下 : 
  1. 快速學會 C++ 語言 (洪志維, 易習 2014)
  2. 第一次學 C++ 就上手第二版 (李啟龍, 碁峰 2017) 
  3. C++ 教學手冊第三版 (旗標 2012)


一. 程式基本架構 :

C 程式的基本架構從上至下依序分為下面四個區塊 : 
  1. 前置指令 : 主要是匯入函式庫標頭檔與定義常數等.
  2. 自訂函式之原型宣告 : 定義於主函式 main() 後面的其他函式都必須先做原型宣告. 
  3. main() 主函式 : 一個程式中只能有一個名稱為 main() 的主函式, 為程式執行入口. 
  4. 自訂函式 : 於 main() 中會呼叫的自訂函式.
C & C++ 程式的每個敘述結尾都必須以分號結束, 但下面兩個結尾不可用分號 :
  • 前置指令如 #include 或 #define 等.
  • 函式的結尾大括號.
其次, 如果函式定義於 main() 前面則不需要原型宣告. 

C 程式的基本範例如下 :

#include <stdio.h>
#include <stdlib.h>

int main() {
   printf("Hello, world!");    //在螢幕顯示字串
   system("PAUSE");           //暫停程式執行, 按 ENTER 繼續
   return 0;                            //傳回 0 表示程式正常結束
   }

C++ 程式的基本架構從上至下依序分為下面五個區塊 : 
  1. 前置指令 : 主要是匯入函式庫標頭檔與定義常數等.
  2. 自訂函式之原型宣告 : 定義於主函式 main() 後面的其他函式都必須先做原型宣告. 
  3. 命名空間宣告 : 可簡化函式的調用方式, 例如宣告標準函式庫 using namespace std. 
  4. main() 主函式 : 一個程式中只能有一個名稱為 main() 的主函式, 為程式執行入口. 
  5. 自訂函式 : 於 main() 中會呼叫的函式.
C++ 主要是多了一個可有可無的命名空間宣告, 基本範例如下 :

#include <iostream>
#include <cstdlib>

using namespace std;    //宣告命名空間 std (標準函式庫)
int main() {
  cout << "Hello, world!" << endl;    //在螢幕顯示字串
  return 0;                                           //傳回 0 表示程式正常結束
  }

由於 C++ 的標準輸出入函式定義在命名空間 std 下的 iostream 函式庫裡, 如果沒有用 using namspace 宣告命名空間, 則標準輸出必須把命名空間寫出來, 例如 std::cout 與 std::end1.


二. 標頭檔 :

C 與 C++ 遵循模組化設計精神, 提供了許多標準函式庫, C 語言函式庫的函式原型宣告都放在副檔名為 .h 的標頭檔 (header file), 只要在程式最前面用前置指令 #include 匯入這些標頭檔, 即可於程式中呼叫這些標準函式庫中的函式. 匯入函式庫標頭檔的語法如下 :

#include <標頭檔名稱.h>   

注意, 前置指令結尾不可加分號

C 語言最常用的標準函式庫標頭檔為 stdio.h 與 stdlib.h, 例如標準輸出入常用的 printf() 與 scanf() 函式的原型宣告放在 stdio.h 標頭檔內; 而呼叫作業系統的函式 system() 原型宣告與記憶體配置函式等則是放在 stdlib.h 標頭檔內,  故 C 程式的開頭通常都需要匯入這兩個標頭檔 :

#include <stdio.h>
#include <stdio.h>

常用的 C 語言標頭檔如下表 :

 常用的 C 語言標頭檔 說明
 stdio.h 標準輸出入 (螢幕與鍵盤) 函式原型宣告, 例如 printf(), scanf()
 stdlib.h 各種基本函式的標準函式庫, 例如 system()
 string.h 字串處理函式的原型宣告, 例如 strcpy()
 time.h 日期時間函式的原型宣告, 
 math.h 數學運算函式的原型宣告, 例如 sqrt()

C++ 最常用的標準函式庫標頭檔為 iostream 與 cstdlib (注意, 沒有 .h), 它們分別包含了 C 語言的 stdio.h 與 stdlib.h 標頭檔, 並且新增到 std 命名空間中 (因此不需要 .h). 除了這兩個函式庫在 C++ 中用法不同外, 其他函式庫例如 string, time 與 math 在 C++ 中用法與 C 程式完全相同.  


三. 註解 :

C 語言的註解必須放在 /* 與 */ 之間, 它原本是只能單行註解, 但 C++ 將其擴充為可單行也可以多行, 例如 :

/*  printf("這是單行註解");  */    
/* int i;
    for(i=0; i<5; i++) {
       printf("這是多行註解");
       }   */

C++ 另外新稱只能用於單行的 // 的註解方式, 例如 :

// printf("這是單行註解");

如果要用 // 註解一個區塊的程式碼, 則每一行都要用 // 註解掉 : 

// int i;
// for(i=0; i<5; i++) {
     //printf("這是多行註解");
     //}   

由於 C++ 編譯器都向下相容 C 語法, 因此這兩種註解方式都可以同時使用, 例如 : 

// printf("這是單行註解");
/* int i;
    for(i=0; i<5; i++) {
       printf("這是多行註解");
       }   */

亦即單行可使用 // 或 /* */, 而多行則使用 /* */.  但建議盡量都使用 C++ 的 // 來註解, 因為 /* */ 在註解中又有註解時會提前結束註解區域而導致編譯失敗, 例如 : 

/* int i;
    for(i=0; i<5; i++) {    /* 印五次的迴圈 */   
       printf("這是多行註解");
       }   */

上述程式碼在 for 迴圈那一行後面有 /* */ 註解, 由於中間的 */ 會被視為註解結束, 後面的程式碼脫離註解範圍而導致編譯失敗, 如果全部用 // 註解就無此問題, 例如 : 

// int i;
    //for(i=0; i<5; i++) {    // 印五次的迴圈
       //printf("這是多行註解");
       //}   


四. 變數, 常數, 與資料型態 :

變數與常數是程式儲存在記憶體中準備用來運算的資料, 變數的值在程式中可用指派運算子 = 更改, 而常數則不可更改. 


1. 資料型態 :

C & C++ 為強型態 (strong-typed) 的語言, 每一個變數都必須指定資料型別以便編譯器為其配置於記憶體空間. C 語言內建的基本資料型別有 4 種 (C 沒有字串型別, 字串使用以空字元 '\0' 結尾的字元陣列儲存) :
  • 字元 : char (1 byte), 必須用單引號括起來. 
  • 整數 : int (4 bytes)
  • 浮點數 : float (4 bytes) 與 double (8 bytes)
C++ 又新增了兩種基本型態 : 
  • 布林 : bool (1 byte), 只有 true(=1) 與 false(=0) 兩個值.
  • 無傳回值 : void, 用於宣告函式無傳回值. 
整數 int 前面可以用下列 4 個修飾詞 :
  • long : 與 int 相同為 4 bytes 整數.
  • short : 2 bytes 整數. 
  • signed : 有正數與負數. 
  • unsigned : 僅正數. 
其中 signed 與 unsigned 也用來修飾 char 類型. 如果整數變數均為正數, 則可宣告為 unsigned short 或 unsigned int.

字元資料必須用單引號括起來, 例如 'a' 與 'A' (單引號裡面只能放一個字元), 以一個 byte 的 ASCII 編碼 (0~127 的整數) 儲存, 例如 'A' 是以 65 這個整數儲存. 另外還有稱為脫逸字元的特殊字元, 常用的脫逸字元如下 (均占用 1 byte 的記憶體) : 
  • \0 : 空字元=NULL (用來標示字串的結束)
  • \n : 換行字元
  • \r : 回車字元
  • \t : 定位點字元
  • \\ : 倒斜線 \
  • \? : 問號 ?
  • \' : 單引號 '
  • \" : 雙引號


2. 變數與識別字 :

變數可以先宣告再賦值, 語法如下 : 

資料型態 識別字;    
識別字=值;    

int a;           // 先宣告
a=100;        // 再賦值

或者宣告同時賦值 :

資料型態 識別字=值;

例如 :

int a=100;     // 宣告同時賦值

可以同時宣告多個相同型別的變數, 各變數識別字以逗號隔開, 語法如下 : 

資料型態 識別字1, 識別字2, 識別字3, .... ; 

例如 :

int a, b, c;
int a=1, b=2, c=3; 

指定資料型態的目的是要讓編譯器為此變數配置所需的記憶體空間. 

識別字命名的規則如下 :
  • 字母有分大小寫, user 與 User 是不同的識別字. 
  • 只能使用英文字母, 數字, 與底線之組合, 但不可以用數字開頭.
  • 不可使用關鍵字或與內建函式同名
  • 長度不可超過 127 個字元.
注意, 這些命名規則不僅適用於變數名稱, 也適用於常數名稱, 函式名稱; 也適用於 C++ 中的物件與類別名稱.  

關鍵字是語言本身的保留字, 不可用作識別字.  C 的關鍵字如下表 : 


 auto break case char const
 continue default do double else
 enum extern float for goto
 if int long register return
 short signed sizeof static struct
 switch typedef union unsigned void
 volatile while   


C++ 又補充了如下關鍵字 : 


 bool catch explicit namespace delete
 dynamic_cast mutable protected friend class
 inline private template new operator
 static_cast try public reinterpret_case true
 virtual this throw typeid false
 type_name const_cast wchar_t asm using


3. 常數 :

常數的宣告有兩種方法 :
  • 使用前置指令 #define :
    語法 : #define 識別字 常數值  
    例如 : #define PI 3.14159
  • 使用 const 關鍵字 :
    語法 : const 資料型態 識別字=常數值;      
    例如 : const double PI=3.14159
注意 : 
  • 常數的識別字命名規則與變數一樣, 但習慣上全部使用大寫字母 (非強制). 
  • 使用前置指令時不需要指定資料型態 , 結尾也不可家分號; 而使用 const 時則要指定資料型態, 結尾必須用分號. 
  • 常數值若是字元要用單引號括起來; 若是字串則要用雙引號括起來.
C & C++ 中的字串常數以字元陣列 + '\0' 儲存, 故字串會比一般字元串列長度多出 1 個 byte, 字串常數以雙引號括起來, 例如 "A" 是字串, 長度為 2 個 byte; 而 'A' 則是字元, 長度為 1 個 byte. 

C++ 新增了 bool 布林型態, 其值只有 true 與 false, 等同於整數的 1 與 0.  

沒有留言 :