《C++ Primer》第一章 开始
目录
1.1 编写一个简单的C++程序
每个C++程序都包含一个或多个函数( function),其中一个必须命名为main
。系统通过调用 main
函数来运行C++程序。main
函数的返回类型必须为int,即整数类型。
一个函数的定义包含四部分:返回类型
(returm type)、函数名
(function name)、一个括号包围的形参列表
(parameter list,允许为空)以及函数体
(function body)。
int main() {
return 0;
}
当return
语句包含一个值时,返回值类型必须与函数返回类型相同。在大多数系统中,main 的返回值被用来指示状态。返回值0表明成功,非0的返回值的含义由系统定义,通常用来指出错误类型。
很多PC机上的编译器都具备集成开发环境( Integrated Developed Environment, IDE)
,将编译器与其他程序创建和分析工具包装在一起。大部分编译器,包括集成IDE的编译器,都会提供一个命令行界面。
程序文件通常被称为源文件(source file)
。在大多数系统中,源文件的名字以一个后缀为结尾,后缀是由一个句点后接一个或多个字符组成的。后缀告诉系统这个文件是一个C++程序。不同编译器使用不同的后缀命名约定,最常见的包括. cc、. cxx、.cpp、.cp及.C。
1.2 初识输入输出
C++语言并未定义任何输入输出(IO)语句,反而包含了一个全面的标准库(standard library)
来提供IO机制(以及很多其他设施)。
iostream库
包含两个基础类型istream
和ostream
,分别表示输入流和输出流。一个流就是-一个字符序列,是从IO设备读出或写入IO设备的。术语“流”(stream)想要表达的是,随着时间的推移,字符是顺序生成或消耗的。
标准库定义了4个IO对象:
为了处理输入,使用cin
(发音为see-in)的istream类型的对象。这个对象也被称为标准输入(standard input)。
对于输出,使用cout
(发音为ssee-out) 的ostream类型的对象。此对象也被称为标准输出(standard output)。
通常用cerr
(发音为see-err)的ostream类型的对象来输出警告和错误消息,因此它也被称为标准错误(standard error)。
而clog
(发音为see-log)的ostream类型的对象用来输出程序运行时的一般性信息。
通过使用IO库,我们可以扩展main程序,使之能提示用户输入两个数,然后输出它们的和,代码如下:
#include<iostream>
using namespace std;
int main() {
//std::cout << "请输入两个数字" << std::endl;
cout << "请输入两个数字" << endl;
int a;
int b;
cin >> a >> b;
cout << "a = " << a << " b = " << b << endl;
cout << "a + b = " << a+b << endl;
return 0;
}
程序的第—行#include <iostream>
告诉编译器我们想要使用iostream库。尖括号中的名字(本例中是iostream)指出了一个头文件(header)
。每个使用标准库设施的程序都必须包含相关的头文件。#include指令和头文件的名字必须写在同一行中。通常情况下,#include指令必须出现在所有函数之外。我们一般将一个程序的所有#include指令都放在源文件的开始位置。
第二个运算符打印endl
,这是一个被称为操纵符(manipulator )的特殊值。写入endl的效果是结束当前行,并将与设备关联的缓冲区(buffer) 中的内容刷到设备中。缓冲刷新操作可以保证到目前为止程序所产生的所有输出都真正写入输出流中,而不是仅停留在内存中等待写入流。
程序员常常在调试时添加打印语句。这类语句应该保证“一直”刷新流。否则,如果程序崩溃,输出可能还留在缓冲区中,从而导致关于程序崩溃位置的错误推断。
前缀std::
指出名字cout和endl是定义在名为std的命名空间(namespace)
中的。命名空间可以帮助我们避免不经意的名字定义冲突,以及使用库中相同名字导致的冲突。标准库定义的所有名字都在命名空间std中。通过命名空间使用标准库有一个副作用:当使用标准库中的一个名字时,必须显式说明我们想使用来自命名空间std中的名字。例如,需要写出std: :cout,通过使用作用域运算符(::)
来指出我们想使用定义在命名空间std中的名字cout。
1.3注释简介
C++中有两种注释:单行注释和界定符对注释。
单行注释以双斜线(//)
开始,以换行符结束。另一种注释使用继承自C语言的两个界定符(/*和*/)
。注释界定符可以放置于任何允许放置制表符、空格符或换行符的地方。当注释界定符跨越多行时,最好能显式指出其内部的程序行都属于多行注释的一部分。
程序中通常同时包含两种形式的注释。注释界定符对通常用于多行解释,而双斜线注释常用于半行和单行附注。
1.4控制流
语句一般是顺序执行的。语句块的第一条语句首先执行,然后是第二条语句,依此类推。
while
语句反复执行一段代码,直至给定条件为假为止。用while语句编写一段程序,求1到10这10个数之和,代码如下:
#include<iostream>
using namespace std;
int main() {
int sum = 0;
int number = 1;
while (number <= 10) {
sum += number;
number++;
}
cout << "1到10的数字之和为" << sum << endl;
return 0;
}
这个程序的内容是while
语句。while 语句的形式如下:
while (condition)
statement
while
语句的执行过程是交替地检测condition条件和执行关联的语句statement,直至condition为假时停止。所谓条件(condition) 就是一个产生真或假的结果的表达式。只要condition为真,statement 就会被执行。当执行完statement,会再次检测condition。 如果condition仍为真,statement再次被执行。while语句持续地交替检测condition和执行statement,直至condition为假为止。
使用for
语句重写从1加到10的程序,代码如下:
#include<iostream>
using namespace std;
int main() {
int sum = 0;
for (int i = 1; i <= 10; i++) {
sum += i;
}
cout << "1到10的数字之和为" << sum << endl;
return 0;
}
每个for
语句都包含两部分:循环头和循环体。循环头控制循环体的执行次数,它由三部分组成,一个初始化语句
(init-statement)、 一个循环条件
(condition) 以及一个表达式
(expression)。初始化语句只在for循环入口处执行一次。循环体每次执行前都会先检查循环条件。表达式在for循环体之后执行。循环持续这一过程直至循环条件为假。
将1至10相加扩展为读取数量不定的输人数据之和,在这种情况下,预先不知道要对多少个数
求和,这就需要不断读取数据直至没有新的输入为止,代码如下:
#include<iostream>
using namespace std;
int main() {
int sum = 0;
int number = 0;
cout << "请输入需要相加的数字" << endl;
while (cin >> number) {
sum += number;
}
cout << "输入数字之和为" << sum << endl;
return 0;
}
当使用一个istream对象作为条件时,其效果是检测流的状态。如果流是有效的,即流未遇到错误,那么检测成功。当遇到文件结束符
(end-of-file), 或遇到一个无效输入
时(例如读入的值不是一个 整数),istream 对象的状态会变为无效。处于无效状态的istream对象会使条件变为假。
因此,while循环会一直执行直至遇到文件结束符 (或输入错误)。while 循环体使用复合赋值运算符将当前值加到sum上。一旦条件失败, while循环将会结束。然后执行下一条语句,打印sum的值和一个endl。
当从键盘向程序输入数据时,对于如何指出文件结束,不同操作系统有不同的约定。在Windows系统中,输入文件结束符
的方法是敲Ctrl+Z(按住Ctrl键的同时按Z键),然后按Enter或Retun键。在UNIX系统中,包括MacOSX系统中,文件结束符
输入是用Ctrl+D。
与大多数语言一样, C++也提供了if
语句来支持条件执行。用if
语句写一个程序,来统计在输入中每个值连续出现了多少次,代码如下:
#include<iostream>
using namespace std;
int main() {
// currVal是我们正在统计的数;我们将读入的新值存入val
int currVal = 0,val = 0;
if ( cin >> currVal) {
int cnt = 1;//保存我们正在处理的当前值的个数
while ( cin >> val) { // 读取剩余的数
if (val == currVal) //如果值相同
++cnt;//将cnt加1
else {//否则,打印前一个值的个数
cout << currVal << "occurs "<< cnt << "times"<< endl ;
currVal = val; // 记住新值
cnt = 1;//重置计数器
}
}
//记住打印文件中最后一个值的个数
cout << currVal <<"occurs"<< cnt << " times" << endl;
}
return 0;
}
1.5 类简介
在C++中,我们通过定义一个类(class)
来定义,自己的数据结构。一个类定义了一个类型,以及与其关联的一组操作。类机制是C++最重要的特性之一。实际上,C++最初的一个设计焦点就是能定义使用上像内置类型一样自然的类类型( class type)
。
下面的程序从标准输入读入数据,存入一个Sales_ item对象
中,然后将Sales_ item的内容写回到标准输出,代码如下:
#include <iostream>
#include "Sales_item.h"//包含该自定义类的头文件
using namespace std;
int main (){
Sales_item book;//创建一个该自定义类的对象,名为book
cin >> book;//读入ISBN号、售出的册数以及销售价格
cout << book << endl;//写入ISBN、售出的册数、总销售额和平均价格
return 0;
}
Sales_ item
对象的加法,将两个Sales_ item 对象相加,代码如下:
#include <iostream>
#include"Sales_item. h"
using namespace std;
int main (){
Sales_item item1, item2 ;
cin>>item1>>item2;//读取一对交易记录
cout << item1 + item2 << endl; // 打印它们的和
return 0;
}
成员函数
(member function)定义为类的一部分的函数, 有时也被称为方法(method)。我们通常以一个类对象的名义来调用成员函数。
例如iteml. isbn ()使用点运算符
(.) 来表达我们需要“名为iteml的对象的isbn成员”。点运算符只能用于类类型的对象。其左侧运算对象必须是一个类类型的对象,右侧运算对象必须是该类型的一个成员名,运算结果为右侧运算对象指定的成员。
1.6 书店程序
书店程序本质上与1.4最后一部分的代码含义相同。都是判断刚刚输入的是否与前面输入的相同。相同则继续等待下一个输入。若不同则统计输出前面输入的数据。
书店程序
:从一个文件中读取销售记录,生成每本书的销售报告,显示售出册数、总销售额和平均售价。假定每个ISBN书号的所有销售记录在文件中是聚在一起保存的。程序会将每个ISBN的所有数据合并起来,存入名为total的变量中。使用另一个名为trans的变量保存读取的每条销售记录。如果trans和total指向相同的ISBN,会更新total的值。否则会打印total的值,并将其重置为刚刚读取的数据(trans),代码如下:
#include <iostream>
#include "Sales item. h"
using namespace std;
int main()
{
Sales_ item total; // 保存下一条交易记录的变量
//读入第一条交易记录,并确保有数据可以处理
if(cin >> total) {
Sales_ item trans;//保存和的变量
//读入并处理剩余交易记录
while (cin >> trans) {
//如果我们仍在处理相同的书
if (total.isbn() == trans.isbn()) {
total += trans; // 更新总销售额
}
else {
//打印前一本书的结果
cout << total << endl;
total = trans; // total 现在表示下一本书的销售额
}
}
cout << total << endl; // 打印最后一本书的结果
}
else {
//没有输入!警告读者
cerr << "No data?!" << endl;
return -1; // 表示失败
}
return 0;
}
术语表
1、参数
(实参,argument)向函数传递的值。
2、赋值
( assignment)抹去一个对象的当前值,用一个新值取代之。
3、程序块
(block)零条或多条语句的序列,用花括号包围。
4、缓冲区
(buffer) 一个存储区域,用于保存数据。IO设施通常将输入(或输出)数据保存在一个缓冲区中,读写缓冲区的动作与程序中的动作是无关的。我们可以显式地刷新输出缓冲,以便强制将缓冲区中的数据写入输出设备。默认情况下,读cin会刷新cout;程序非正常终止时也会刷新cout。
5、内置类型
( built-in type) 由语言定义的类型,如int。
6、Cerr
一个ostream对象,关联到标准错误,通常写入到与标准输出相同的设备。默认情况下,写到cerr的数据是不缓冲的。cerr通常用于输出错误信息或其他不属于程序正常逻辑的输出内容。
7、字符串字面值常量
( character string literal)术语string literal的另一种叫法。
8、cin
一个istream对象,用来从标准输入读取数据。
9、类
(class)一一种用于定义自己的数据结构及其相关操作的机制。类是C++中最基本的特性之一。标准库类型中,如istream和ostream都是类。
10、类类型
( class type)类定义的类型。类名即为类型名。
11、clog
一个ostream对象,关联到标准错误。默认情况下,写到clog的数据是被缓冲的.clog通常用于报告程序的执行信息,存入一个日志文件中。
12、注释
(comment)被编译器忽略的程序文本。C++有两种类型的注释:单行注释和界定符对注释。单行注释以//
开始,从//
到行尾的所有内容都是注释。界定符对注释以/*
开始,其后的所有内容都是注释,直至遇到*/
为止。
13、条件
( condition)求值结果为真或假的表达式。通常用值0表示假,用非零值表示真。
14、cout
一个ostream对象,用于将数据写入标准输出。通常用于程序的正常输出内容。
15、花括号
(curly brace) 花括号用于划定程序块边界。左花括号{为程序块开始,右花括号}为结束。
16、数据结构
(data structure) 数据及其上所允许的操作的–种逻辑组合。
17、编辑-编译-调试
( edit-compile-debug)使程序能正确执行的开发过程。
18、文件结束符
( end-of-file)系 统特定的标识,指出文件中无更多数据了。
19、表达式
( expression)最小的计算单元。一个表达式包含一个或多个运算对象,通常还包含一个或多个运算符。表达式求值会产生一个结果。例如,假设i和j是int对象,则i+j是一个表达式,它产生两个int值的和。
20、for
语句(for statement)迭代语句,提供重复执行能力。通常用来将一个计算反复
执行指定次数。
21、函数
(function) 具名的计算单元。
22、函数体
( function body)语句块,定义了函数所执行的动作。
23、函数名
( function name)函 数为人所知的名字,也用来进行函数调用。
24、头文件
(header)使类或其他名字的定义可被多个程序使用的一种机制。程序通过#include指令使用头文件。
25、if
语句(if statement) 根据一 个特定条件的值进行条件执行的语句。如果条件为真,执行if语句体。否则,执行else语句体(如果存在的话)。
26、初始化
(initialize) 在一个对象创建的时候赋予它一个值。
27、iostream头文件
,提供了面向流的输入输出的标准库类型。
28、istream
标准库类型,提供了面向流的输入的库类型。
29、库类型
(library type)标准库定义的类型,如istream。
30、main
操作系统执行一个C++程序时所调用的函数。每个程序必须有且只有一个命名为main的函数。
31、操纵符
( manipulator)对象,如stdl:end1,在读写流的时候用来“操纵”流本身。
32、成员函数
(member function)类定义的操作。通常通过调用成员函数来操作特定对象。
33、方法
(method) 成员函数的同义术语。
34、命名空间
( namespace)将库定义的名字放在一个单一位置的机制。命名空间可以帮助避免不经意的名字冲突。C++ 标准库定义的名字在命名空间std中。
35、ostream
标准库类型,提供面向流的输出的库类型。
36、形参列表
( parameter list) 函数定义的部分,指出调用函数时可以使用什么样的实参,可能为空列表。
37、返回类型
(return type) 函数返回值的类型。
38、源文件
( source file)包含C++程序的文件。
39、标准错误
( standard error)输出流,用于报告错误。标准输出和标准错误通常关联到程序执行所在的窗口。
40、标准输入
(standard input)输入流,通常与程序执行所在窗口相关联。
41、标准库
( standard library) 一个类型和函数的集合,每个C++编译器都必须支持。标准库提供了支持IO操作的类型。C++程序员倾向于用“库”指代整个标准库,还倾向于用库类型表示标准库的特定部分,例如用“iostream库”表示标准库中定义IO类的部分。
42、标准输出
(standard output) 输出流,通常与程序执行所在窗口相关联。
43、语句
(statement) 程序的一部分,指定了当程序执行时进行什么动作。一个表达式接一个分号就是一条语句;其他类型的语句包括语句块、if语旬、for语句和while语句,所有这些语句内都包含其他语句。
44、std
标准库所使用的命名空间。std: :cout表示我们要使用定义在命名空间std中的名字cout。
45、字符串常量
(string literal) 零或多个字符组成的序列,用双引号包围(“a string literal”)。
46、未初始化的变量
( uninitialized variable )未赋予初值的变量。类类型的变量如果未指定初值,则按类定义指定的方式进行初始化。定义在函数内部的内置类型变量默认是不初始化的,除非有显式的初始化语句。试图使用一个未初始化变量的值是错误的。未初始化变量是bug的常见成因。
47、变量
(variable)具名对象。
48、while
语句(while statement)迭代语句,提供重复执行直至一个特定条件为假的机制。循环体会执行零次或多次,依赖于循环条件求值结果。
.
49、()运算符
(() operator)调用运算符。跟随在函数名之后的一对括号“()”, 起到调用函数的效果。传递给函数的实参放置在括号内。
50、++运算符
( ++ operator)递增运算符。将运算对象的值加1,++i等价于i=i+1。
51、+=运算符
(+= operator)复合赋值运算符,将右侧运算对象加到左侧运算对象上;a+=b等价于a=a+b。
52、.运算符
(. operator) 点运算符。左侧运算对象必须是一个类类型对象,右侧运算对象必须是此对象的一个成员的名字。运算结果即为该对象的这个成员。
53、::运算符
(:: operator)作用域运算符。其用处之一是访问命名空间中的名字。例如,std::cout表示命名空间std中的名字cout。
54、=运算符
(= operator)将右侧运算对象的值赋予左侧运算对象所表示的对象。
55、--运算符
(- - operator)递减运算符。将运算对象的值减1,- -i等价于i=i-1。
56、<<运算符
(<< operator)输出运算符。将右侧运算对象的值写到左侧运算对象表示的输出流: cout << "hi"表示将hi写到标准输出。输出运算符可以连接: cout <<“hi”<< "bye"表示将输出hibye。
57、>>运算符
(>> operator)输入运算符。从左侧运算对象所指定的输入流读取数据,存入右侧运算对象中: cin>> i表示从标准输入读取下一个值,存入之中。输入运算符可以连接: cin>> i>> j表示先读取一个值存入i,再读取一个值存入j。
58、#include
头文件包含指令,使头文件中代码可被程序使用。
59、==运算符
(== operator)相等运算符。检测左侧运算对象是否等于右侧运算对象。
60、!=运算符
(!= operator)不等运算符。检测左侧运算对象是否不等于右侧运算对象。
61、<=运算符
(<= operator)小于等于运算符。检测左侧运算对象是否小于等于右侧运算对象。
62、<运算符
(< operator)小于运算符。检测左侧运算对象是否小于右侧运算对象。
63、>=运算符
(>= operator)大于等于运算符。检测左侧运算对象是否大于等于右侧运算对象。
64、>运算符
(> operator)大于运算符。检测左侧运算对象是否大于右侧运算对象。