Skip to content

Commit 568bda7

Browse files
committed
Reviewed Chapter 3
1 parent 40eeea9 commit 568bda7

16 files changed

+145
-128
lines changed

.vscode/Test.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
#include <iostream>
22
#include <limits>
33
int main() {
4-
std::cout<<std::numeric_limits<long double>::min();
4+
using namespace std;
5+
for (int i = 0; i < 5; i++) { //i++与++i在这里效果相同
6+
for (int j = 1; j <= 5; j++) {
7+
cout << i * 5 + j << ' '; //每输出一个数字,以空格隔开
8+
}
9+
cout << endl; //每输出五个数字,以换行隔开
10+
}
511
return 0;
612
}

.vscode/Test.exe

-1.05 KB
Binary file not shown.
File renamed without changes.

generalized_parts/01_welcome_to_cpp/01_start_with_a_cpp_program.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ \subsection*{回到Hello World}
6767
第三节我们就会开始介绍如何使用 \lstinline@cout@ 来输出数据。\par
6868
\subsection*{输出你的编译器/语言标准信息}
6969
读者可能搞完了自己的开发环境,但是对编译器和语言标准的问题依旧感到茫然。下面这段程序可以输出当前所用的编译器和语言标准信息:
70-
\lstinputlisting[caption=\texttt{standard\_and\_compiler.cpp}]{code_in_book/1.2/standard_and_compiler.cpp}
70+
\lstinputlisting[caption=\texttt{standard\_and\_compiler.cpp}\label{lst:standard_and_compiler}]{code_in_book/1.2/standard_and_compiler.cpp}
7171
这段代码,我们就不讲了,只是拿来运行就好。它的输出结果因你的开发环境而异\footnote{根据已知信息,Visual Studio 2022对于 \lstinline@__cplusplus@ 的输出结果总是 \lstinline@199711@,这可能是一个Bug。如果要让它输出正确结果,需要在编译命令行中添加 \texttt{/Zc:\_\_cplusplus} 指令才行。这对于初学者来说可能有点难,但是也不要担心,这个问题不会影响我们对于语言标准的正常使用,所以不这么做也没问题。}。对于我的开发环境来说,它的输出结果是\\\noindent\rule{\linewidth}{.2pt}\texttt{
7272
Current C++ Standard: 201703\\
7373
Current C++ Compiler: GCC

generalized_parts/01_welcome_to_cpp/02_data_and_information.tex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ \subsubsection*{整数类型(Integer type)}
4343
\subsubsection*{浮点类型(Floating-point type)}
4444
浮点类型有点像``科学记数法'',一个浮点数既有表示分数的部分(Fraction),又有表示冪次的部分(Exponent bias)。它既可以表示小数,也可以表示整数,并且数据范围非常宽\footnote{值得注意的是,浮点类型的数据都有精度限制,不能准确表示有效数字过多的数据。正因如此,浮点类型不适合用来表示和计算特别大的整数;这时应当使用整型。}。\par
4545
C++同样提供了内置的浮点类型。不同类型的区别主要在于以下两点:其一,它们能表示的有效位数各不相同;其二,它们的冪指数范围有宽有窄。\par
46-
\subsubsection*{字符类型(Character type)}
47-
严格说来,字符型是一种特殊的整型。不同之处在于,字符数据不是用来``计算''而是用来``编码''的。\par
48-
以最原始而最通用的ASCII码\footnote{美国信息标准交换代码(American Standard Code for Information Interchange, ASCII),是一套基于拉丁字母的编码系统,主要用于显示现代英语。}为例,它有若干控制字符和可显示字符,每个字符都有一个编码,如图1.1所示。读者无需记忆本图,只需知道它是一套编码系统即可。通过ASCII,每个拉丁字母都能编码成一个整数,比如字符\texttt{'0'}对应着编码48,字符\texttt{'A'}对应着编码65,字符\texttt{'a'}对应着编码97。\par
4946
\begin{figure}[htbp]
5047
\centering
5148
\includegraphics[width=0.75\textwidth]{../images/generalized_parts/01_ASCII.png}
5249
\caption{一个ASCII码表}
5350
\footnotesize{图片来源:维基共享资源}
5451
\end{figure}
52+
\subsubsection*{字符类型(Character type)}
53+
严格说来,字符型是一种特殊的整型。不同之处在于,字符数据不是用来``计算''而是用来``编码''的。\par
54+
以最原始而最通用的ASCII码\footnote{美国信息标准交换代码(American Standard Code for Information Interchange, ASCII),是一套基于拉丁字母的编码系统,主要用于显示现代英语。}为例,它有若干控制字符和可显示字符,每个字符都有一个编码,如图1.1所示。读者无需记忆本图,只需知道它是一套编码系统即可。通过ASCII,每个拉丁字母都能编码成一个整数,比如字符\texttt{'0'}对应着编码48,字符\texttt{'A'}对应着编码65,字符\texttt{'a'}对应着编码97。\par
5555
这套字符编码只适用于现代拉丁字母。如果要表示其它语言(比如中文)的字符,就需要用更复杂的编码规则。我们会在精讲篇中细细道来。\par

generalized_parts/03_control_flow/01_introduction_to_structure_process_and_order.tex

Lines changed: 28 additions & 30 deletions
Large diffs are not rendered by default.

generalized_parts/03_control_flow/02_choice.tex

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
\section{选择结构}
22
在此之前我们遇到的代码都是顺序结构的,程序一个接一个地执行一系列操作。仅用顺序结构是不能完成复杂工作的,比如根据一定的条件,作出不同的反应。这时我们就需要用到选择结构了。\par
33
\lstinline@if@-\lstinline@else@ 结构是最常用的选择结构,而 \lstinline@switch@-\lstinline@case@ 结构在处理特定的条件判断时,会更加高效。本节我们就来介绍这两种结构。\par
4-
\subsection*{\lstinline@if@-\lstinline@else@ 结构}
4+
\subsection*{\texttt{if}-\texttt{else}结构}
55
\lstinline@if@-\lstinline@else@ 结构的基本格式是这样的:
66
\begin{lstlisting}
77
if (<条件>) { //if是必需的
@@ -44,17 +44,17 @@ \subsection*{\lstinline@if@-\lstinline@else@ 结构}
4444
else {
4545
cout << "偶数"; //输出"偶数"
4646
}
47-
\end{lstlisting}
48-
这个程序的流程图如图3.7所示。可以看出,前面部分是顺序结构,后面部分是选择结构。\par
49-
\begin{figure}[htbp]
50-
\centering
51-
\includegraphics[width=0.3\textwidth]{../images/generalized_parts/03_structure_of_odd_or_even.drawio.png}
52-
\caption{奇偶判断程序流程图}
53-
\end{figure}
47+
\end{lstlisting}
48+
这个程序的流程图如图3.7所示。可以看出,前面部分是顺序结构,后面部分是选择结构。\par
49+
\begin{figure}[htbp]
50+
\centering
51+
\includegraphics[width=0.3\textwidth]{../images/generalized_parts/03_structure_of_odd_or_even.drawio.png}
52+
\caption{奇偶判断程序流程图}
53+
\end{figure}\pagebreak
5454
最后Ctrl+V一下文件包含等等乱七八糟的代码,就是这样:
5555
\lstinputlisting[caption=\texttt{odd\_or\_even.cpp},label=lst:oddoreven]{../code_in_book/3.2/odd_or_even.cpp}
56-
读者可以自行测试一下,例如输入\texttt{1},程序就会给出输出 \texttt{奇数};输入\texttt{2},程序就会给出输出 \texttt{偶数}。\par
57-
如果甲方有什么其它的奇怪要求,比如``如果是偶数就输出,如果是奇数就不输出'',这时我们就只需要为偶数部分写一个 \lstinline@if@ 块即可,没有必要再写 \lstinline@else@ 块,代码可以这样写:
56+
读者可以自行测试一下,例如输入\texttt{1},程序就会给出输出``\texttt{奇数}'';输入\texttt{2},程序就会给出输出``\texttt{偶数}''\par
57+
如果甲方有什么其它的奇怪要求,比如``如果是偶数就输出,如果是奇数就不输出'',这时我们就只需要为偶数部分写一个 \lstinline@if@ 块即可,没有必要再写 \lstinline@else@ 块,代码可以这样写:\pagebreak
5858
\begin{lstlisting}
5959
if (mod == 0) { //注意,判断条件是mod是否为0
6060
cout << "偶数"; //mod为0说明它是偶数
@@ -87,7 +87,7 @@ \subsubsection{多路分支的选择结构}
8787
}
8888
\end{lstlisting}\par
8989
有些参考资料将其称为 \lstinline@if@ - \lstinline@else if@ - \lstinline@else@ 结构,以 \lstinline@if@ 加条件为开头,中间全用 \lstinline@else if@ 加条件的形式,结尾用 \lstinline@else@。\par
90-
但是以我个人的观点来看,实际上并没有 \lstinline@else if@ 这个关键字。它是 \lstinline@else@ 嵌套了 \lstinline@if@ 的结构,本质上只是对 \lstinline@if@-\lstinline@else@ 结构的一种特殊应用。这段代码与下面的代码并无任何区别\footnote{与Python等一些语言不同,C++对代码的缩进、换行和标识符间的空格几乎没有任何限制,所以缩进的修改、换行的使用,乃至特定情况下是否套花括号 \lstinline@\{\}@ 都不会对编译造成影响。}:
90+
但是以我的观点来看,实际上并没有 \lstinline@else if@ 这个关键字。它是 \lstinline@else@ 嵌套了 \lstinline@if@ 的结构,本质上只是对 \lstinline@if@-\lstinline@else@ 结构的一种特殊应用。这段代码与下面的代码并无任何区别\footnote{与Python等一些语言不同,C++对代码的缩进、换行和标识符间的空格几乎没有任何限制,所以缩进的修改、换行的使用,乃至特定情况下是否套花括号 \lstinline@\{\}@ 都不会对编译造成影响。}:
9191
\begin{lstlisting}
9292
if (ch >= 'A' && ch <= 'Z') {
9393
cout << "大写字母";
@@ -104,13 +104,13 @@ \subsubsection{多路分支的选择结构}
104104
cout << "其它";
105105
}
106106
\end{lstlisting}
107-
这样就是 \lstinline@if@-\lstinline@else@ 方式的理解了。所以 \lstinline@else if@ 只不过是一种更紧湊的写法而已,不能称为一个``关键字''。它的 \lstinline@else@ 部分属于上一个 \lstinline@if@-\lstinline@else@ 结构,而 \lstinline@if@ 部分属于下一个 \lstinline@if@-\lstinline@else@ 结构。图3.描述了这样一种结构是如何搭建起来的\par
107+
这样就是 \lstinline@if@-\lstinline@else@ 方式的理解了。所以 \lstinline@else if@ 只不过是一种更紧湊的写法而已,不能称为一个``关键字''。它的 \lstinline@else@ 部分属于上一个 \lstinline@if@-\lstinline@else@ 结构,而 \lstinline@if@ 部分属于下一个 \lstinline@if@-\lstinline@else@ 结构。图3.8描述了这样一种结构是如何搭建起来的\par
108108
\begin{figure}[htbp]
109109
\centering
110110
\includegraphics[width=0.4\textwidth]{../images/generalized_parts/03_if_elseif_else.drawio.png}
111111
\caption{\lstinline@if@-\lstinline@else@ 嵌套实现多路分支}
112112
\end{figure}
113-
\subsection*{\lstinline@switch@-\lstinline@case@ 结构}
113+
\subsection*{\texttt{switch}-\texttt{case}结构}
114114
\lstinline@switch@-\lstinline@case@ 结构是一种在特定情况下可以方便地实现多路选择的选择结构。它的基本语法是
115115
\begin{lstlisting}
116116
switch (<整型数据>) {
@@ -125,14 +125,13 @@ \subsection*{\lstinline@switch@-\lstinline@case@ 结构}
125125
break; //break并非必需,尤其对于最末的case而言
126126
}
127127
\end{lstlisting}\par
128-
\lstinline@switch@\lstinline@case@ 结构与 \lstinline@if@ 结构不同,它的判断是通过``匹配''进行的。\par
129-
\lstinline@switch@ 块中的每个 \lstinline@case@ 都是一个标签,能对某个位置进行标记。\lstinline@switch@ 跟随的整型数据将会去匹配每个\lstinline@case@ 标签后的字面量\footnote{其实不光是字面量,所有常量表达式都是可以用的。}。一旦匹配到了合适的字面量,程序就会从本句开始顺序执行。\par
128+
\lstinline@switch@-\lstinline@case@ 结构与 \lstinline@if@\lstinline@else@ 结构不同,它的判断是通过``匹配''进行的。\lstinline@switch@ 块中的每个 \lstinline@case@ 都是一个标签,能对某个位置进行标记。\lstinline@switch@ 跟随的整型数据将会去匹配每个\lstinline@case@ 标签后的字面量\footnote{其实不光是字面量,所有常量表达式都是可以用的。}。一旦匹配到了合适的字面量,程序就会从本句开始顺序执行。\par
130129
现在我们要输入一个1\~{}6之间的正整数,并输出它的英文(one, two, \ldots);如果输入不是1\~{}6之间的正整数,就什么也不做。我们可以按照下面这个使用 \lstinline@switch@-\lstinline@case@ 结构的代码来实现这个功能。
131130
\begin{lstlisting}
132131
int num; //定义待输入变量,注意必须用整型、字符型或布尔型
133132
cin >> num; //输入num的值
134133
switch (num) {
135-
case 6: //case可以从1到6,也可以从6到1,也可以打乱顺序,对应即可
134+
case 6: //case可以从1到6,也可以从6到1,也可以打乱顺序,语法上都正确
136135
cout << "six" <<endl; //如果num匹配6,就从这里开始顺序执行
137136
break; //用break来退出switch块
138137
case 5:
@@ -152,19 +151,21 @@ \subsection*{\lstinline@switch@-\lstinline@case@ 结构}
152151
}
153152
\end{lstlisting}
154153
可以看出,这样写要比用 \lstinline@else if@ 然后加一众 \lstinline@num==@ 的方式要简洁一些。读者可以自行测试这段代码,看看效果。\par
155-
\lstinline@switch@-\lstinline@case@ 结构有一个特性,叫做\textbf{穿透效应(Fallthrough behavior)}。因为 \lstinline@case@ 只是一个标签,不能起到退出 \lstinline@switch@ 结构的作用,所以如果在写每个 \lstinline@case@ 之后不加以 \lstinline@break@ 的话,程序将会继续运行下一个 \lstinline@case@、再下一个 \lstinline@case@,至到遇到一个退出语句或者运行到 \lstinline@switch@ 的末尾为止。\par
156-
举个例子来说,如果上面的代码不加 \lstinline@break@ 的话,程序运行的结果将是这样的\footnote{本书默认:键盘输入的内容用黑体标识,程序输出的内容不用黑体。换行符不单独显示,行末空格和回车也忽略掉。如有特殊情况,会特别说明。}:\\\noindent\rule{\linewidth}{0.2pt}\texttt{
154+
\lstinline@switch@-\lstinline@case@ 结构有一个特性,叫做\textbf{穿透效应(Fallthrough behavior)}。因为每个 \lstinline@case@ 只是一个标签,不能起到退出 \lstinline@switch@ 结构的作用,所以若是在写每个 \lstinline@case@ 之后不加以 \lstinline@break@ 的话,程序将会继续运行下一个 \lstinline@case@、再下一个 \lstinline@case@,直到遇到一个退出语句或者运行到 \lstinline@switch@ 的末尾为止。\par
155+
举个例子,如果上面的代码不加 \lstinline@break@ 的话,程序运行的结果将是这样的\footnote{本书默认:键盘输入的内容用黑体标识,程序输出的内容不用黑体。换行符不单独显示,行末空格和回车也忽略掉。如有特殊情况,会特别说明。}:
156+
\\\noindent\rule{\linewidth}{0.2pt}\texttt{
157157
\textbf{4}\\
158158
four\\
159159
three\\
160160
two\\
161-
one
161+
onefrrrrr
162162
}\\\noindent\rule{\linewidth}{0.2pt}
163-
而加上了 \lstinline@break@ 之后就会得到这样的运行结果:\\\noindent\rule{\linewidth}{0.2pt}\texttt{
163+
而加上了 \lstinline@break@ 之后就会得到这样的运行结果:\pagebreak
164+
\\\noindent\rule{\linewidth}{0.2pt}\texttt{
164165
\textbf{4}\\
165166
four
166167
}\\\noindent\rule{\linewidth}{0.2pt}\par
167-
我们还可以做合并标签的操作,这个效果相当于``如果 \lstinline@<整型数据>@ 匹配了 \lstinline@<字面量1>@ \textbf{或者} \lstinline@<字面量2>@,就从这里开始执行''\par
168+
我们还可以做合并标签的操作,这个效果相当于``如果 \lstinline@<整型数据>@ 匹配了 \lstinline@<字面量1>@ \textbf{或者}\linebreak\lstinline@<字面量2>@,就从这里开始执行''\par
168169
举个例子,某个百分制的成绩根据分数划定等级,90\~{}100分定为A,80\~{}89分定为B,70\~{}79分定为C,60\~{}69分定为D,0\~{}59分定为E。我们可以用 \lstinline@switch@-\lstinline@case@ 结构来实现输入成绩,输出等级的操作。\par
169170
首先思考一下我们该用什么思路。如果直接按照100分制来写 \lstinline@case@ 的话,那么我们要为 \lstinline@score@ (代表分数的整型变量)变量写100个 \lstinline@case@,这个实在太麻烦了。即便考虑到可以用 \lstinline@default@ 来表示60分以下的情况,我们也要为 \lstinline@60@ 及以上的分数写41个 \lstinline@case@。这还不如用 \lstinline@if@-\lstinline@else@ 呢,好歹这种方式可以表示范围。\par
170171
为了简化我们的代码,我们可以取个巧:用 \lstinline@score/10@ 来匹配数据(还记得吗,整型变量的除法是自动截尾的)。这样我们就只需为 \lstinline@6@, \lstinline@7@, \lstinline@8@, \lstinline@9@ 和 \lstinline@10@ 来写 \lstinline@case@ 了。\par

0 commit comments

Comments
 (0)