C++ 語法基礎
代碼框架
如果你不想深究背後的原理,初學時可以直接將這個「框架」背下來:
1 2 3 4 5 6 7 | |
什麼是 include?
#include 其實是一個預處理命令,意思為將一個文件「放」在這條語句處,被「放」的文件被稱為頭文件。也就是説,在編譯時,編譯器會「複製」頭文件 iostream 中的內容,「粘貼」到 #include <iostream> 這條語句處。這樣,你就可以使用 iostream 中提供的 std::cin、std::cout、std::endl 等對象了。
如果你學過 C 語言,你會發現目前我們接觸的 C++ 中的頭文件一般都不帶 .h 後綴,而那些 C 語言中的頭文件 xx.h 都變成了 cxx,如 stdio.h 變成了 cstdio。因為 C++ 為了和 C 保持兼容,都直接使用了 C 語言中的頭文件,為了區分 C++ 的頭文件和 C 的頭文件,使用了 c 前綴。
一般來説,應當根據你需要編寫的 C++ 程序的需要來確定你要 #include 哪些頭文件。但如果你 #include 了多餘的頭文件,只會增加編譯時間,幾乎不會對運行時間造成影響。目前我們只接觸到了 iostream 和 cstdio 兩個頭文件,如果你只需要 scanf 和 printf,就可以不用 #include <iostream>。
可以 #include 自己寫的頭文件嗎?答案是,可以。
你可以自己寫一個頭文件,如:myheader.h。然後,將其放到和你的代碼相同的目錄裏,再 #include "myheader.h" 即可。需要注意的是,自定義的頭文件需要使用引號而非尖括號。當然,你也可以使用編譯命令 -I <header_file_path> 來告訴編譯器在哪找頭文件,就不需要將頭文件放到和代碼相同的目錄裏了。
什麼是 main()?
可以理解為程序運行時就會執行 main() 中的代碼。
實際上,main 函數是由系統或外部程序調用的。如,你在命令行中調用了你的程序,也就是調用了你程序中的 main 函數(在此之前先完成了全局 變量 的構造)。
最後的 return 0; 表示程序運行成功。默認情況下,程序結束時返回 0 表示一切正常,否則返回值表示錯誤代碼(在 Windows 下這個錯誤代碼的十六進制可以通過 Windows Error Codes 網站 進行查詢)。這個值返回給誰呢?其實就是調用你寫的程序的系統或外部程序,它會在你的程序結束時接收到這個返回值。如果不寫 return 語句的話,程序正常結束默認返回值也是 0。
在 C 或 C++ 中,程序的返回值不為 0 會導致運行時錯誤(RE)。
註釋
在 C++ 代碼中,註釋有兩種寫法:
-
行內註釋
以
//開頭,行內位於其後的內容全部為註釋。 -
註釋塊
以
/*開頭,*/結尾,中間的內容全部為註釋,可以跨行。
註釋對程序運行沒有影響,可以用來解釋程序的意思,還可以在讓某段代碼不執行(但是依然保留在源文件裏)。
在工程開發中,註釋可以便於日後維護、他人閲讀。
在 OI 中,很少有人寫許多註釋,但註釋可以便於在寫代碼的時候理清思路,或者便於日後複習。而且,如果要寫題解、教程的話,適量的註釋可以便於讀者閲讀,理解代碼的意圖。希望各位同學能養成寫註釋的好習慣。
輸入與輸出
cin 與 cout
1 2 3 4 5 6 7 8 | |
什麼是變量?
可以參考 變量 頁面。
scanf 與 printf
scanf 與 printf 其實是 C 語言提供的函數。大多數情況下,它們的速度比 cin 和 cout 更快,並且能夠方便地控制輸入輸出格式。
讀入輸出優化
cin/cout 和 scanf/prinf 的具體差別和讀入輸出優化,請參考 讀入、輸出優化 頁面。
1 2 3 4 5 6 7 8 | |
其中,%d 表示讀入/輸出的變量是一個有符號整型(int 型)的變量。
類似地:
%s表示字符串。%c表示字符。%lf表示雙精度浮點數 (double)。%lld表示長整型 (long long)。根據系統不同,也可能是%I64d。%u表示無符號整型 (unsigned int)。%llu表示無符號長整型 (unsigned long long),也可能是%I64u。
除了類型標識符以外,還有一些控制格式的方式。許多都不常用,選取兩個常用的列舉如下:
%1d表示長度為 1 的整型。在讀入時,即使沒有空格也可以逐位讀入數字。在輸出時,若指定的長度大於數字的位數,就會在數字前用空格填充。若指定的長度小於數字的位數,就沒有效果。%.6lf,用於輸出,保留六位小數。
這兩種運算符的相應地方都可以填入其他數字,例如 %.3lf 表示保留三位小數。
「雙精度浮點數」,「長整型」是什麼
這些表示變量的類型。和上面一樣,會留到 變量 中統一講解。
為什麼 scanf 中有 & 運算符?
在這裏,& 實際上是取址運算符,返回的是變量在內存中的地址。而 scanf 接收的參數就是變量的地址。具體可能要在 指針 才能完全清楚地説明,現在只需要記下來就好了。
什麼是 \n?
\n 是一種 轉義字符,表示換行。
轉義字符用來表示一些無法直接輸入的字符,如由於字符串字面量中無法換行而無法直接輸入的換行符,由於有特殊含義而無法輸入的引號,由於表示轉義字符而無法輸入的反斜槓。
常用的轉義字符有:
\t表示製表符。\\表示\。\"表示"。\0表示空字符,用來表示 C 風格字符串的結尾。\r表示回車。Linux 中換行符為\n,Windows 中換行符為\r\n。在 OI 中,如果輸出需要換行,使用\n即可。但讀入時,如果使用逐字符讀入,可能會由於換行符造成一些問題,需要注意。例如,gets將\n作為字符串結尾,這時候如果換行符是\r\n,\r就會留在字符串結尾。- 特殊地,
%%表示%,只能用在printf或scanf中,在其他字符串字面量中只需要簡單使用%就好了。
什麼是字面量?
「字面量」是在代碼裏直接作為一個值的程序段,例如 3 就是一個 int 字面量,'c' 就是一個 char 字面量。我們上面寫的程序中的 "hello world" 也是一個字符串字面量。
不加解釋、毫無來由的字面量又被稱為「魔術數」(magic number),如果代碼需要被人閲讀的話,這是一種十分不被推薦的行為。
一些擴展內容
C++ 中的空白字符
在 C++ 中,所有空白字符(空格、製表符、換行),多個或是單個,都被視作是一樣的。(當然,引號中視作字符串的一部分的不算。)
因此,你可以自由地使用任何代碼風格(除了行內註釋、字符串字面量與預處理命令必須在單行內),例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
當然,這麼做是不被推薦的。
一種也被廣泛使用但與 OI Wiki 要求的碼風不同的代碼風格:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
#define 命令
#define 是一種預處理命令,用於定義宏,本質上是文本替換。例如:
1 2 3 4 5 6 7 8 9 10 | |
什麼是標識符?
標識符就是可以用作變量名的一組字符。例如,abcd 和 abc1 都是合法的標識符,而 1a 和 c+b 都不是合法的標識符。
標識符由英文字母、下劃線開頭,中間只允許出現英文字母、下劃線和數字。值得注意的是,關鍵字(如 int,for,if)不能用作標識符。
什麼是預處理命令?
預處理命令就是預處理器所接受的命令,用於對代碼進行初步的文本變換,比如 文件包含操作 #include 和 處理宏 #define 等,對 GCC 而言,默認不會保留預處理階段的輸出 .i 文件。可以用 -E 選項保留輸出文件。
宏可以帶參數,帶參數的宏可以像函數一樣使用:
1 2 3 4 5 6 7 | |
但是帶參數的宏和函數有區別。因為宏是文本替換,所以會引發許多問題。如:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
使用 #define 是有風險的(由於 #define 作用域是整個程序,因此可能導致文本被意外地替換,需要使用 #undef 及時取消定義),因此應謹慎使用。較為推薦的做法是:使用 const 限定符聲明常量,使用函數代替宏。
但是,在 OI 中,#define 依然有用武之處(以下兩種是不被推薦的用法,會降低代碼的規範性):
#define int long long+signed main()。通常用於避免忘記開 long long 導致的錯誤,或是調試時排除忘開 long long 導致錯誤的可能性。(也可能導致增大常數甚至 TLE,或者因為爆空間而 MLE)#define For(i, l, r) for (int i = (l); i <= (r); ++i)、#define pb push_back、#define mid ((l + r) / 2),用於減短代碼長度。
不過,#define 也有優點,比如結合 #ifdef 等預處理指令有奇效,比如:
1 2 3 4 5 | |
可以在編譯的時候通過 -DLINUX 來控制編譯出的代碼,而無需修改源文件。這還有一個優點:通過 -DLINUX 編譯出的可執行文件裏並沒有其他操作系統的代碼,那些代碼在預處理的時候就已經被刪除了。
#define 還能使用 #、## 運算符,極大地方便調試。
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:OI-wiki
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用