1.2.2 一个使用IO库的程序
到目前为止,我们已经明白如何编译与执行简单的程序,虽然那个程序什么也不做。在开篇的书店问题中,有一些记录含有相同的ISBN,需要将这些记录进行汇总,也就是说需要弄清楚如何累加已售出书籍的数量。
为了弄清楚如何解决这个问题,我们先来看应如何把两数相加。我们可以使用IO库来扩充main程序,要求用户给出两个数,然后输出它们的和:
#include int main() { std::cout << "Enter two numbers:" << std::endl; int v1, v2; std::cin >> v1 >> v2; std::cout << "The sum of " << v1 << " and " << v2 ; << " is " << v1 + v2 << std::endl; return 0; } |
程序首先在用户屏幕上显示提示语:
然后程序等待用户输入。如果用户输入
跟着一个换行符,则程序产生下面的输出:
程序的第一行是一个预处理指示:
告诉编译器要使用iostream库。尖括号里的名字是一个头文件。程序使用库工具时必须包含相关的头文件。#include指令必须单独写成一行——头文件名和#include必须在同一行。通常,#include指令应出现在任何函数的外部。而且习惯上,程序的所有#include指示都在文件开头部分出现。
1. 写入到流
main函数体中第一条语句执行了一个表达式(expression)。C++(www.cppentry.com)中,一个表达式由一个或几个操作数和通常是一个操作符组成。该语句的表达式使用输出操作符(<<操作符),在标准输出上输出提示语:
std::cout << "Enter two numbers:" << std::endl; |
这个语句用了两次输出操作符。每个输出操作符实例都接受两个操作数:左操作数必须是ostream对象;右操作数是要输出的值。操作符将其右操作数写到作为其左操作数的ostream对象。
C++(www.cppentry.com)中,每个表达式产生一个结果,通常是将运算符作用到其操作数所产生的值。当操作符是输出操作符时,结果是左操作数的值。也就是说,输出操作返回的值是输出流本身。
既然输出操作符返回的是其左操作数,那么我们就可以将输出请求链接在一起。输出提示语的那条语句等价于
(std::cout << "Enter two numbers:") << std::endl;
|
因为(std::cout << "Enter two numbers:")返回其左操作数std::cout,这条语句等价于
std::cout << "Enter two numbers:"; std::cout << std::endl; |
endl是一个特殊值,称为操纵符(manipulator),将它写入输出流时,具有输出换行的效果,并刷新与设备相关联的缓冲区(buffer)。通过刷新缓冲区,保证用户立即看到写入到流中的输出。
程序员经常在调试过程中插入输出语句,这些语句都应该刷新输出流。忘记刷新输出流可能会造成输出停留在缓冲区中,如果程序崩溃,将会导致程序错误推断崩溃位置。
2. 使用标准库中的名字
细心的读者会注意到这个程序中使用的是std::cout和std::endl而不是cout和endl。前缀std::表明cout和endl是定义在命名空间(namespace)std中的。命名空间使程序员可以避免与库中定义的名字相同引起的无意冲突。因为标准库定义的名字是定义在命名空间中,所以我们可以按自己的意图使用相同的名字。
标准库使用命名空间的副作用是,当我们使用标准库中的名字时,必须显式地表达出使用的是命名空间std下的名字。std::cout的写法使用了作用域操作符(scope operator,::操作符),表示使用的是定义在命名空间std中的cout。我们将在3.1节学习到程序中经常使用的避免这种冗长句法的方法。
3. 读入流
在输出提示语后,将读入用户输入的数据。先定义两个名为v1和v2的变量(variable)来保存输入:
将这些变量定义为int类型,int类型是一种代表整数值的内置类型。这些变量未初始化(uninitialized),表示没有赋给它们初始值。这些变量在首次使用时会读入一个值,因此可以没有初始值。
下一条语句读取输入:
输入操作符(>>操作符)行为与输出操作符相似。它接受一个istream对象作为其左操作数,接受一个对象作为其右操作数,它从istream操作数读取数据并保存到右操作数中。像输出操作符一样,输入操作符返回其左操作数作为结果。由于输入操作符返回其左操作数,我们可以将输入请求序列合并成单个语句。换句话说,这个输入操作等价于:
std::cin >> v1; std::cin >> v2; |
输入操作的效果是从标准输入读取两个值,将第一个存放在v1中,第二个存放在v2中。
4. 完成程序
剩下的就是要输出结果:
std::cout << "The sum of " << v1 << " and " << v2 << " is " << v1 + v2 << std::endl; |
这条语句虽然比输出提示语的语句长,但概念上没什么区别。它将每个操作数输出到标准输出。有趣的是操作数并不都是同一类型的值,有些操作数是字符串字面值。例如
其他是不同的int值,如v1,v2以及对算术表达式v1 + v2求值的结果。iostream库定义了接受全部内置类型的输入输出操作符版本。
在写C++(www.cppentry.com)程序时,大部分出现空格符的地方,可用换行符代替。这条规则的一个例外是字符串字面值中的空格符不能用换行符代替。另一个例外是换行符不允许出现在预处理指示中。
关键概念:已初始化变量和未初始化变量
在C++(www.cppentry.com)中,初始化是一个非常重要的概念,对它的讨论将贯穿本书始终。
已初始化变量是指变量在定义时就给定一个值。未初始化变量则未给定初始值:
int val1 = 0; // initialized int val2; // uninitialized |
给变量一个初始值几乎总是正确的,但不要求必须这样做。当我们确定变量在第一次使用时会赋一个新值,那就不需要创建初始值。例如,在本小节最开始我们的第一个有意义的程序中,定义了未初始化变量,并立即读取值给它们。
定义变量时,应该给变量赋初始值,除非确定将变量用于其他意图之前会覆盖这个初值。如果不能保证读取变量之前重置变量,就应该初始化变量。
习题
习题1.3 编一个程序,在标准输出上打印“Hello, World”。
习题1.4 我们的程序利用内置的加法操作符“+”来产生两个数的和,编写程序,使用乘法操作符“*”产生两个数的积。
习题1.5 我们的程序使用了一条较长的输出语句。重写程序,使用单独的语句打印每一个操作数。
习题1.6 解释下面的程序段:
std::cout << "The sum of " << v1; << " and " << v2; << " is " << v1 + v2 << std::endl; |
这段代码合法吗?如果合法,为什么?如果不合法,又为什么?
【责任编辑:
董书 TEL:(010)68476606】