OSDN Git Service

Merge pull request #2148 from lvneg1/patch-1
[oi-wiki/main.git] / docs / lang / pas-cpp.md
index 616203f..5496c96 100644 (file)
@@ -2,6 +2,42 @@ author: kexplorning, Ir1d, lvneg1
 
 > 用来急救,不多废话。
 
+???+note "药方食用提示"
+    本急救贴可以让您充分了解以下内容(对应 [C++ 语法快速提要](#c-start-here) ):
+    
+    - 基本语法(块语句、注释、导入库、简单输入输出、声明变量、赋值……)
+    -   C++ 的 Hello World 与 A+B Problem 写法与解释
+    
+         [对应语法](#syntax) 部分较为紧凑,正式食用可能需要额外参考资料(已给出)。此部分不包括指针与 C 风格数组的介绍,也没有结构体、运算符重载等等。
+    
+         [重要不同之处](#differences) 部分为 C++ 的语法特点,也是 Pascal 转 C++ 时会碰到的坑。
+    
+    如要快速查找,请见附录:
+    
+    -  [附 A:Pascal 与 C++ 运算符与数学函数语法对比表](#apascal-c-pascal-vs-c-operator-syntax-table) 
+    -  [附 B:文章检索](#b-index) - 按 C++ 语句语法索引
+
+<!-- 
+
+INFO: 恭喜你找到了隐藏彩蛋!
+
+> !!⚠️ **警告** ⚠️!!
+> 
+> ~~☠ **有毒物品警告**~~  ~~☣️ **腐化身心警告**~~
+> 
+> ~~此药方仅适用于 Pascal 中毒症状早期;若您是晚期,本药方不能使您快速康复(不能让您理解指针),请节哀顺变(顺其自然),或遵循本 Wiki 其他页面等医嘱,或删除技能树重练。~~
+> 
+> ~~本药方治疗机理为**以毒攻毒**,故副作用是 C++ 中毒症状,请服用此方前再三确认。本药方贡献者与本 Wiki 不承担您使用发生意外时的任何责任。~~
+> 
+> 欢迎对本药方进行小白鼠测试(可在初具规模之后,使用猿类进行实验),也非常欢迎通过发评论、发 issue、提交 PR 进行实验结果反馈与药方改进。
+> ~~若您想要特效药,本 Wiki 有[一剂](./python):~~
+> 
+> > 人生苦短,我用 Python。
+> 
+> 可以让您超脱世间,驾鹤西去,再也不用因 OI 而困扰。 
+
+-->
+
 ## C++ 快速安装与环境配置
 
 > 注意:这里假设使用的系统是 Windows。
@@ -10,9 +46,9 @@ author: kexplorning, Ir1d, lvneg1
 
 以下 IDE 选择一个即可:
 
--    [Dev-C++](https://sourceforge.net/projects/orwelldevcpp/
--    [Code::Blocks](https://sourceforge.net/projects/codeblocks/) 
--    [Visual Studio](https://visualstudio.microsoft.com/) (Community 版本够用)
+-  [Dev-C++](../tools/editor/devcpp.md
+-  [Code::Blocks](https://sourceforge.net/projects/codeblocks/) 
+-  [VS Code](../tools/editor/vscode.md) 
 
 ### 方式二:使用 代码编辑器 + 编译器 + 调试器
 
@@ -35,7 +71,7 @@ C++ 程序都是从 `main` 这个部分开始运行的。
 ```cpp
 #include <iostream>  // 导入 iostream 库
 
-int main(int argc, char const *argv[])  // main 部分
+int main()  // main 部分
 {
   std::cout << "Hello World!" << std::endl;
 
@@ -73,12 +109,12 @@ std::cout << "Hello World!" << std::endl;
 
 好了,到这里 Hello World 应该解释的差不多了。
 
-可能有同学会问,后面那个 `return 0` 是什么意思?那个 `int main(int argc, char const *argv[])` 是啥意思? **先别管它** ,一开始写程序的时候先把它当作模板来写吧(这里也是用模板写的)。不过,入门时并不会用到 `main` 中参数,所以写成 `int main()` 也是没有关系的
+可能有同学会问,后面那个 `return 0` 是什么意思?那个 `int main()` 是啥意思? **先别管它** ,一开始写程序的时候先把它当作模板来写吧(这里也是用模板写的)。因为入门时并不会用到 `main` 中参数,所以不需要写成 `int main(int argc, char const *argv[])` 
 
 #### 简单练习
 
-1.  试着换个字符串输出。
-2.  试着了解转义字符。
+1. 试着换个字符串输出。
+2. 试着了解转义字符。
 
 ### A+B Problem:第二个 C++ 程序
 
@@ -87,7 +123,7 @@ std::cout << "Hello World!" << std::endl;
 ```cpp
 #include <iostream>
 
-int main(int argc, char const *argv[]) {
+int main() {
   int a, b, c;
 
   std::cin >> a >> b;
@@ -137,8 +173,8 @@ int a = 0, b = 0, c = 0;
 
 #### 简单练习
 
-1.  重写一遍代码,提交到 OJ 上,并且 AC。
-2.  更多的输入输出语法参考 [这节内容](../basic/#scanf-printf) ,并试着了解 C++ 的格式化输出。
+1. 重写一遍代码,提交到 OJ 上,并且 AC。
+2. 更多的输入输出语法参考 [这节内容](../basic/#scanf-printf) ,并试着了解 C++ 的格式化输出。
 
 ### 结束语与下一步
 
@@ -148,7 +184,7 @@ int a = 0, b = 0, c = 0;
 
 请善用<kbd>Alt</kbd>+<kbd>←</kbd>与<kbd>Alt</kbd>+<kbd>→</kbd>返回跳转。
 
-## 对应语法
+## 对应语法 Syntax
 
 ### 变量 Variable
 
@@ -156,13 +192,13 @@ int a = 0, b = 0, c = 0;
 
 C++ 与 Pascal 基本上差不多,常见的有
 
--    `bool` Boolean 类型
--    `int` 整型
+-  `bool` Boolean 类型
+-  `int` 整型
 -   浮点型
-    -    `float` 
-    -    `double` 
--    `char` 字符型
--    `void` 无类型
+    -  `float` 
+    -  `double` 
+-  `char` 字符型
+-  `void` 无类型
 
 C++ 的单引号是专门用于表示单个字符的(字符型),比如 `'a'` ,而字符串(字符型数组)必须要用双引号。
 
@@ -170,7 +206,7 @@ C++ 还要很多额外的数据类型,请参考更多资料。
 
 扩展阅读:
 
--    [基础类型 - cppreference.com](https://zh.cppreference.com/w/cpp/language/types) 
+-  [基础类型 - cppreference.com](https://zh.cppreference.com/w/cpp/language/types) 
 
 #### 常量声明 Constant
 
@@ -184,8 +220,8 @@ const double PI = 3.1415926;
 
 请直接参考
 
--    [附:Pascal 与 C++ 语法对比表](#apascal-c-pascal-vs-c-syntax-table) 
--    [运算 - OI Wiki](../op/) 
+-  [附 A:Pascal 与 C++ 运算符与数学函数语法对比表](#apascal-c-pascal-vs-c-operator-syntax-table) 
+-  [运算 - OI Wiki](../op/) 
 
 ### 条件
 
@@ -212,24 +248,24 @@ if (a == b && a > 0 && b > 0) {
 
 布尔运算与比较
 
--    `and` -> `&&` 
--    `or` -> `||` 
--    `not` -> `!` 
--    `=` -> `==` 
--    `<>` -> `!=` 
+-  `and` -> `&&` 
+-  `or` -> `||` 
+-  `not` -> `!` 
+-  `=` -> `==` 
+-  `<>` -> `!=` 
 
 注释:
 
-1.  Pascal 中 `and` 与 C++ 中 `&&` 优先级不同,C++ 不需要给判断条件加括号。
-2.  Pascal 中判断相等是 `=` ,赋值是 `:=` ;C++ 中判断相等是 `==` ,赋值是 `=` 。
-3.  如果在 `if` 语句的括号内写了 `a = b` 而不是 `a == b` ,程序不会报错,而且会把 `b` 赋值给 `a` , `a = b` 这个语句的返回结果是 `true` 。
-4.  C++ 不需要思考到底要不要在 `end` 后面加分号。
-5.  C++ 布尔运算中,非布尔值可以自动转化为布尔值。
+1. Pascal 中 `and` 与 C++ 中 `&&` 优先级不同,C++ 不需要给判断条件加括号。
+2. Pascal 中判断相等是 `=` ,赋值是 `:=` ;C++ 中判断相等是 `==` ,赋值是 `=` 。
+3. 如果在 `if` 语句的括号内写了 `a = b` 而不是 `a == b` ,程序不会报错,而且会把 `b` 赋值给 `a` , `a = b` 这个语句的返回结果是 `true` 。
+4. C++ 不需要思考到底要不要在 `end` 后面加分号。
+5. C++ 布尔运算中,非布尔值可以自动转化为布尔值。
 
 ???+note "易错提醒"
     特别注意: **不要把 `==` 写成 `=` !** 
-
-    由于 C/C++ 比 Pascal 语法灵活,如果在判断语句中写了 `if (a=b) {`,那么程序会顺利运行下去,因为 C++ 中 `a=b` 是有返回值的。
+    
+    由于 C/C++ 比 Pascal 语法灵活,如果在判断语句中写了 `if (a=b) {` ,那么程序会顺利运行下去,因为 C++ 中 `a=b` 是有返回值的。
 
 ####  `case` 与 `switch` 
 
@@ -289,10 +325,10 @@ for (int i = 1; i <= 10; i++) {
 
 注释:
 
-1.   `for (int i = 1; i <= 10; i++){` 这一行语句很多, `for` 中有三个语句。
-2.  第一个语句 `int i = 1;` 此时声明一局部变量 `i` 并初始化。(这个设计比 Pascal 要合理得多。)
-3.  第二个语句 `i <= 10;` 作为判断循环是否继续的标准。
-4.  第三个语句 `i++` ,在每次循环结尾执行,意思大约就是 Pascal 中的 `inc(i)` ,此处写成 `++i` 也是一样的。 `i++` 与 `++i` 的区别请参考其他资料。
+1.  `for (int i = 1; i <= 10; i++){` 这一行语句很多, `for` 中有三个语句。
+2. 第一个语句 `int i = 1;` 此时声明一局部变量 `i` 并初始化。(这个设计比 Pascal 要合理得多。)
+3. 第二个语句 `i <= 10;` 作为判断循环是否继续的标准。
+4. 第三个语句 `i++` ,在每次循环结尾执行,意思大约就是 Pascal 中的 `inc(i)` ,此处写成 `++i` 也是一样的。 `i++` 与 `++i` 的区别请参考其他资料。
 
 ####  `repeat until` 与 `do while` 循环
 
@@ -334,7 +370,7 @@ C++ 标准库中提供了 `vector` ,相当于不定长数组,调用前需导
 #include <iostream>
 #include <vector>  // 导入 vector 库
 
-int main(int argc, char const *argv[]) {
+int main() {
   std::vector<int> a;  // 声明 vector a 并定义 a 为空 vector 对象
   int n;
 
@@ -364,7 +400,7 @@ C++ 访问数组成员,与 Pascal 类似,不过有很重要的区别:数
 
 扩展阅读:
 
--    [序列式容器 - OI Wiki](../csl/sequence-container/) 
+-  [序列式容器 - OI Wiki](../csl/sequence-container/) 
 
 #### 字符串:标准库类型 String
 
@@ -374,7 +410,7 @@ C++ 标准库中提供了 `string` ,与 `vector` 可以进行的操作有些
 #include <iostream>
 #include <string>
 
-int main(int argc, char const *argv[]) {
+int main() {
   std::string s;  // 声明 string s
 
   std::cin >> s;  // 读入 s;
@@ -388,7 +424,7 @@ int main(int argc, char const *argv[]) {
 
 扩展阅读:
 
--    [string - OI Wiki](../csl/string/) 
+-  [string - OI Wiki](../csl/string/) 
 
 #### C 风格数组 Array
 
@@ -398,9 +434,9 @@ C 风格的数组与指针有密切关系,所以此处不多展开。
 
 扩展阅读:
 
--    [数组 - OI Wiki](../array/) 
+-  [数组 - OI Wiki](../array/) 
 
-## 重要不同之处
+## 重要不同之处 Differences
 
 ### 变量作用域 Scope:全局变量与局部变量
 
@@ -447,7 +483,7 @@ if (i) {  // i = 0 会返回 false,其余返回 true
 }
 ```
 
-不光是 `int` 转成 `bool` ,还有 `int` 与 `float` 相互转换
+不光是 `int` 转成 `bool` ,还有 `int` 与 `float` 相互转换。在 Pascal 中可以把整型赋给浮点型,但不能反过来。C++ 没有这个问题。
 
 ```cpp
 int a;
@@ -462,8 +498,26 @@ float a = 32 / 10;    // 32/10 的结果是 3(整除);a = 3.0
 float b = 32.0 / 10;  // 32.0/10 的结果是 3.2;b = 3.2
 ```
 
+ `pow(a, b)` 计算 $a^b$ ,该函数返回的是浮点型,如果直接用来计算整数的幂,由于有自动转换,不需要担心它会报错
+
+```cpp
+int a = pow(2, 3);  // 计算 2^3
+```
+
 还有 `char` 与 `int` 之间相互转换。
 
+```cpp
+char a = 48;              // ASCII 48 是 '0'
+int b = a + 1;            // b = 49
+std::cout << (a == '0');  // true 输出 1
+```
+
+其实 C++ 中的 `char` 与 `bool` 本质上是整型。
+
+扩展阅读:
+
+-  [隐式转换 - cppreference.com](https://zh.cppreference.com/w/cpp/language/implicit_conversion) 注意内容可能过于专业
+
 ### C++ 很多语句有返回值:以如何实现读取数量不定数据为例
 
 有些时候需要读取到数据结束,比如,求一组不定数量的数之和(数据可以多行),直到文件末尾,实现方式是
@@ -474,7 +528,7 @@ float b = 32.0 / 10;  // 32.0/10 的结果是 3.2;b = 3.2
 ```cpp
 #include <iostream>
 
-int main(int argc, char const *argv[]) {
+int main() {
   int sum = 0, a = 0;
 
   while (std::cin >> a) {
@@ -537,9 +591,13 @@ end.
 ```cpp
 #include <iostream>
 
-void printAns(int ans) { std::cout << ans << std::endl; }
+void printAns(int ans) {
+  std::cout << ans << std::endl;
+
+  return;
+}
 
-int main(int argc, char const *argv[]) {
+int main() {
   int ans = 10;
   printAns(ans);
 
@@ -547,6 +605,57 @@ int main(int argc, char const *argv[]) {
 }
 ```
 
+C++ 的 `return` 与 Pascal 中给函数变量赋值有一点非常大的不同。C++ 的 `return` 即返回一个值,执行完这个语句,函数就执行结束了;而 Pascal 中给函数变量赋值并不会跳出函数本身,而是继续执行。于是,如果 Pascal 需要某处中断函数/过程,就需要一个额外的命令,即 `exit` 。而 C++ 则不需要,如果需要在某处中断,可以直接使用 `return` 。比如(由于实在想不出来简短且实用的代码,所以就先这样)
+
+```cpp
+#include <iostream>
+
+void printWarning(int x) {
+  if (x >= 0) {
+    return;  // 该语句在此处相当于 Pascal 中的 `exit;`
+  }
+  std::cout << "Warning: input a negative number.";
+}
+
+int main() {
+  int a;
+
+  std::cin >> a;
+  printWarning(a);
+
+  return 0;
+}
+```
+
+而在某种意义上,前面的 `abs` 函数,这样才是严格等效的
+
+```pas
+function abs(x:integer):integer;
+begin
+    if x < 0 then
+        begin
+            abs := -x; exit; // !注意此处
+        end
+    else
+        begin
+            abs := x;  exit; // !注意此处
+        end;
+end;
+```
+
+```cpp
+int abs(int x) {
+  if (x < 0) {
+    return -x;
+  } else {
+    return x;
+  }
+}
+```
+
+???+note "特别提醒"
+    C++ 中 `exit` 是退出程序;不要顺手把 `exit` 打上去,要用 `return` !
+
 C++ 把函数和过程统统视作函数,连 `main` 都不放过,比如写 `int main` ,C++ 视 `main` 为一个整型的函数,这里返回值是 `0` 。它是一种习惯约定,返回 `0` 代表程序正常退出。
 
 也许你已经猜到了, `main(int argc, char const *argv[])` 中的参数就是 `int argc` 与 `char const *argv[]` ,不过意义请参考其他资料。
@@ -584,7 +693,7 @@ void swap(int* x, int* y) {
   *y = temp;
 }
 
-int main(int argc, char const* argv[]) {
+int main() {
   int a = 10, b = 20;
   swap(&a, &b);
   std::cout << a << " " << b;
@@ -631,25 +740,28 @@ C++ 标准库中 `<algorithm>` 有很多有用的函数比如快排、二分查
 
 如果要找关于字符串操作的函数见
 
--    [std::basic_string - cppreference.com](https://zh.cppreference.com/w/cpp/string/basic_string) 
--    [ `<string>` - C++ Reference](https://www.cplusplus.com/reference/string/) 
+-  [std::basic_string - cppreference.com](https://zh.cppreference.com/w/cpp/string/basic_string) 
+-  [ `<string>` - C++ Reference](https://www.cplusplus.com/reference/string/) 
 
 C/C++ 的指针是很灵活的东西,如果想要彻底理解指针,建议找本书或者参考手册仔细阅读。
 
+-  [指针 - OI Wiki](../pointer) 
+
 ### 错误排查与技巧
 
--    [常见错误 - OI Wiki](../../intro/common-mistakes/) 
--    [常见技巧 - OI Wiki](../../intro/common-tricks/) 
+-  [常见错误 - OI Wiki](../../intro/common-mistakes/) 
+-  [常见技巧 - OI Wiki](../../intro/common-tricks/) 
 
 ### C++ 语言资料
 
--    [学习资源 - OI Wiki](../../intro/resources/) 
--    [cppreference.com](https://zh.cppreference.com/) - 最重要的 C/C++ 参考资料
--    [C++ Language - C++ Tutorials](https://www.cplusplus.com/doc/tutorial/) 
--    [Reference - C++ Reference](https://www.cplusplus.com/reference/) 
--    [C++ Standard Library - Wikipedia](https://en.wikipedia.org/wiki/C%2B%2B_Standard_Library) 
--    [The Ultimate Question of Programming, Refactoring, and Everything](https://www.gitbook.com/book/alexastva/the-ultimate-question-of-programming-refactoring-/details) 
--    [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) 
+-  [学习资源 - OI Wiki](../../intro/resources/) 
+-  [cppreference.com](https://zh.cppreference.com/) - 最重要的 C/C++ 参考资料
+-  [C++ 教程 - 菜鸟教程](https://www.runoob.com/cplusplus/cpp-tutorial.html) 
+-  [C++ Language - C++ Tutorials](https://www.cplusplus.com/doc/tutorial/) 
+-  [Reference - C++ Reference](https://www.cplusplus.com/reference/) 
+-  [C++ Standard Library - Wikipedia](https://en.wikipedia.org/wiki/C%2B%2B_Standard_Library) 
+-  [The Ultimate Question of Programming, Refactoring, and Everything](https://www.gitbook.com/book/alexastva/the-ultimate-question-of-programming-refactoring-/details) 
+-  [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) 
 
 ## 后记
 
@@ -659,11 +771,18 @@ C/C++ 的指针是很灵活的东西,如果想要彻底理解指针,建议
 
 需要指出的一点是,上面说 C++ 的语法,其实有很多语法是从 C 语言来的,标题这么写比较好——《Pascal 转 C/C++ 急救帖》。
 
-Pascal 在上个世纪后半叶是门很流行的语言,它早于 C 语言,不过随着 UNIX 系统的普及,微软使用 C 语言,现在 Pascal 已经成为历史了。Pascal 后期发展也是有的,比如 Free Pascal 这个开源编译器项目,增加面向对象的特性(Delphi 语言)。Pascal 目前的用处除了在信息竞赛外,有一个特点是其他语言没有的——编译支持非常非常多老旧机器,比如 Gameboy 这种上个世纪的任天堂游戏机。
+Pascal 在上个世纪后半叶是门很流行的语言,它早于 C 语言,不过随着 UNIX 系统的普及,微软使用 C 语言,现在 Pascal 已经成为历史了。Pascal 后期发展也是有的,比如 Free Pascal 这个开源编译器项目,增加面向对象的特性(Delphi 语言)。Pascal 目前的用处除了在信息竞赛外,有一个特点是其他语言没有的——编译支持非常非常多老旧机器,比如 Gameboy 这种上个世纪的任天堂游戏机,还有一个用处就是以伪代码的形式(Pascal 风格的伪代码)出现在各种教科书中
 
 最后,Pascal 的圈子其实很小,C/C++ 的圈子很大,帮助手册与教程很多很全,一定要掌握好英语。世界上还有很多很多编程语言,而计算机这门学科与技术不光是信息竞赛和编程语言。
 
-## 附 A:Pascal 与 C++ 语法对比表 Pascal vs C++ Syntax Table
+### 本文 Pascal 语言的参考文献
+
+-  [Lazarus wiki](https://wiki.freepascal.org/) 
+-  [Free Pascal Reference guide](https://freepascal.org/docs-html/current/ref/ref.html) 
+
+## 附 A:Pascal 与 C++ 运算符与数学函数语法对比表 Pascal vs C++ Operator Syntax Table
+
+> 仅包括最常用的运算符与函数。
 
 ### 基本算术
 
@@ -715,27 +834,47 @@ Pascal 在上个世纪后半叶是门很流行的语言,它早于 C 语言,
 | 自减  |  `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` 库。
+
+其他函数请参考:
+
+-  [常用数学函数 - cppreference.com](https://zh.cppreference.com/w/cpp/numeric/math) 
+
 ## 附 B:文章检索 Index
 
--    [基本语法](#c-start-here) 
+> 按 C++ 语句语法索引。
+
+-  [基本语法](#c-start-here) 
 -    [变量](#variable) 
-    -    [数据类型](#fundamental-types) 
-    -    [常量声明](#constant) 
-    -    [作用域](#scope) 
--    [运算符](#operator) 
+    -  [数据类型](#fundamental-types) 
+    -  [常量声明](#constant) 
+    -  [作用域](#scope) 
+-  [运算符](#operator) 
 -    [if 语句](#if) 
-    -   if
-    -   else
+    - if
+    - else
 -    [循环语句](#loop) 
-    -    [for 语句](#for) 
-    -    [while 语句](#while) 
-    -    [do while 语句](#repeat-until-do-while) 
-    -    [break, continue](#loop-control) 
+    -  [for 语句](#for) 
+    -  [while 语句](#while) 
+    -  [do while 语句](#repeat-until-do-while) 
+    -  [break, continue](#loop-control) 
 -    [函数](#functionc-void-return) 
-    -    [函数定义](#functionc-void-return) 
-    -    [函数传参](#passing-parameters-to-functions) 
+    -  [函数定义,return](#functionc-void-return) 
+    -  [函数传参](#passing-parameters-to-functions) 
 -    [数组与字符串](#array-and-string) 
-    -    [不定长数组 Vector](#vector) 
-    -    [C 风格数组](#c-array) 
-    -    [字符串 String](#string) 
--    [资料](#c-reference) 
+    -  [不定长数组 Vector](#vector) 
+    -  [C 风格数组](#c-array) 
+    -  [字符串 String](#string) 
+-  [资料](#c-reference)