作者 谢恩铭 转载请注明出处
公众号「程序员联盟」(微信号:ProgrammerLeague )
原文:https://www.jianshu.com/p/d44bd24ce6af
《C++探索之旅》全系列
内容简介
- 前言
- 命令行的奇幻世界
- 创建第一个项目
- 解释第一个项目
- 注释及代码整洁之道
- 总结
- 第一部分第四课预告
1. 前言
经过上两课 C++探索之旅 | 第一部分第一课:什么是C++ 和 C++探索之旅 | 第一部分第二课:C++编程的必要软件 之后,我们已经知道了什么是编程,编程的语言,编程的必要软件,C++ 是什么。
我们也安装了适合自己的 IDE(Integrated Development Environment,就是「集成开发环境」的意思)。
除了使用 IDE 之外(IDE 集成了文本编辑器,编译器,调试器,运行程序,等),也可以选择另一种难一些的方式:自己用某一种文本编辑器来编写 C++ 代码,用 g++( C++ 的编译器)来编译程序,然后用命令行来运行程序。
推荐几个不错的文本编辑器:Vim,Emacs,Sublime Text,Atom,VS Code,等。
以上几个文本编辑器,我都用过。Sublime 只用了一会,Vim 和 Emacs 用得比较多,Atom 也不错,微软出的 VS Code 也挺好。
我以前写了一篇专门介绍 Emacs 的文章, Emacs,最强编辑器,没有之一 。关于 Vim 的文章,请参看我的 Linux探索之旅 | 第五部分第一课:Vim岂是池中物,宝剑锋从磨砺出 。
这一课我们就来介绍命令行程序,用 IDE 或 文本编辑器编写第一个 C++ 程序,以及讲解 C++ 程序的基本原理吧。
2. 命令行的奇幻世界
这个标题是不是有点玄乎:命令行还有奇幻可言?什么是命令行?
我们会一一解释。
也许说起编写第一个程序,大家会很激动,期待干一番大事业。
但是,遗憾的是,我们这一课可不会带大家开始编写《星际争霸》这样的游戏(当然我的实力也远远够不上... 那需要一个专业团队耗费很多年才能完成),也不会来写一个浏览器,或者视频播放器,等。
我们会「慢条斯理」地前进,因为我们要做到的是「踏实」,因为即使是编写《星际争霸》的暴雪团队中的编程精英,也是从最基础的编程知识学起的。
首先,我们说一说什么是命令行程序。
我们需要知道,有两种类型的程序:命令行程序 和 图形界面程序。
图形界面程序
简单来说,图形界面程序就是“显示窗口的程序”。
有过 Windows 使用经验的朋友肯定对这样的程序不陌生,因为就连微软的 Windows 操作系统的「Windows」(window 是英语 “窗、窗户” 的意思,windows 是 window 的复数)这个英语单词的意思就是「视窗」,Windows 操作系统其实应该翻成“视窗操作系统”。
所以我们平时也就是在操作形形色色的「窗口」,比如 Chrome 浏览器,火狐浏览器,QQ,微信,迅雷,暴风影音播放器,大家想想,是不是这些程序都有一个「窗口」作为最外边的框架?我们可以打开窗口,关闭窗口,调节窗口大小,操作窗口内部的按钮,等等。
这样的程序,专业术语叫做「GUI」程序。GUI 是 Graphic User Interface 的首字母缩略词,也就是「图形用户界面」的意思。
例如下图中,我们可以看到我们所熟知的 Office Word 软件:
命令行程序
注意:真正的命令行界面应该是完全没有图形的,就是一个只能输入命令,而且通常是黑色背景,白色字体的「大黑洞」。
我们以下举例的时候所说的命令行程序,其实大多是在图形界面内创建一个窗口,此窗口内就像是命令行界面的屏幕一样,通常称为「终端」(Terminal)。
在 Unix 或者 Linux 系统下(可以看我的另一个系列教程 Linux探索之旅 ),命令行程序相对 Windows 和 macOS 来说用得更多一些。
Windows 里面也有命令行程序,就是大家可能使用过的 cmd.exe 程序(在 Windows 下按 “Windows 键(键盘左下角有微软图标的按键)+ 字母键 R ”, 然后输入 cmd,回车,就可以调出),它其实是微软 的 Windows 系统基于 Windows 上的命令解释程序,类似于微软的 DOS 操作系统。如下图:
macOS 里也有 Unix 范式的命令行解释器:
看了 Windows 和 macOS 下的命令行程序,再来看一下我们 Linux(用 Ubuntu 这个 Linux 发行版来做例子)的命令行程序:
虽说终端或者命令行界面看起来比图形界面「难看」,大家会说「土啊」...
但是不可讳言,命令行程序是有其独到的优势的。毕竟这年头,大家都喜欢「高颜值」的图形界面程序么。
如果命令行没点绝活,哪能受到我们程序员的青睐。命令行有如下优势:
可实现图形界面不具有的功能:Linux 的很多程序是面向命令行的,没有图形前端,只能用命令行使用。
可使用超级用户权限:一些需要超级用户权限的操作只能在命令行下运行。
高效快速:可借助正则表达式实现批量处理,还能向程序发送参数。
安全性高:可减少因错误操作或者权限问题导致的风险。
很多程序员要的就是这个 feel,倍儿爽~
命令行程序中,我们只能使用键盘输入命令,鼠标一般是没什么作为的。文字信息是按从上到下,从左到右的顺序显示。
我们的首期目标:命令行程序
我们将从命令行程序开始,一点点学习 C++ 的各样知识点。
我知道,虽然扫了在座各位的兴致,命令行界面颜值不够高,但是相对图形界面却更容易创建,特别对于初学编程的朋友来说。
当然了,之后的课程我们可以在学习完了 C++ 的基本知识点后,用 Qt 这个 C++ 库来编写图形界面的程序,会有很多好玩的程序等待我们去实现。
这就好比,如果中国共产党没有经过农村包围城市,从基层(命令行程序)做起的话,又怎么能有后来恢宏的开国大典(图形界面程序)上毛主席的慷慨陈词呢?
不过大家也不要怕,我们并不需要经过艰苦卓绝的「八年抗战」才能够资格编写图形界面的程序。
好了,说了这么多“废话”,我们可以正式开始 C++ 编程了。
3. 创建第一个项目
在上一课 C++探索之旅 | 第一部分第二课:C++编程的必要软件 中,我们演示了三个主流 的 C/C++ 编程 IDE :
CodeBlocks (跨平台。Linux,Windows,macOS 等操作系统都可以)
Visual Studio (简称 VS,只能运行在 Windows 操作系统里)
XCode (只能运行在 macOS 操作系统里)
当然了,免费开源的 Eclipse 也有适合 C++ 开发的 IDE:Eclipse CDT。CDT 是 C/C++ Development Tooling 的缩写,表示 “C/C++ 开发工具”。不过,Eclipse 需要有 Java 环境才能运行,需要配置 Java 开发环境。我们本课就不演示了,大家可以自己上网找 Eclipse CDT 安装和环境配置的教程。
上一课里我们演示了如何用 CodeBlocks 和 XCode 创建一个 C++ 项目,没有演示如何用 VS 创建 C++ 项目,那么这一课就来演示如何在 Visual Studio 中创建第一个 C++ 项目,并编译运行。
之后再演示不使用 IDE,而纯使用 g++ 命令(对于 Linux 下的用户来说,最好使用这个方式,比用 IDE 可以学到更多东西)来编译,并用命令行来运行。
Visual Studio 创建 C++ 项目
我是在 Win7 系统下用 Visual Studio 2012 来演示。其他版本的 VS,可能菜单的命名或某些选项窗口会不一样,但基本操作应该是类似的。
首先,新建一个项目,有两种方法,你可以在初始打开 VS 时,点击如下图中的「新建项目」:
或者(比较提倡这种方法,因为不一定每次创建新项目都是刚打开 VS 时)选择 “文件->新建->项目” :
用以上两种方式,都可以调出以下窗口:
选择默认的 Visual C++ 的 Win32 控制台程序就好了,项目名字可以不改,不过我这里改成了 HelloWorld。点击「确定」,可以看到下图:
点击「下一步」,出现下图:
不需要修改,默认配置就好,点击「完成」。我们的项目就创建好了:
可以看到我们的主要的文件:HelloWorld.cpp
Windows 生成的 main 函数名字和一般的不太一样,叫 _tmain。反正和我们平时的 main 函数是类似的。
我们添加我们需要的代码,之后完整的代码是这样:
// HelloWorld.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
// 在屏幕上显示"Hello World!"
cout<<"Hello World!"<
至此,我们的主要程序就写好了。我们来编译运行吧。
首先,编译代码。点击 生成->生成解决方案 (也可以按快捷键 F7):
稍等片刻,VS 的下方会显示:
显示「生成:成功」,则表示我们的程序编译成功了。
接下来运行程序,点击 调试->开始执行(不调试)(也可以按 Ctrl + F5):
程序运行的结果是输出「Hello World!」,如下图:
通过简单的几个步骤、短短的几行代码,就创建了我们的第一个 C++ 程序,并实现了「Hello World! 」输出。用 C++ 编程就这么简单!
命令行创建 C++ 项目
看过了用 IDE 来创建 C++ 程序的实例,我们来学习一下对于初学者,特别是没接触过 Linux(一个操作系统,现在主流的操作系统有 Windows,macOS 和 Linux)命令行的朋友来说比较复杂的方式。如果您完全没有 Linux 或 Unix 基础,可以跳过此节,就用 IDE 也行。当然你也可以通过百度一些知识来完成这一节。
首先,把之前的主要程序用文本编辑器(随便你用那个文本编辑器,Nano,Gedit,Vim,Emacs,Sublime Text,Atom,VS Code 等)编写,然后保存为 HelloWorld.cpp这个文件。
#include
using namespace std;
int main() {
cout << "Hello world!" << endl;
return 0;
}
然后,我们在 Linux 系统下启动终端(Terminal),一般可以在“应用->附件->终端”,点击启动。
或者像 Ubuntu 这样的 Linux 发行版,可以同时按 Ctrl + Alt + T 这三个键来快捷启动终端,终端是长这个样子的:
下面演示的命令,是在 Ubuntu 系统下执行的:
- 安装 g++ 编译器(用于编译 C++ 程序):
sudo apt-get install g++
- 进入 HelloWorld.cpp 这个文件所在的目录:
cd "HelloWorld.cpp 这个文件所在的路径"
我的 HelloWorld.cpp 文件就存放在家目录下,所以直接用 cd ~
就可以。
如果不了解 cd 命令,可以参看我的 Linux探索之旅 | 第二部分第三课:文件和目录,组织不会亏待你。
- 编译程序:
g++ HelloWorld.cpp -o HelloWorld
上面的 -o 参数里的 o 是表示 output(英语“输出”的意思),就是说“用 g++ 编译 HelloWorld.cpp 这个 C++ 文件,生成的可执行程序名字是 HelloWorld”。
- 运行程序:
./HelloWorld
如果你在第 3 步编译的时候不用 -o 参数来指定生成的可执行程序名字,g++ 会为你设置一个默认的名字,可能会叫 a.out。如下图所示:
4. 解释第一个项目
虽然我们创建了一个项目,但是这个项目很简单,只有一个主要文件,就是 HelloWorld.cpp,它的主要内容如下:
#include
using namespace std;
int main() {
cout << "Hello World!" << endl;
return 0;
}
对于第一次接触编程的朋友,可能这个最基础的代码也是难以理解。
所以我们才要一起来学习如何阅读这段代码。
先从第一行开始吧:
#include
这一行很特别,我们会在源代码开头的地方见到这样的以 # 号开头的语句。像这样特别的行,称为「预编译指令」。
这个术语听起来有点复杂。预编译指令会在编译开始的时候,被一种叫做「预编译器」的程序所读取。
其实编译器为我们做很多事情,我们之后的课程会详细来说明。
但是这一行到底是什么意思呢?
这里的 # 号是预编译指令开始的标志,没有什么特别的含义,后面接着的 include 是英语「包含」的意思,所以这句话的意思就是在我们的程序里包含 iostream 这个文件,这个文件在 C++ 的系统的库里已经存在了,这些文件被称为 库文件 。
iostream 是英语「Input Output Stream」(输入输出流)的简称。通常,电脑的输入流是键盘和鼠标,输出流是屏幕。
所以 iostream 这个标准库头文件里面就定义了操作输入输出流相关的所有函数等。
之后的课程,当我们要编写图形界面程序时,我们会使用 Qt 这个 C++ 的第三方库。而我们会在程序里引入 Qt 这个头文件的内容,如下:
#include
当然了,我们每次可以 include 好多个头文件。
命名空间:namespace
接着我们看到第二句话:
using namespace std;
这又是什么呢?
我们来介绍一下命名空间(namespace)的概念:
命名空间告诉编译器去哪里找我们所调用的东西。
听着有点晕?命名空间有什么用呢?
例如,你用 #include 语句引入了好多个库,而这些库里有的函数是重名的。假设在 iostream 库中我们定义了 DoSomething 这个函数,而在 Qt 这个第三方库中也定义了相同名字的函数,也叫 DoSomething。那编译器就不知道用哪个库里面所定义的 DoSomething 函数了。
using 是英语「使用」的意思,所以这句话的意思就是「使用 std 命名空间的东西」。
std这个命名空间是很常用的,因为它指明了“标准命名空间”(std 是英语「标准」(standard)的简写)。我们的 iostream 就是属于 std 命名空间的。
接着,我们看到了下面的语句:
int main() {
cout << "Hello World!" << endl;
return 0;
}
以上我们所看到的语句块,被称为函数。其实 C++ 语言的程序基本就是由函数来构成的。目前我们的程序只有一个函数。
我们现在还不会讲很多函数的细节,因为那是后面的【函数】那一课的内容,现在还早。但是我们会大体说一下函数的组成。
第一行包含了函数的名字,是第二个单词:main。main 是英语“主要的”的意思,所以这里的函数称为 main 函数,也就是 主函数。main 函数是一个特殊的函数,C++ 的程序执行总是从 main 函数开始。
一个函数有开始和结束,使用大括号 {} 来标识。所以我们的 main 函数包含以下两行代码
cout << "Hello World!" << endl;
return 0;
这些在函数里的行也有名字,被称为「指令」。每一条指令都会让电脑做特定的事情。一个函数大体来说是用来集中一定数目的指令。比如我们可以创建一个函数叫做「打开文件」,这个函数会让电脑为你打开某个文件。
函数的优势就是当你写好了这个函数之后,你只需要使用(专业术语叫做 「调用」)「打开文件」这个函数,电脑就会为你执行函数里面的指令。你不需要每次在要实现「打开文件」功能的地方都重复写那些指令。
函数可以大大节约代码空间,增加利用率,提高效率。
这一行指令
cout << "Hello World!" << endl;
使得屏幕显示「Hello World!」这一句话。
它由三部分组成:
- cout :在标准输出(此处是屏幕)上显示信息
- "Hello World!" :要显示的内容
- endl :表示换行
当你的程序执行到这一行时,就在屏幕上显示相应的信息,然后换行。
cout 类似 C 语言的 printf 函数,是 C++ 里面负责标准输出的。不过又有不同,我们可以看到 cout 后面不是加括号,而是连接了 << 这个特殊的符号。
暂时我们不深入,因为 cout 其实不是一个函数,cout 是一个 ostream 类的对象(关于类和对象,我们之后的课程会讲解),它有一个成员运算符函数 operator<< (涉及到 C++ 的运算符重载的技术,以后的课程会讲)。(这一句指令暂时不需要理解,只需要知道这句话的作用)。
cout 的定义是在 iostream 库的 std 命名空间中,现在你知道
#include
using namespace std;
这两句话的重要性了吧?如果没有引入 iostream 这个库并且不指明使用哪个命名空间的话,那我们的 main 函数就不能调用 std 的 cout。
假如你没加
using namespace std;
这一句话,那么调用 cout 时须要加上 std:: 这样的前缀:
#include
int main() {
std::cout << "Hello World!" << endl;
return 0;
}
第二个指令
return 0;
大体上说来就是表示函数结束了,并且返回 0 值。return 是英语“返回”的意思。
为什么我们的 main 函数返回 0,而不是返回其他值呢?
实际上,每个 C++ 语言的程序结束时都会返回一个值,0 表示一切正常结束,其他的值表示异常。
这里我们只是简单介绍了函数的概念。关于函数的细节请看之后的课程。
5. 注释及代码整洁之道
在结束这一课前,我们必须再来讲一下 注释。不论什么编程语言,我们都可以在源代码里添加注释。C++ 语言当然不例外。
注释,到底是什么啊 ?
简单地说,注释就是在你程序之中用来标注这个程序的作用,某一行代码的作用等等的文字。注释真的很重要,因为即使是一个计算机天才,也要在程序中做一些注解。
注释有如下作用:
在之后阅读自己写的代码时不至于迷失方向。不可否认,在重新阅读之前写的代码时,我们常常会忘记这个函数是干什么的,那个地方为什么要这样写。特别是代码量很大,几千几万行甚至更多时,如果没有注释,那阅读起来会很费力。
如果你把你的代码给别人阅读,注释可以节省对方理解你的代码的时间
要在代码中插入注释,有几种形式:
如果你的注释比较短,在一行里就能写完,那可以用 //... 这样的形式
如果你的注释跨越好几行,那可以用 /* ... */ 的形式
我们可以对之前的代码添加注释,变成如下:
#include // 引入 iostream 这个库 (为了使用 cout)
using namespace std; // 指明要使用的命名空间
/*
主函数 main
所有的 C++ 程序都从 main 函数开始
*/
int main() {
cout << "Hello, World!\n" << endl; // 在屏幕上显示 "Hello, World!",并且换行
return 0; // 结束 main 函数,也就是结束程序
}
可以看到,虽然程序行数变多了,但注释却使我们的代码变得易读很多。
编译代码的时候,编译器会忽略所有的注释。这些注释不会出现在最终的程序里,只是为程序员自己和阅读程序的其他人服务的。
记住:
注释要起到引导阅读代码的作用,以便理清头绪。但是不要在太过浅显易懂的地方添加注释。
引用 IBM 公司的一句格言:
《如果一个程序,在你仅仅看完它的注释之后,你不能了解它的作用,那么把这个程序扔了吧》
-- 大公司就是这么严格,这么任性。
代码整洁之道
其实我们的程序完全可以写成这样,也是正确的,可以编译运行,输出「Hello World!」
#include
using namespace std; int main()
{
cout << "Hello world!"<< endl; return 0; }
因为编译器并不介意你的程序是不是「规范」。
但这样的程序问题是什么呢?
「乱七八糟」,可以这么形容。因为这样的程序风格使得别人很不容易阅读你的代码,甚至过了一段时间可能你自己也会摸不着头脑。
如果你去面试,写出这样的程序,那九成是不会被录取的。除非你参加「国际 C 语言乱码大赛(IOCCC)」。
所以一开始就养成良好的代码风格是很重要的。
推荐大家去看林锐编写的 《高质量 C++/C 编程指南》 。
其实我个人更喜欢直接参考 Google 公司的 C++ 代码规范:https://google.github.io/styleguide/cppguide.html
6. 总结
有两种程序:命令行程序 和 图形界面程序。
刚开始学编程,实现命令行程序更简单。所以我们从命令行程序开始学习。
一个 C++ 程序总是有 main 函数:这是程序运行的入口。
cout 可以在屏幕上显示信息。
我们可以给程序添加注释,以详述其作用。C++ 中的注释有两种形式:
// 注释
或者/* 注释 */
。
7. 第一部分第四课预告
今天的课就到这里,一起加油吧!
下一课我们学习:
我是 谢恩铭,软件工程师,慕课网精英讲师 Oscar 老师,终生学习者。
热爱生活,喜欢游泳,略懂烹饪。
人生格言:「向着标杆直跑」