Pascal 轉 C++ 急救
用來急救,不多廢話。
藥方食用提示
本急救貼可以讓您充分了解以下內容(對應 C++ 語法快速提要):
- 基本語法(塊語句、註釋、導入庫、簡單輸入輸出、聲明變量、賦值……)
-
C++ 的 Hello World 與 A+B Problem 寫法與解釋
對應語法 部分較為緊湊,正式食用可能需要額外參考資料(已給出)。此部分不包括指針與 C 風格數組的介紹,也沒有結構體、運算符重載等等。
重要不同之處 部分為 C++ 的語法特點,也是 Pascal 轉 C++ 時會碰到的坑。
如要快速查找,請見附錄:
- 附 A:Pascal 與 C++ 運算符與數學函數語法對比表
- 附 B:文章檢索 - 按 C++ 語句語法索引
C++ 快速安裝與環境配置
注意:這裏假設使用的系統是 Windows。
方式一:使用 IDE
以下 IDE 選擇一個即可:
方式二:使用 代碼編輯器 + 編譯器 + 調試器
-
Visual Studio Code 官方網站上有文檔解釋如何進行 C++ 的配置。一般而言 VS Code 搭配插件使用更方便,見 VS Code 的官方網站。
C++ 語法快速提要 Start Here
C++ 程序都是從 main 這個部分開始運行的。
大括號表示塊語句的開始與結束: { 就相當於 Pascal 裏面的 begin ,而 } 就相當於 end 。
注意,和 Pascal 一樣,C++ 每句話結束要加分號 ; ,不過大括號結尾不需要有分號,而且程序結束末尾不用打句號 . 。
// 表示行內註釋, /* */ 表示塊註釋。
按照慣例,看看 Hello World 吧。
Hello World:第一個 C++ 程序
1 2 3 4 5 6 7 8 | |
然後編譯運行一下,看看結果。
簡要解釋
第一行, #include <iostream> 的意思是,導入 iostream 這個庫。
Pascal 的庫文件
Pascal 其實是有庫文件的,只不過,很多同學從來都沒有用過……
看到第三行的 main 嗎?程序從 main 開始執行。
接下來最重要的一句話是
1 | |
std::cout 是輸出( cout 即 C-out)的命令。你可能看過有些 C++ 程序中直接寫的是 cout 。
有關 std:: 前綴
有關 std:: 這個前綴的問題,請見 這節 底下的註釋「什麼是 std?」。
中間的 << 很形象地表示流動,其實它就是表示輸出怎麼「流動」的。這句代碼的意思就是, "Hello World!" 會先被推到輸出流,之後 std::endl 再被推到輸出流。
而 std::endl 是 輸出 換行( endl 即 end-line)命令,這與 Pascal 的 writeln 類似,不過 C++ 裏面可沒有 coutln 。Pascal 與 C++ 的區別在於, write('Hello World!') 等價於 std::cout << "Hello World!" ,而 writeln('Hello World!') 等價於 std::cout << "Hello World!" << std::endl 。
此處 "Hello World!" 是字符串,Pascal 中字符串都是用單引號 ' 不能用雙引號,而 C++ 的字符串必須用雙引號。C++ 中單引號包圍的字符會有別的含義,後面會再提及的。
好了,到這裏 Hello World 應該解釋的差不多了。
可能有同學會問,後面那個 return 0 是什麼意思?那個 int main() 是啥意思? 先別管它 ,一開始寫程序的時候先把它當作模板來寫吧(這裏也是用模板寫的)。因為入門時並不會用到 main 中參數,所以不需要寫成 int main(int argc, char const *argv[]) 。
簡單練習
- 試着換個字符串輸出。
- 試着瞭解轉義字符。
A+B Problem:第二個 C++ 程序
經典的 A+B Problem。
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
注:代碼空行較多,若不習慣可去掉空行。
簡要解釋
std::cin 是讀入( cin 即 C-in), >> 也與輸出語法的類似。
這裏多出來的語句中最重要的是兩個,一個是變量聲明語句
1 | |
你可能習慣於 Pascal 裏面的聲明變量
1 2 | |
C++ 的聲明是直接以數據類型名開頭的,在這裏, int (整型)開頭表示接下來要聲明變量。
接着一個最重要的語句就是賦值語句
1 | |
這是 Pascal 與 C++ 語法較大的不同, 這是個坑 :Pascal 是 := ,C++ 是 = ;而 C++ 判斷相等是 == 。
C++ 也可直接在聲明時進行變量初始化賦值
1 | |
簡單練習
- 重寫一遍代碼,提交到 OJ 上,並且 AC。
- 更多的輸入輸出語法參考 這節內容 ,並試着瞭解 C++ 的格式化輸出。
結束語與下一步
好了,到現在為止,你已經掌握了一些最基本的東西了,剩下就是找 Pascal 和 C++ 裏面對應的語法和不同的特徵。
不過在此之前,強烈建議先看 變量作用域:全局變量與局部變量 ,也可使用 附 B:文章檢索 查閲閲讀。
請善用Alt+←與Alt+→返回跳轉。
對應語法 Syntax
變量 Variable
基本數據類型 Fundamental types
C++ 與 Pascal 基本上差不多,常見的有
boolBoolean 類型int整型- 浮點型
floatdouble
char字符型void無類型
C++ 的單引號是專門用於表示單個字符的(字符型),比如 'a' ,而字符串(字符型數組)必須要用雙引號。
C++ 還要很多額外的數據類型,請參考更多資料。
擴展閲讀:
常量聲明 Constant
1 | |
若不清楚有關宏展開的問題,建議使用常量,而不用宏定義。
運算符 Operator
請直接參考
條件
if 語句
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 | |
布爾運算與比較
and->&&or->||not->!=->==<>->!=
註釋:
- Pascal 中
and與 C++ 中&&優先級不同,C++ 不需要給判斷條件加括號。 - Pascal 中判斷相等是
=,賦值是:=;C++ 中判斷相等是==,賦值是=。 - 如果在
if語句的括號內寫了a = b而不是a == b,程序不會報錯,而且會把b賦值給a,a = b這個語句的返回結果是true。 - C++ 不需要思考到底要不要在
end後面加分號。 - C++ 布爾運算中,非布爾值可以自動轉化為布爾值。
易錯提醒
特別注意: 不要把 == 寫成 = !
由於 C/C++ 比 Pascal 語法靈活,如果在判斷語句中寫了 if (a=b) { ,那麼程序會順利運行下去,因為 C++ 中 a=b 是有返回值的。
case 與 switch
用到得不多,此處不詳細展開。
需要注意:C++ 沒有 1..n ,也沒有連續不等式(比如 1 < x < 2 )。
循環 Loop
以下三種循環、六份代碼實現的功能是一樣的。
while 循環
while 很相似。(C++ 此處並非完整程序,省略一些框架模板,後同)
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 5 | |
for 循環
C++ 的 for 語句非常不同。
1 2 3 4 5 6 7 8 | |
1 2 3 | |
註釋:
for (int i = 1; i <= 10; i++){這一行語句很多,for中有三個語句。- 第一個語句
int i = 1;此時聲明一局部變量i並初始化。(這個設計比 Pascal 要合理得多。) - 第二個語句
i <= 10;作為判斷循環是否繼續的標準。 - 第三個語句
i++,在每次循環結尾執行,意思大約就是 Pascal 中的inc(i),此處寫成++i也是一樣的。i++與++i的區別請參考其他資料。
repeat until 與 do while 循環
注意, repeat until 與 do while 是不同的,請對比以下代碼
1 2 3 4 5 6 7 8 9 | |
1 2 3 4 5 | |
循環控制 Loop Control
C++ 中 break 的作用與 Pascal 是一樣的,退出循環。
而 continue 也是一樣的,跳過當前循環,進入下一次循環(回到開頭)。
數組與字符串 Array and String
不定長數組:標準庫類型 Vector
C++ 標準庫中提供了 vector ,相當於不定長數組,調用前需導入庫文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
C++ 訪問數組成員,與 Pascal 類似,不過有很重要的區別:數組的第一項是 a[0] ,而 Pascal 中是可以自行指定的。
擴展閲讀:
字符串:標準庫類型 String
C++ 標準庫中提供了 string ,與 vector 可以進行的操作有些相同,同樣需要導入庫文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
擴展閲讀:
C 風格數組 Array
如果要用不定長的數組請用 Vector,不要用 C 風格的數組。
C 風格的數組與指針有密切關係,所以此處不多展開。
擴展閲讀:
重要不同之處 Differences
變量作用域 Scope:全局變量與局部變量
C++ 幾乎可以在 任何地方 聲明變量。
以下對於 C++ 的變量作用域的介紹摘自 變量作用域 - OI Wiki :
作用域是變量可以發揮作用的代碼塊。
變量分為全局變量和局部變量。在所有函數外部聲明的變量,稱為全局變量。在函數或一個代碼塊內部聲明的變量,稱為局部變量。
全局變量的作用域是整個文件,全局變量一旦聲明,在整個程序中都是可用的。
局部變量的作用域是聲明語句所在的代碼塊,局部變量只能被函數內部或者代碼塊內部的語句使用。
由一對大括號括起來的若干語句構成一個代碼塊。
1 2 3 4 5 6int g = 20; // 聲明全局變量 int main() { int g = 10; // 聲明局部變量 printf("%d\n", g); // 輸出 g return 0; }在一個代碼塊中,局部變量會覆蓋掉同名的全局變量,比如上面的代碼輸出的
g就是10而不是20。為了防止出現意料之外的錯誤,請儘量避免局部變量與全局變量重名的情況。
在寫 Pascal 過程/函數時,容易忘記聲明局部變量 i 或者 j ,而一般主程序裏會有循環,於是大部分情況下 i 與 j 都是全局變量,於是,在這種情況下,過程/函數中對 i 操作極易出錯。更要命的是,如果忘記聲明這種局部變量,編譯器編譯不報錯,程序可以運行。(有很多難找的 bug 就是這麼來的。)
所以,在使用 C++ 時,聲明變量,比如循環中使用的 i , 不要用全局變量,能用局部變量就用局部變量 。如果這麼做,不用擔心函數中變量名(比如 i )衝突。
額外注
Pascal 可在某種程度上避免這個問題,仿照 C++ 的方法,主程序只有調用過程/函數,不聲明 i j 這類極易名稱衝突的全局變量,如果需要循環,另寫一個過程進行調用。
C++ 可以自動轉換類型
1 2 3 4 5 6 | |
不光是 int 轉成 bool ,還有 int 與 float 相互轉換。在 Pascal 中可以把整型賦給浮點型,但不能反過來。C++ 沒有這個問題。
1 2 3 | |
區分 / 是整除還是浮點除法,是通過除數與被除數的類型判斷的
1 2 | |
pow(a, b) 計算 \(a^b\) ,該函數返回的是浮點型,如果直接用來計算整數的冪,由於有自動轉換,不需要擔心它會報錯
1 | |
還有 char 與 int 之間相互轉換。
1 2 3 | |
其實 C++ 中的 char 與 bool 本質上是整型。
擴展閲讀:
- 隱式轉換 - cppreference.com 注意內容可能過於專業
C++ 很多語句有返回值:以如何實現讀取數量不定數據為例
有些時候需要讀取到數據結束,比如,求一組不定數量的數之和(數據可以多行),直到文件末尾,實現方式是
文件末尾 EOF
EOF,文件末尾標識符,在命令行中 Windows 上以Ctrl+Z輸入(還需按Enter),*unix 系統以Ctrl+D輸入。
1 2 3 4 5 6 7 8 9 10 11 12 | |
實現原理: while (std::cin >> a) 中 std::cin >> a 若在輸入有問題或遇到文件結尾時,會返回 false,使得循環中斷。
函數 Function:C++ 只有函數沒有過程但有 void ,沒有函數值變量但有 return 。
Pascal 函數與 C++ 函數對比示例:
1 2 3 4 5 6 7 8 9 10 11 | |
1 2 3 4 5 6 7 | |
C++ 中函數聲明 int abs ,就定義了 abs() 函數且返回值為 int 型(整型),函數的返回值就是 return 語句給出的值。
如果不想有返回值(即 Pascal 的「過程」),就用 void 。 void 即「空」,什麼都不返回。
1 2 3 4 5 6 7 8 9 10 11 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
C++ 的 return 與 Pascal 中給函數變量賦值有一點非常大的不同。C++ 的 return 即返回一個值,執行完這個語句,函數就執行結束了;而 Pascal 中給函數變量賦值並不會跳出函數本身,而是繼續執行。於是,如果 Pascal 需要某處中斷函數/過程,就需要一個額外的命令,即 exit 。而 C++ 則不需要,如果需要在某處中斷,可以直接使用 return 。比如(由於實在想不出來簡短且實用的代碼,所以就先這樣)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
而在某種意義上,前面的 abs 函數,這樣才是嚴格等效的
1 2 3 4 5 6 7 8 9 10 11 | |
1 2 3 4 5 6 7 | |
特別提醒
C++ 中 exit 是退出程序;不要順手把 exit 打上去,要用 return !
C++ 把函數和過程統統視作函數,連 main 都不放過,比如寫 int main ,C++ 視 main 為一個整型的函數,這裏返回值是 0 。它是一種習慣約定,返回 0 代表程序正常退出。
也許你已經猜到了, main(int argc, char const *argv[]) 中的參數就是 int argc 與 char const *argv[] ,不過意義請參考其他資料。
在函數中傳遞參數 Passing Parameters to Functions
C++ 中沒有 Pascal 的 var 關鍵字可以改變傳遞的參數,但是 C++ 可以使用引用和指針達到同樣的效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
注意,此處 C++ 代碼 涉及指針問題 。指針問題還是很麻煩的,建議去閲讀相關資料。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
注意,此處 C++ 代碼涉及 引用相關類型問題 。在用引用調用一些 STL 庫、模板庫的時候可能會遇到一些問題,這時候需要手動聲明別類型。具體資料可以在《C++ Primer》第五版或者網絡資料中自行查閲。
C++ 中函數傳遞參數還有其他方法,其中一種是 直接使用全局變量傳遞參數 ,如果不會用指針,可以先用這種方法。但是這種方法的缺陷是沒有棧保存數據, 沒有辦法在遞歸函數中傳參 。(除非手寫棧,注意,手寫棧也是一種突破系統棧限制的方法。)
C++ 標準庫與參考資料 Reference
千萬不要重複造輪子(除非為了練習),想要自己動手寫一個功能出來之前,先去看看有沒有這個函數或者數據結構。
C++ 標準庫
C++ 標準庫中 <algorithm> 有很多有用的函數比如快排、二分查找等,可以直接調用。請參考這個頁面: STL 算法 - OI Wiki 。
還有 STL 容器,比如數組、向量(可變大小的數組)、隊列、棧等,附帶很多函數。請參考這個頁面: STL 容器簡介 - OI Wiki 。
如果要找關於字符串操作的函數見
C/C++ 的指針是很靈活的東西,如果想要徹底理解指針,建議找本書或者參考手冊仔細閲讀。
錯誤排查與技巧
C++ 語言資料
- 學習資源 - OI Wiki
- cppreference.com - 最重要的 C/C++ 參考資料
- C++ 教程 - 菜鳥教程
- C++ Language - C++ Tutorials
- Reference - C++ Reference
- C++ Standard Library - Wikipedia
- The Ultimate Question of Programming, Refactoring, and Everything
- Google C++ Style Guide
後記
寫到這裏,很多同學會覺得這一點都不急救啊,有很多東西沒有提到啊。那也是沒辦法的事情。
雖然是為了急救,但很多東西像怎麼把字符串轉化為數字,怎麼搜索字符串中的字符,這些東西也不適合一篇精悍短小的急救帖,如果把這些都寫出來,那就是 C++ 入門教程,所以請充分利用本 Wiki、參考手冊與搜索引擎。
需要指出的一點是,上面説 C++ 的語法,其實有很多語法是從 C 語言來的,標題這麼寫比較好——《Pascal 轉 C/C++ 急救帖》。
Pascal 在上個世紀後半葉是門很流行的語言,它早於 C 語言,不過隨着 UNIX 系統的普及,微軟使用 C 語言,現在 Pascal 已經成為歷史了。Pascal 後期發展也是有的,比如 Free Pascal 這個開源編譯器項目,增加面向對象的特性(Delphi 語言)。Pascal 目前的用處除了在信息競賽外,有一個特點是其他語言沒有的——編譯支持非常非常多老舊機器,比如 Gameboy 這種上個世紀的任天堂遊戲機,還有一個用處就是以偽代碼的形式(Pascal 風格的偽代碼)出現在各種教科書中。
最後,Pascal 的圈子其實很小,C/C++ 的圈子很大,幫助手冊與教程很多很全,一定要掌握好英語。世界上還有很多很多編程語言,而計算機這門學科與技術不光是信息競賽和編程語言。
本文 Pascal 語言的參考文獻
附 A:Pascal 與 C++ 運算符與數學函數語法對比表 Pascal vs C++ Operator Syntax Table
僅包括最常用的運算符與函數。
基本算術
| Pascal | C++ | |
|---|---|---|
| 加法 | a + b |
a + b |
| 減法 | a - b |
a - b |
| 乘法 | a * b |
a * b |
| 整除 | a div b |
a / b |
| 浮點除法 | a / b |
a / b |
| 取模 | a mod b |
a % b |
邏輯
| Pascal | C++ | |
|---|---|---|
| 非 | not(a) |
!a |
| 且 | a and b |
a && b |
| 或 | a or b |
a || b |
比較
| Pascal | C++ | |
|---|---|---|
| 相等 | a = b |
a == b |
| 不等 | a <> b |
a != b |
| 大於 | a > b |
a > b |
| 小於 | a < b |
a < b |
| 大於等於 | a >= b |
a >= b |
| 小於等於 | a <= b |
a <= b |
賦值
| Pascal | C++ | |
|---|---|---|
a := b |
a = b |
|
a := a + b |
a += b |
|
a := a - b |
a -= b |
|
a := a * b |
a *= b |
|
a := a div b 或 a := a / b |
a /= b |
|
a := a mod b |
a %= b |
自增/自減
| Pascal | C++ | |
|---|---|---|
| 自增 | inc(a) |
a++ |
| 自增 | inc(a) |
++a |
| 自減 | dec(a) |
a-- |
| 自減 | dec(a) |
--a |
數學函數
使用需要導入
<cmath>庫。
| Pascal | C++ | |
|---|---|---|
| 絕對值 | abs(a) |
abs(a) (整數) |
| 絕對值 | abs(a) |
fabs(a) (浮點數) |
| \(a^b\) | N/A (*) | pow(a, b) |
| 截斷取整 | trunc(a) |
trunc(a) |
| 近似取整 | round(a) |
round(a) |
*Extended Pascal 中有 a**b 不過需要導入 Math 庫。
其他函數請參考:
附 B:文章檢索 Index
按 C++ 語句語法索引。
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:kexplorning, Ir1d, lvneg1
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用