1.4.3 读取数量不定的输入数据
在前一节中,我们编写程序实现了1到10这10个整数求和。扩展此程序一个很自然的方向是实现对用户输入的一组数求和。在这种情况下,我们预先不知道要对多少个数求和,这就需要不断读取数据直至没有新的输入为止:
- #include <iostream>
- int main()
- {
- int sum = 0, value = 0;
- // 读取数据直到遇到文件尾,计算所有读入的值的和
- while (std::cin >> value)
- sum += value; // 等价于sumsum = sum + value
- std::cout << "Sum is: " << sum << std::endl;
- return 0;
- }
如果我们输入
- 3 4 5 6
则程序会输出
- Sum is: 18
main的首行定义了两个名为sum和value的int变量,均初始化为0。我们使用value保存用户输入的每个数,数据读取操作是在while的循环条件中完成的:
- while (std::cin >> value)
while循环条件的求值就是执行表达式
- std::cin >> value
此表达式从标准输入读取下一个数,保存在value中。输入运算符(参见1.2节,第8页)返回其左侧运算对象,在本例中是std::cin。因此,此循环条件实际上检测的是std::cin。
当我们使用一个istream对象作为条件时,其效果是检测流的状态。如果流是有效的,即流未遇到错误,那么检测成功。当遇到文件结束符(end-of-file),或遇到一个无效输入时(例如读入的值不是一个整数),istream对象的状态会变为无效。处于无效状态的istream对象会使条件变为假。
因此,我们的while循环会一直执行直至遇到文件结束符(或输入错误)。while循环体使用复合赋值运算符将当前值加到sum上。一旦条件失败,while循环将会结束。我们将执行下一条语句,打印sum的值和一个endl。
从键盘输入文件结束符
当从键盘向程序输入数据时,对于如何指出文件结束,不同操作系统有不同的约定。在Windows系统中,输入文件结束符的方法是敲Ctrl+Z(按住Ctrl键的同时按Z键),然后按Enter或Return键。在UNIX系统中,包括Mac OS X系统中,文件结束符输入是用Ctrl+D。
再探编译
编译器的一部分工作是寻找程序文本中的错误。编译器没有能力检查一个程序是否按照其作者的意图工作,但可以检查形式(form)上的错误。下面列出了一些最常见的编译器可以检查出的错误。
语法错误(syntax error):程序员犯了C++(www.cppentry.com)语言文法上的错误。下面程序展示了一些常见的语法错误;每条注释描述了下一行中语句存在的错误:
- // 错误:main的参数列表漏掉了
- int main ( {
- // 错误:endl后使用了冒号而非分号
- std::cout << "Read each file." << std::endl:
- // 错误:字符串字面常量的两侧漏掉了引号
- std::cout << Update master. << std::endl;
- // 错误:漏掉了第二个输出运算符
- std::cout << "Write new master." std::endl;
- // 错误:return语句漏掉了分号
- return 0
- }
类型错误(type error):C++(www.cppentry.com)中每个数据项都有其类型。例如,10的类型是int(或者更通俗地说,"10是一个int型数据")。单词"hello",包括两侧的双引号标记,则是一个字符串字面值常量。一个类型错误的例子是,向一个期望参数为int的函数传递了一个字符串字面值常量。
声明错误(declaration error):C++(www.cppentry.com)程序中的每个名字都要先声明后使用。名字声明失败通常会导致一条错误信息。两种常见的声明错误是:对来自标准库的名字忘记使用std::、标识符名字拼写错误:
- #include <iostream>
- int main()
- {
- int v1 = 0, v2 = 0;
- std::cin >> v >> v2; // 错误:使用了"v"而非"v1"
- // 错误:cout未定义;应该是std::cout
- cout << v1 + v2 << std::endl;
- return 0;
- }
错误信息通常包含一个行号和一条简短描述,描述了编译器认为的我们所犯的错误。按照报告的顺序来逐个修正错误,是一种好习惯。因为一个单个错误常常会具有传递效应,导致编译器在其后报告比实际数量多得多的错误信息。另一个好习惯是在每修正一个错误后就立即重新编译代码,或者最多是修正了一小部分明显的错误后就重新编译。这就是所谓的"编辑-编译-调试"(edit-compile-debug)周期。
1.4.3节练习
练习1.16:编写程序,从cin读取一组数,输出其和。