1. 计算机硬件系统与程序 #
1.1 计算机的组成 #
为了学好 C++ 的课程,需要大家对计算机有深刻的理解。
它们都有一个基本的组成:显示器、键盘、鼠标、主机。
请你想一想,手机,平板等,也符合上面的组成规律吗?
“主机”就是计算机的核心,所以我们需要对“主机”,做一个更加深入的介绍。
下面,是一张“主机”的照片。
笔记本电脑没有主机箱,而是将所有零部件集中在了一块主板上。
一台主机,基本都含有下面几个关键部件:
- CPU
- 内存
- 硬盘
- 显卡
- 网卡
- 声卡
- 电源
1.1.1 CPU #
CPU,中文翻译为“中央处理器”,它是主机的核心,负责“数据运算”,就相当于整个主机的大脑。
CPU 被誉为是人类科学技术的杰作之一。其地位,相当于古埃及人的金字塔、中国古代修建的赵州桥、京杭大运河。
它们都能代表那个时代的科技巅峰。
说到这里,大家肯定要问了,这个 CPU 到底有什么神奇之处呢?
小
CPU 的小,其实是指,芯片内部,两条导线的间隔(业内称为“制程”)。
比如目前主流CPU,比如英特尔和 AMD 的一些处理器(i5 i7 i9等),它的制程就是 14 纳米、10 纳米等,目前最高可以到达 3 纳米,用于苹果公司在2023年推出的M3系列芯片。
这个纳米,大约是头发丝直径的 6 万分之一。
我们再从大到小,感受一下 CPU 的小。
这是从主板上,取下一个 CPU
这是 CPU 的正反面
这是 CPU 里面的样子。中间的粉色物体,就是核心芯片。
这块核心芯片上,集成了上千万个电子元件。
这是芯片加工后的样子。经过切割,就得到每一个小芯片。
快
CPU 的快,主要是指它的运行速度。到底有多块呢?我们用 i++ 来举个例子。
首先,我们可以查看一下自己电脑的 CPU 信息(可以在任务管理器中查看)。
以上图为例,这个 cpu 的主频(base speed) 是 2.6 GHz。这个主频相当于 CPU 的“心跳”。
一般而言,CPU 执行一条指令(比如: i++ )时,需要若干次“心跳”的时间。这个值,我们假设为 10。
那么,我们就可以来算一算,若 i 从 0 开始,然后不断执行 i++。一秒钟后,i 的值是多少。
// 主频 除以 10 2.6 / 10.0 * 10^9 = 2.6 * 10^8 (次)
从这里可以看到,从 0 开始累加,一秒钟后,这个 CPU 可以数到 260 000 000。这是非常快的。远远超过了人类口头数数的速度。
还有那些“超级计算机”,它们的 CPU 运行速度更快!
难
CPU 的难,其实体现在设计和加工两个方面。
设计,主要是指把“人类的逻辑”,转化成“电路的逻辑”,这需要非常专业的技术能力。
加工,主要是指,把设计变成实际的产品,这需要非常专业的加工能力。
就设计方面来说,全球范围内,著名的 CPU 厂商,有英特尔、AMD、ARM、Apple、 等都具有非常深厚的技术积累,都具有芯片的设计能力。
但是,全球的芯片加工能力,只有少数几家公司具备。比如“台积电”、“韩国三星”等。
我们国家,目前已经具有比较强的设计能力,但是我们加工不出来我们自己设计的高级芯片。
这也说明了,我们的中国制造,其实还没有达到真正的世界一流水平。
目前,一些中国的手机厂商,受到国际上芯片巨头的断供威胁。这样的问题,最终还是需要靠你们不断地学习进步,才能解决。
1.1.2 硬盘 #
硬盘就比较简单了。
我们打开电脑,就会看到硬盘的容量显示。
这是我们用来存放文件的。比如音乐、电影、文档等。
它对应的硬件实物,就长这个样子。
1.1.3 内存 #
内存是也是用来存储文件的。不过,它和硬盘的差别在于:
- 硬盘上的文件,断电后,依然保留。
- 内存上的文件,断电后,会丢失。
- 硬盘,可以直接用用户使用。
- 内存,仅供程序使用。内存,对于编程人员而言是非常重要的。
它对应的硬件实物,就长这个样子。
1.1.4 显卡 #
显卡上,有连接显示器的接口,主要是负责连接显示器。
集成显卡(电脑自带):被植入CPU芯片组中的显卡,与CPU共享系统内存。
优点:成本低、功耗低
缺点:性能较差
独立显卡(自行配置):单独的图形处理单元,拥有独立的显存和处理器,不与CPU共享系统内存。
优点:性能好、专业功能多
缺点:成本高、功耗高
如今,显卡变得很重要的一个原因,是因为 AI。
在神经网络的计算中,需要新建大量的线程用于计算。而显卡一个很重要的特点,就是可以很快速的完成多线程计算。
1.1.5 网卡 #
就是上网的接口。电脑能够上网,就是因为主机上插有网卡。
网卡上,有网线的接口。连上网线,就可以使用网络了。
1.2 什么是编程 #
在学习了计算机硬件系统的构成后,让我们思考一下:计算机是怎么完成各种复杂任务的呢?
显然,光靠硬件是不够的,那么我们就要通过编程来向计算机发出指令。
所谓编程,就是“编写”“程序”。
程序是机器的“智慧”,有了“智慧”的机器,就可以完成各种各样的事情。
1.3 我们身边的程序 #
其实程序早已经遍布我们生活的方方面面。
1.4 程序是怎么被创造的 #
我们知道,每一个文字都有它们自己的独立意义。
而它们被人为组合在一起时,又能代表新的含义。
比如下面的这首诗。
我行世间寻真理, 爱此逻辑与奥秘。 编出千般奇幻境, 程中有我意飞扬。
这是一首藏头诗,你发现了吗?:)
而且,这首诗是由 AI 生成的。
现在这么火热的 AI ,其实它的本质,就是一段程序。
我们学习编程,其实是学习一种,让计算机按照我们的意图,进行工作的方法。
下面我们来看一个C++程序的例子,这段程序实现的是一个推箱子的小游戏:
#include <stdio.h> #include <stdlib.h> #include <windows.h> #include <conio.h> int main() { char a[12][12]={"##########", "## ###", "##O #", "# S O O #", "# **# O ##", "##**# ##", "##########", }; int x=3,y=2; int i; char ch; for(i=0;i<7;i++) puts(a[i]); while(a[4][2]!='@'||a[4][3]!='@'||a[5][2]!='@'||a[5][3]!='@') { ch=getch(); if(ch=='s') { if(a[x+1][y]!='#'&&a[x+1][y]!='O'&&a[x+1][y]!='@') //如果只有人,没有箱子 { a[x][y]=' '; x++; a[x][y]='S'; } else if(a[x+2][y]!='#'&&a[x+1][y]=='O'&&a[x+2][y]!='*') //如果是箱子和人一起走 { a[x][y]=' '; x++; a[x][y]='S'; a[x+1][y]='O'; } else if(a[x+2][y]!='#'&&(a[x+1][y]=='O'||a[x+1][y]=='@')&&a[x+2][y]=='*') //如果人和箱子一起走,并且前面是终点 { a[x][y]=' '; x++; a[x][y]='S'; a[x+1][y]='@'; } } if(ch=='w') { if(a[x-1][y]!='#'&&a[x-1][y]!='O'&&a[x-1][y]!='@') //如果只有人,没有箱子 { a[x][y]=' '; x--; a[x][y]='S'; } else if(a[x-2][y]!='#'&&a[x-1][y]=='O'&&a[x-2][y]!='O') //如果是箱子和人一起走 { a[x][y]=' '; x--; a[x][y]='S'; a[x-1][y]='O'; } else if(a[x-2][y]!='#'&&(a[x-1][y]=='O'||a[x-1][y]=='@')&&a[x-2][y]=='*') //如果人和箱子一起走,并且前面是终点 { a[x][y]=' '; x--; a[x][y]='S'; a[x-1][y]='@'; } } if(ch=='a') { if(a[x][y-1]!='#'&&a[x][y-1]!='O'&&a[x][y-1]!='@') //如果只有人,没有箱子 { a[x][y]=' '; y--; a[x][y]='S'; } else if(a[x][y-2]!='#'&&a[x][y-1]=='O') //如果是箱子和人一起走 { a[x][y]=' '; y--; a[x][y]='S'; a[x][y-1]='O'; } else if(a[x][y-2]!='#'&&(a[x][y-1]=='O'||a[x][y-1]=='@')&&a[x][y-2]=='*') //如果人和箱子一起走,并且前面是终点 { a[x][y]=' '; y--; a[x][y]='S'; a[x][y-1]='@'; } } if(ch=='d') { if(a[x][y+1]!='#'&&a[x][y+1]!='O'&&a[x][y+1]!='@') //如果只有人,没有箱子 { a[x][y]=' '; y++; a[x][y]='S'; } else if(a[x][y+2]!='#'&&a[x][y+1]=='O'&&a[x][y+2]!='O') //如果是箱子和人一起走 { a[x][y]=' '; y++; a[x][y]='S'; a[x][y+1]='O'; } else if(a[x][y+2]!='#'&&(a[x][y+1]=='O'||a[x][y+1]=='@')&&a[x][y+2]=='*'&&a[x][y+2]!='O') //如果人和箱子一起走,并且前面是终点 { a[x][y]=' '; y++; a[x][y]='S'; a[x][y+1]='@'; } } if(a[4][2]!='@'&&a[4][2]!='S'&&a[4][2]!='*') { a[4][2]='*'; } if(a[4][3]!='@'&&a[4][3]!='S'&&a[4][3]!='*') { a[4][3]='*'; } if(a[5][2]!='@'&&a[5][2]!='S'&&a[5][2]!='*') { a[5][2]='*'; } if(a[5][3]!='@'&&a[5][3]!='S'&&a[5][3]!='*') { a[5][3]='*'; } if(a[1][2]=='O'||a[1][6]=='O'||a[2][8]=='O'||a[3][8]=='O'||a[5][5]=='O'||a[5][7]=='O') //判断失败的情况 { break; } system("cls"); for(i=0;i<7;i++) puts(a[i]); } system("cls"); if(a[4][2]!='@'||a[4][3]!='@'||a[5][2]!='@'||a[5][3]!='@') printf("YOU LOSE!"); else printf("YOU WIN!"); Sleep(3000); return 0; }
其实,程序也是由一行行的文字组成的。
而且,这些文字,也代表了不同的含义。
将它们组合在一起之后,也包含了不同的意义。
现在大家有了对计算机硬件和程序的基本认识,下面就让我们正式开始学习吧!
2. C++ #
2.1 什么是C++ #
C++是一种计算机高级程序设计语言,由C语言扩展升级而产生,最早于1979年由本贾尼·斯特劳斯特卢普(Bjarne Stroustrup)研发。C++继承了C语言的优点,同时增加了面向对象编程的特性(关于面向对象编程的具体概念,我们将在之后的课程中学习)。C++被广泛地应用于系统软件、应用软件、游戏等领域的开发中。C++也是信息学奥林匹克竞赛指定的程序设计语言。
2.2 搭建学习环境 #
C++开发可以使用Dev-C++、Visual Studio、Visual Studio Code、CLion等软件。
这里我们以Dev-C++为例,Dev-C++是一个Windows环境下的一个适合于初学者使用的轻量级 C/C++ 集成开发环境(IDE)。它是一款自由软件,遵守GPL许可协议分发源代码。它集合了MinGW中的GCC编译器、GDB调试器和 AStyle格式整理器等众多自由软件。
Dev-C++下载地址:https://sourceforge.net/projects/orwelldevcpp/
点击如下箭头所指按钮即可下载:
安装流程:
1、双击“Dev-Cpp 5.11 TDM-GCC 4.9.2 Setup.exe”,之后点击“是”,出现如下界面:
2、选择“English”,点击“OK”,出现如下界面:
3、点击“I Agree”,出现如下界面:
4、点击“Next”,出现如下界面:
5、点击“Install”,进行安装,出现如下界面,点击“Finish”,安装完成并打开DEV C++。
6、选择“简体中文/Chinese”,并点击“Next”。
7、点击“Next”,接着再点击“OK”,完成DEV C++安装。
3. 第一个C++程序 #
3.1 程序的基本结构 #
3.1.1 C++程序结构 #
为了弄清C++的编程规则,首先我们看看C++程序的基本结构。
3.1.2 头文件 #
#include // 引用 iostream 库
include 是“包含”的意思。iostream 是一个库。
所谓的库,就是指其他人事先编写好的代码。
#include 在 C++ 中,就是表示要引用“他人”的事先写好的代码。
在这里,我们主要是要使用 iostream 库中的“输出”语句(cout)。
3.1.3 名字空间(名称空间) #
std::cout << "I love programming." << std::endl;
关于名字空间的详细解释,我们将在后面说明。
这里先简单认识一下“名字空间”的概念。
我们都知道,我们的祖国,幅员辽阔,人口众多。所以,遇到重名的人,并不稀奇。
所以,往往我们会这样来区分它们:
- 上海的小王;
- 北京的小王;
- 广州的小王;
同样的道理,所谓名字空间,其实就是一个名称的补充,表示“小王”来自哪里。
C++ 写法:
- 上海::小王;
- 北京::小王;
- 广州::小王;
符号“::”,就相当于汉语“的”。
cout 是一个输出语句。为了不和其他语句重名,特地放在了 std 这个“名字空间”中。
endl 表示“换行”(此说法不完整,但可以先这么理解,完整说法:endl表示插入一个换行符,并刷新输出缓冲区)。
3.1.4 主函数 #
a. 形式 #
main() { … }
程序是从 main 函数开始的。main 是“主要”的意思。
函数:就是一系列的“代办事项”。就像家里的“购物清单”、“操作步骤”等。
想一想:
把大象装进冰箱,总共分几步?
b. “操作步骤” #
main() { 打开冰箱; 把大象放进去; 关上门; }
main 函数有一对花括号 { }。
“操作步骤”就写在:花括号 { } 内。
c. 返回值 #
int main() { … return 0; }
return 是“返回”的意思。
return 0 一般用于表示 main 函数执行成功,没有错误。它的详细意义,我们在函数一章中讲解。
d. 分号 #
int main() { std::cout << “I love programming.” << std::endl; return 0; }
main 函数里面的一句代码,是以“分号” 结尾的。
- C++ 中,语句是由分号间隔开的
一句语句中,词之间可以有空格。不限数量、不限位置。
把词拆开是不行的。
下面看几个例子:
int main() { std::cout << “I love programming. " << std::endl; // 对 s td::c out << “I love programming." << std::en dl; // 错 std::cout // 一句语句中,可以回车换行 << “I love programming." << std::endl; // 对,而且这是一句代码 return 0; // 对 re turn 0; // 错 }
e. 注释 #
int main() { … return 0; // 成功执行,正常结束,退出程序 }
// 后面是代码的注释。
注释:是写给读者看,起着解释代码的作用。它并不影响代码的功能。
int main() { … /* 我行世间寻真理, 爱此逻辑与奥秘。 编出千般奇幻境, 程中有我意飞扬。 */ return 0; // 成功执行,正常结束,退出程序 }
/* */ 之间的所有内容,包括之间的回车换行,都属于代码的注释。这也被称为段落注释。
而 // 则被称为行注释。
3.2 输出 #
3.2.1 输出的基本用法 #
请运行下面的代码:
#include <iostream> int main() { std::cout << "Hello World!" << std::endl; // 输出字符串(字符串:就是指文字) std::cout << 1 << 2 << 3 << std::endl; // 输出数字 std::cout << "Hello " << 2 << std::endl; // 输出字符串和数字 // 格式化输出 std::cout << "现在的温度是:" << -26.5 << "摄氏度" << std::endl; std::cout << "现在的坐标是:(" << 0.5 << ", " << -9 << ")" << std::endl; std::cout << "现在的时间是:" << 15 << ":" << 30 << std::endl; return 0; }
以上的代码中,我们介绍了最基本的 C++ 输出形式。
3.2.2 使用名称空间 #
另一种常见的写法如下:
#include <iostream> using namespace std; // 使用名称空间 std。有了这句话之后,cout 就会自动被识别为 std::cout int main() { cout << "Hello World!" << endl; // 省略 std:: return 0; }
在这种写法中,我们使用了新的语句:
using namespace std;
这句话的意思是:使用 名称空间 std。
有了这句话之后,cout 就会自动被识别为 std::cout 。从而就可以在书写中,省略 std:: 。