Skip to content

Commit 513e7c9

Browse files
committed
Reviewed Chapter 1
1 parent 051c4ff commit 513e7c9

21 files changed

+623
-610
lines changed

.vscode/Test.cpp

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,16 @@
1-
#include <iostream>
2-
#include <fstream>
3-
#include <filesystem>
4-
#include <stack>
5-
namespace fs = std::filesystem;
6-
int main() {
7-
try {
8-
fs::path ph {fs::current_path() / ".vscode"};
9-
std::ifstream fin {ph / "in.txt"};
10-
std::ofstream fout {ph / "out.txt"};
11-
if (!fin.is_open()) //输入文件异常检测
12-
throw std::ios_base::failure {"Cannot open in.txt"};
13-
if (!fout.is_open()) //输出文件异常检测
14-
throw std::ios_base::failure {"Cannot open out.txt"};
15-
std::stack<char> stk; //定义一个栈,方便我们存取数据
16-
int ch = {fin.get()}; //定义一个ch,逐个字符地接收get()输入数据
17-
while (!fin.eof()) { //如果fin还没有读到文件结尾
18-
stk.push(ch); //就说明ch是有效内容,把它填入栈中
19-
ch = fin.get(); //接收下一个字符输入
20-
}
21-
while (stk.size()){ //只要栈中还有数据,那就说明输出还没到头
22-
fout << stk.top(); //用fout输出栈顶元素
23-
stk.pop(); //栈顶的元素弹出
24-
}
25-
std::cout << "Done" << std::endl; //提示操作完成
26-
} catch (const std::ios_base::failure &msg) {
27-
std::cerr << "An exception has been caught:\n" << msg.what();
28-
}
1+
//这段程序可以告诉你当前使用的C++标准和编译器都是什么
2+
#include <iostream> //标准输入输出头文件
3+
using namespace std; //使用std命名空间
4+
int main() { //主函数;以上都是固定格式,照搬就行
5+
cout << "Current C++ Standard: " << __cplusplus << endl; //语言标准
6+
#if defined(__clang__) || defined(__llvm__) //通过检测宏常量判断编译器类型
7+
cout << "Current C++ Compiler: Clang" << endl; //Clang编译器
8+
#elif defined(__GNUC__) || defined(__GNUG__)
9+
cout << "Current C++ Compiler: GCC" << endl; //GCC编译器
10+
#elif defined(_MSC_VER)
11+
cout << "Current C++ Compiler: MSVC" << endl; //MSVC编译器
12+
#else //如果你使用的是其它编译器,那么将会输出Others;本书不推荐读者使用其它编译器
13+
cout << "Current C++ Compiler: Others" << endl;
14+
#endif
2915
return 0;
3016
}

.vscode/Test.exe

-335 KB
Binary file not shown.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//这段程序可以告诉你当前使用的C++标准和编译器都是什么
2+
#include <iostream> //标准输入输出头文件
3+
using namespace std; //使用std命名空间
4+
int main() { //主函数;以上都是固定格式,照搬就行
5+
cout << "Current C++ Standard: " << __cplusplus << endl; //语言标准
6+
#if defined(__clang__) || defined(__llvm__) //通过检测宏常量判断编译器类型
7+
cout << "Current C++ Compiler: Clang" << endl; //Clang编译器
8+
#elif defined(__GNUC__) || defined(__GNUG__)
9+
cout << "Current C++ Compiler: GCC" << endl; //GCC编译器
10+
#elif defined(_MSC_VER)
11+
cout << "Current C++ Compiler: MSVC" << endl; //MSVC编译器
12+
#else //如果你使用的是其它编译器,那么将会输出Others;本书不推荐使用其它编译器
13+
cout << "Current C++ Compiler: Others" << endl;
14+
#endif
15+
return 0;
16+
}

generalized_parts/01_welcome_to_cpp.tex

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
\chapter{初识C++}
2-
在本章,我们将会了解一些C++中最基本的知识,最常见的概念,和最简单的语法,并付诸代码来实现。\par
3-
我们不要求读者搞懂每句代码的含义——那是不必要的。我们在本章中会给出一个基本的代码模板,读者只需修改其中的一小部分即可。毕竟,\textbf{学习都是从模仿开始的},C++也不例外。\par
2+
在本章,我们将会了解一些C++中最基本的知识最常见的概念,和最简单的语法,并付诸代码来实现。\par
3+
我不强求读者搞懂每句代码的含义——那是不必要的。我在本章中会给出一个基本的代码模板,读者只需修改其中的一小部分内容即可。毕竟,\textbf{学习都是从模仿开始的},C++也不例外。\par
44
有一点值得注意。我们需要有一个编译器,来把我们的代码(.cpp文件或者别的什么)变成可以执行和看到效果的程序(Windows中的.exe文件、Linux或MacOS上的可执行文件,或者别的什么),以便检查它能否实现我们想要的功能,并在日后使用这个程序。\par
5-
根据自己计算机的系统,你可以选择\href{https://www.embarcadero.com/free-tools/dev-cpp}{Embarcadero Dev-C++ (Windows)}, \href{https://learn.microsoft.com/zh-cn/cpp/?view=msvc-170}{Microsoft Visual C++ (Windows)}, \href{https://developer.apple.com/xcode/}{Apple Xcode (MacOS)}, \href{https://github.com/open-watcom/open-watcom-v2}{Open Watcom C++ (Windows/Linux/DOS)}, \href{https://www.codeblocks.org/}{Code::Blocks (跨系统)}, \href{https://www.monodevelop.com/}{MonoDevelop (跨系统)}。这些都是集成开发环境\footnote{集成开发环境(Integrated Development Environment, IDE),是一种辅助进行软件开发的应用。在开发工具内部就可以编写源代码,并编译打包成为可用的程序。IDE需要的配置较少,对新手比较友好,上手容易。},你只需要在下载后做很简单的配置,就可以开始写代码了。\par
6-
另外还有一些代码编辑器,比如\href{https://code.visualstudio.com/}{Visual Studio Code (Windows/Linux/MacOS)}, \href{https://www.sublimetext.com/}{Sublime Text (Windows/Linux/MacOS)}, \href{https://www.vim.org/}{Vim (跨系统)},你需要做额外的配置(比如安装插件),把它们变得如同集成开发环境一样。\par
7-
另有一些在线的代码编译工具,让你可以无需安装软件,只要在浏览器上提供代码,就能远程编译并告诉你运行结果。比如\href{https://coliru.stacked-crooked.com/}{Coliru}\href{https://wandbox.org/}{Wandbox}。不过相比于本地编译运行,这种方式的交互效果就相当差劲了,仅适合一些无输入或只有简单输入的程序。这些在线编译方式对于本章涉及的程序来说当然够用,但不要太过依赖\par
5+
根据自己计算机的系统,你可以选择 \href{https://www.embarcadero.com/free-tools/dev-cpp}{Embarcadero Dev-C++ (Windows)}, \href{https://learn.microsoft.com/zh-cn/cpp/?view=msvc-170}{Microsoft Visual C++ (Windows)}, \href{https://developer.apple.com/xcode/}{Apple Xcode (MacOS)}, \href{https://github.com/open-watcom/open-watcom-v2}{Open Watcom C++ (Windows/Linux/DOS)}, \href{https://www.codeblocks.org/}{Code::Blocks (跨系统)}, \href{https://www.monodevelop.com/}{MonoDevelop (跨系统)}。这些都是集成开发环境\footnote{集成开发环境(Integrated Development Environment, IDE),是一种辅助进行软件开发的应用。在开发工具内部就可以编写源代码,并编译打包成为可用的程序。IDE需要的配置较少,对新手比较友好,上手容易。},你只需要在下载后做很简单的配置,就可以开始写代码了。\par
6+
另外还有一些代码编辑器,比如 \href{https://code.visualstudio.com/}{Visual Studio Code (Windows/Linux/MacOS)}, \href{https://www.sublimetext.com/}{Sublime Text (Windows/Linux/MacOS)}, \href{https://www.vim.org/}{Vim (跨系统)},你需要做额外的配置(比如安装插件,配置编译器),把它们变得如同集成开发环境一样。\par
7+
另有一些在线的代码编译工具,让你可以无需安装软件,只要在浏览器上提供代码,就能远程编译并告诉你运行结果。比如 \href{https://coliru.stacked-crooked.com/}{Coliru}, \href{https://wandbox.org/}{Wandbox}\href{https://cpp.sh/}{C++ Shell}。不过相比于本地编译运行,这种方式的交互效果就相当差劲了,仅适合一些无输入或只有简单输入的程序。这些在线编译方式对于本章涉及的程序来说当然够用,但读者不要太过依赖\par
88
\import{01_welcome_to_cpp/}{01_start_with_a_cpp_program.tex}
99
\import{01_welcome_to_cpp/}{02_data_and_information.tex}
1010
\import{01_welcome_to_cpp/}{03_define_and_use_data.tex}

generalized_parts/01_welcome_to_cpp/01_start_with_a_cpp_program.tex

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ \section{开始一个C++程序}
1616
实际上的过程会更复杂,比如在编译之前还会进行预处理(Preprocess)。但是我们现在还不需要操心这么多,因为在按下``编译''键之后,预处理和编译都会进行,所以不妨把它统称为一个过程。\par
1717
\subsection*{编译器的选择}
1818
C++的\textbf{编译器(Compiler)}非常丰富。\href{https://en.wikipedia.org/wiki/List_of_compilers\#C++_compilers}{List of C++ Compilers - Wikipedia} 条目为我们提供了一个不完全的C++编译器列表。\par
19-
一般我们选择使用Clang、GCC或Visual C++(MSVC),它们都是跨系统的编译器,对语言标准的支持比较好\footnote{Clang和GCC支持C++17以前标准和C++20的大部分标准,而MSVC支持C++20的全部标准和C++23的部分标准。},许多IDE(如Dev\_C++, Code::Blocks,Visual C++等)也都默认提供这些编译器之一。另外,Coliru和Wandbox等在线编译器也都支持使用Clang和GCC\par
20-
同种的编译器也会有版本上的差异。很多古老的版本(如GCC 4.9.4)并不支持新近的语法(如C++17\footnote{C++17是C++委员会制定的一个语言标准,其最终版发布于2017年12月。这也是本书采用的主要语言标准。})。新版本的编译器往往有很多好用的特性,比如对代码有更好的优化。\footnote{另请注意,最好选择稳定版本的编译器,而非试验性的测试版,以免出现问题带来的麻烦。}\par
19+
一般我们选择使用Clang、GCC或Visual C++(MSVC),它们都是跨系统的编译器,对语言标准的支持比较好\footnote{Clang和GCC支持C++17以前标准和C++20的大部分标准,而MSVC支持C++20的全部标准和C++23的部分标准。},许多IDE(如Dev\_C++, Code::Blocks,Visual C++等)也都默认提供这些编译器之一。另外,Coliru, Wandbox和C++ Shell等在线编译器也都支持使用Clang或GCC\par
20+
同种的编译器也会有版本上的差异。很多古老的版本(如GCC 4.9.4)并不支持新近的语法(如C++17\footnote{C++17是C++委员会制定的一个语言标准,发布于2017年,代号为 \lstinline@201703L@。})。新版本的编译器往往有很多好用的特性,比如对代码有更好的优化。\footnote{另请注意,最好选择稳定版本的编译器,而非试验性的预览版,以免编译器自身存在问题带来的麻烦。}\par
2121
\subsection*{语言标准的选择}
2222
不同的C++\textbf{标准(Standard)}对语法的支持不同。比如说,在C++11以后的标准中下,可以使用 \lstinline@auto@ 来自动确定我们要定义的变量类型。这是一种很方便的语法,但C++11以前的版本就不支持使用。\par
2323
C++语言标准的更新总会带来很多新的功能,也会对以往标准中的缺陷和漏洞加以弥补,所以越新的标准往往就越强大、易用。另一方面,新标准通常都能兼容旧标准\footnote{只是通常如此。有很多反例,比如C++17标准移除了古已有之的 \lstinline@std::auto_ptr@。},所以你也无需担心为了适应新标准而放弃很多旧知识,或者换用新标准后很多代码编译失败了。\par
@@ -33,7 +33,7 @@ \subsubsection*{Windows下运行的可能问题}
3333
}
3434
\end{lstlisting}
3535
\lstinline@cin.get()@ 的作用是读取下一个键盘输入,所以如果你不按下键盘上的Enter键,程序就会一直等待下去。(只有按下Enter,输入内容才能发送给程序,我们后面会慢慢道来)\par
36-
至于用两个 \lstinline@cin.get()@,这是为了应对可能的 \lstinline@'\n'@ 遗留被第一个 \lstinline@cin.get()@ 吞没。我们现在尚无必要在乎这些细枝末节,只需要知道:如果窗口没有保持打开,就加一个 \lstinline@cin.get()@;如果还不行,就加两个 \lstinline@cin.get()@。\footnote{值得留意的是,用 \lstinline@cin.get()@ 来阻断程序进度只是一种临时的解决方案,目的在于便于我们进行学习和演示。而在实际的开发中,人们通常不会在程序中添加这种代码。}\par
36+
至于用两个 \lstinline@cin.get()@,这是为了应对可能的 \lstinline@'\n'@ 遗留被第一个 \lstinline@cin.get()@ 吞没。我们现在尚无必要在乎这些细枝末节,只需要知道:如果窗口没有保持打开,就加一个 \lstinline@cin.get()@;如果还不行,就加两个 \lstinline@cin.get()@。\footnote{值得留意的是,用 \lstinline@cin.get()@ 来阻断程序进度只是一种临时的解决方案,目的在于方便我们进行学习和演示。而在实际编程中,人们通常不会在程序中添加这种代码。}\par
3737
\subsection*{回到Hello World}
3838
现在让我们回来看Hello World代码。这个代码可以在任何操作系统上,用任何编译器和任何语言标准来编译。程序的输出就是一个单词 \texttt{Hello World!}。\par
3939
\begin{lstlisting}
@@ -43,11 +43,11 @@ \subsection*{回到Hello World}
4343
\begin{lstlisting}
4444
#include <iostream> //标准输入输出头文件
4545
\end{lstlisting}
46-
程序的第二行是一个\textbf{文件包含(File Inclusion)}。通过这个语句,预处理器会对代码作预处理\footnote{如前所述,源代码在编译之前需要经过预处理,例如文件包含和宏。预处理结束后,编译才会开始。},将本句命令替换成 \lstinline@iostream@ 库中的代码\par
46+
程序的第二行是一个\textbf{文件包含(File Inclusion)}。通过这个语句,预处理器会对代码作预处理\footnote{如前所述,源代码在编译之前需要经过预处理,例如文件包含和宏的展开。预处理结束后,编译才会开始。}, \lstinline@iostream@ 库中的代码导入该文件中\footnote{所以这个源代码的实际的内容量会比你看上去的大很多,绝大多数来自于文件包含命令。}\par
4747
\begin{lstlisting}
4848
using namespace std; //使用std命名空间
4949
\end{lstlisting}
50-
程序的第三行是一个\textbf{命名空间(Namespace)}使用。C++中,\lstinline@cout@ 被定义\footnote{定义(Definition),是为程序中的一个实体(如变量、函数、类等)分配内存并提供其具体的实现或值的过程。在以C++为代表的静态语言中,一个实体必须定义才能使用。}在 \lstinline@std@ 命名空间中,我们要通过 \lstinline@std::cout@ 这样的语法才可以使用它。而有了 \lstinline@using namespace std;@ 之后,我们就可以直接使用 \lstinline{cout}。\par
50+
程序的第三行是一个\textbf{命名空间(Namespace)}使用。C++中,\lstinline@cout@ 被定义\footnote{定义(Definition),是为程序中的一个实体(如变量、函数、类等)分配内存并提供其具体的实现或值的过程。在以C++为代表的静态语言中,一个实体必须定义才能使用。}在 \lstinline@std@ 命名空间中,我们要通过 \lstinline@std::cout@ 这样的语法才可以使用它。而有了 \lstinline@using namespace std@ 之后,我们就可以直接使用 \lstinline{cout}。\par
5151
关于文件包含和命名空间的概念,我们会在第七章进行讲解。目前我们无需过分纠结。\par
5252
\begin{lstlisting}
5353
int main(){//主函数,程序执行始于此
@@ -62,6 +62,15 @@ \subsection*{回到Hello World}
6262
\lstinline@<<@ 左侧的 \lstinline@cout@ 是在标准库 \lstinline@iostream@ 中定义的 \lstinline@std@ 空间的对象,控制标准输出。我们无需对它作修改;\lstinline@<<@ 右侧的 \lstinline@"hello World!"@ 则是我们要输出的内容。外套双引号表示它是一个字符串,我们会在第五章讲解字符串。\par
6363
如果我们想要输出一个数字,我们只需要修改 \lstinline@<<@ 右侧的内容即可,比如
6464
\begin{lstlisting}
65-
cout << 3.14159;//输出圆周率小数点后五位
65+
cout << 3.14159;//输出3.14159这个数
6666
\end{lstlisting}
6767
第三节我们就会开始介绍如何使用 \lstinline@cout@ 来输出数据。\par
68+
\subsection*{输出你的编译器/语言标准信息}
69+
读者可能搞完了自己的开发环境,但是对编译器和语言标准的问题依旧感到茫然。下面这段程序可以输出当前所用的编译器和语言标准信息:
70+
\lstinputlisting[caption=\texttt{standard\_and\_compiler.cpp}]{code_in_book/1.2/standard_and_compiler.cpp}
71+
这段代码,我们就不讲了,只是拿来运行就好。它的输出结果因你的开发环境而异\footnote{根据已知信息,Visual Studio 2022对于 \lstinline@__cplusplus@ 的输出结果总是 \lstinline@199711@,这可能是一个Bug。如果要让它输出正确结果,需要在编译命令行中添加 \texttt{/Zc:\_\_cplusplus} 指令才行。这对于初学者来说可能有点难,但是也不要担心,这个问题不会影响我们对于语言标准的正常使用,所以不这么做也没问题。}。对于我的开发环境来说,它的输出结果是\\\noindent\rule{\linewidth}{.2pt}\texttt{
72+
Current C++ Standard: 201703\\
73+
Current C++ Compiler: GCC
74+
}\\\noindent\rule{\linewidth}{.2pt}\\
75+
这说明我当前使用的C++标准是C++17。对于C++11以前的标准来说,它会显示 \lstinline@199711@;对于C++11, C++14, C++20和C++23来说,它们会分别显示 \lstinline@201103@, \lstinline@201402@, \lstinline@202002@ 和 \lstinline@202302@。读者可以对号入座,了解自己当前使用的C++语言标准。\par
76+
如果读者使用的标准不是C++17,希望读者根据软件的使用说明,修改自己的语言标准;如果编译器本身不支持C++17,希望读者换成较新版本的编译器。如果读者使用的不是本书推荐的三种编译器之一,也希望读者能改用这三种编译器,以获得最佳的使用效果。\par

0 commit comments

Comments
 (0)