跳转至

第一章 开始

学习一门新的程序设计语言的最好方法就是练习编写程序。


编写一个简单的C++程序

每个C++程序都包含一个或多个函数(function),其中一个必须命名为main。操作系统通过调用main来运行C++程序。

下面是一个简单的main函数,它什么都不做,只是返回给操作系统一个值:

int main()
{
    return 0;
}

main函数的返回类型必须为int。int类型是一种内置类型(built-in type),即语言自身定义的类型。

函数体是一个以左花括号(curly brace)开始,以右花括号结束的语句块(block of statements)。

return语句结束函数的执行。main的返回值被用来指示状态。返回值0表明成功,非0的返回值的含义由系统定义,通常用来指出错误类型。

重要概念:类型

一种类型不仅定义了数据元素的内容,还定义了这类数据上可以进行的运算。程序所处理的数据都保存在变量中,而每个变量都拥有自己的类型。

编译、运行程序

编写好程序后,我们就需要编译它,这依赖于操作系统和编译器。

程序源文件命名约定

程序文件通常被称为源文件(source file)。它以一个后缀为结尾,告诉系统这个文件是一个C++程序,比如.cpp。

初识输入输出

C++包含了一个全面的标准库(standard library)来提供IO机制(以及很多其他设施)。

iostream库包含两个基础类型istream和ostream,分别表示输入流和输出流。一个流就是一个字符序列,是从IO设备读出或写入IO设备的。

标准输入输出对象

标准库定义了4个IO对象。为了处理输入,使用名为cin的istream类型的对象。这个对象被称为标准输入(standard input)。对于输出,使用名为cout的ostream类型的对象。这个对象被称为标准输出(standard output)。另外还有其他两个ostream对象,名为cerr和clog,cerr通常用来输出警告和错误消息,因此被称为标准错误(standard error)。clog用来输出程序运行时的一般性消息。

系统通常将程序所运行的窗口与这些对象关联起来。因此,当读取cin,数据将从程序正在运行的窗口读入,当向cout写入数据时,将会写到同一个窗口。

Note

clog关联到标准错误,默认情况下,写到clog的数据是被缓冲的。写到cerr的数据是不缓冲的。

一个使用IO库的程序

#include <iostream>
int main()
{
        std::cout << "Enter two numbers:" << std::endl;
        int v1 = 0, v2 = 0;
        std::cin >> v1 >> v2;
        std::cout << "The sum of " << v1 << " and " << v2 << " is "
                  << v1 + v2 << std::endl;
        return 0;
}

#include <iostream>告诉编译器我们想要使用iostream库。尖括号中的名字指出了一个头文件(header)。每个使用标准库设施的程序都必须包含相关的头文件。#include指令和头文件的名字必须写在同一行中。#include指令一般出现在所有函数之外,源文件的开始位置。

向流写入数据

std::cout << "Enter two numbers" << std::endl;

这条语句执行了一个表达式(expression)。在C++中,一个表达式产生一个计算结果,它由一个或多个运算对象和(通常是)一个运算符组成。这条语句中的表达式使用了输出运算符(<<)。

<<运算符接受两个运算对象:左侧必须是一个ostream对象;右侧是要打印的值。此运算符将给定的值写到给定的ostream对象中。计算结果是左侧的ostream对象。

"Enter two numbers"是一个字符串字面值常量(string literal),它是用一对双引号包围的字符序列。

endl是一个被称为操纵符(manipulator)的特殊值。写入endl的效果是结束当前行,并将与设备关联的缓冲区(buffer)中的内容刷到设备中。

Note

一个表达式接一个分号就是一条语句。

使用标准库中的名字

前缀std::指出名字cout和endl是定义在名为std命名空间(namespace)中的。

命名空间可以帮助我们避免不经意的名字定义冲突。标准库定义的所有名字都在命名空间std中。

从流读取数据

首先定义两个名为v1和v2的变量(variable)来保存输入:

int v1 = 0, v2 = 0;

这两个变量被定义为int类型,并初始化(initialize)为0。初始化一个变量,就是在变量创建的同时为它赋予一个值。

std::cin >> v1 >> v2;

这条语句读入输入数据。输入运算符(>>)接受一个istream作为其左侧运算对象,接受一个对象作为其右侧运算对象。它从给定的istream读入数据,并存入给定对象中。输入运算符返回其左侧运算对象作为计算结果。

注释简介

注释(comments)通常用于概述算法,确定变量的用途,或者解释晦涩难懂的代码段。编译器会忽略掉注释,因此注释对程序的行为和性能不会有任何影响。

C++中注释的种类

C++中有两种注释:单行注释和界定符注释。

注释界定符不能嵌套

界定符对形式的注释是以/*开始,以*/结束的。因此,一个注释不能嵌套在另一个注释之内。

如果在调试期间要注释掉包含界定符对形式注释的代码,最好的方式是用单行注释方式注释掉代码段的每一行。

// /*
//  * comments
//  */

控制流

语句一般是顺序执行的,语句块的第一条语句首先执行,然后是第二条,以此类推。但程序设计语言提供了多种不同的控制语句,允许我们写出更为复杂的执行路径。

while语句

while语句反复执行一段代码,直到给定条件为假为止。

while语句的形式为:

while (condition)
    statement

while语句的执行过程是交替地检测condition条件和执行关联的语句statement,直至condition为假时停止。所谓条件就是一个产生真或假的结果的表达式。

statement可以是语句块,也叫循环体。所谓语句块(block),就是用花括号包围的语句序列。语句块也是语句的一种,在任何要求使用语句的地方都可以使用语句块。

for语句

每个for语句都包含两部分:循环头和循环体。循环头控制循环体的执行次数,它由三部分组成:一个初始化语句(init-statement)、一个循环条件(condition)以及一个表达式(expression)。

比如:

for (int val = 1; val <= 10; ++val)
    sum += val;

for循环的总体执行流程:

  1. 创建变量val,将其初始化为1,它仅在循环内部存在。

  2. 检测val是否小于等于10。如果检测成功,执行循环体。若失败,退出循环。

  3. 将val的值增加1。

  4. 重复第二个步骤。

读取数量不定的输入数据

使用这样的方法连续读入数据,直到遇到文件尾(Linux下,输入CTRL+D):

while (std::cin >> value)
    statement

输入运算符返回其左侧对象,因此,此循环条件检测的是std::cin。

当使用一个istream对象作为条件时,其效果是检测流的状态。如果流是有效的,那么检测成功。当遇到文件结束符(end-of-file),或遇到一个无效输入时,istream对象的状态会变为无效。

if语句

if也对一个条件求值,书本里有一个完整的例子。

语法大致如此:

if (condition) {
    statements
} else {
    statements
}

类简介

在C++中,通过定义一个(class)来定义自己的数据结构。一个类定义了一个类型,以及与其关联的一组操作。

类似使用标准库设施,我们也需要使用头文件来自己的类。习惯上,头文件根据类名来命名,使用.h作为头文件的后缀。标准库的头文件通常不带后缀。

初识成员函数

什么是成员函数?

有这样的检测条件:

item1.isbn() == item2.isbn()

调用名为isbn的成员函数(member function)。成员函数是定义为类的一部分的函数。

使用点运算符(.)来表达我们需要“名为item1的对象的isbn成员”。点运算符只能用于类类型的对象。其左侧运算对象必须是一个类类型的对象,右侧运算对象必须是该类型的一个成员名,运算结果为右侧运算对象指定的成员。

我们使用调用运算符(())来调用一个函数,它是一对圆括号,里面放实参列表(可能为空)。