最近公司效益不好,没什么项目,只能翻翻旧代码,看看资料,百无聊赖的时候,弄了一本《C++ Primer》(第5版)复习一下,同时顺便练习一下久违的英语翻译。由于我并不是英语专业出身的,而且也只是闲暇时草草地翻译,所以难免出现差错,欢迎提出批评指正。(*^__^*)
1.2. A First Look at Input/Output
1.2.初窥Input/Output
The C++ language does not define any statements to do input or output (IO). Instead, C++ includes an extensive standard library that provides IO (and many other facilities). For many purposes, including the examples in this book, one needs to know only a few basic concepts and operations from the IO library.
C++语言并没有为输入、输出(IO)操作定义任何语句。 相反,C++是通过包含大量标准库这种方式来提供IO操作(和大量其它类型的设施)。 对大多数应用场合而言,包括本书中的例子,你只需了解IO库里的一些基本概念和操作即可。
Most of the examples in this book use the iostream library. Fundamental to the iostream library are two types named istream and ostream, which represent input and output streams, respectively. A stream is a sequence of characters read from or written to an IO device. The term stream is intended to suggest that the characters are generated, or consumed, sequentially over time.
本书中的例子大都使用iostream库。iostream库的基础是名为istream和ostream的两种类型,分别表示输入流和输出流。所谓流,就是在IO设备上读取或者写入的字符序列。“流”这个术语意在表明这些字符是按时间顺序产生或使用的。
Standard Input and Output Objects
标准输入、输出对象
The library defines four IO objects. To handle input, we use an object of type istream named cin (pronounced see-in). This object is also referred to as the standard input. For output, we use an ostream object named cout (pronounced see-out). This object is also known as the standard output. The library also defines two other ostream objects, named cerr and clog (pronounced see-err and see-log, respectively). We typically use cerr, referred to as the standard error, for warning and error messages and clog for general information about the execution of the program.
标准库定义了四个IO对象。我们可以使用一个名为cin(读作see-in)的istream类型的对象来处理输入操作。这个对象也被称为标准输入。如果是输出的话,我们可以使用一个名为cout(读作see-out)的ostream类型的对象。这个对象被称为标准输出。标准库还额外定义了两个ostream对象:cerr和clog(分别读作see-err和see-log)。我们通常会使用被称为标准错误的cerr对象来处理警告和错误信息。clog对象则用来处理程序执行过程中的一般信息。
Ordinarily, the system associates each of these objects with the window in which the program is executed. So, when we read from cin, data are read from the window in which the program is executing, and when we write to cout, cerr, or clog, the output is written to the same window.
通常,系统会把这些IO对象跟程序的执行窗口关联起来。因此,当我们从cin读取数据的时候,数据实际上是从执行程序的窗口中读进来的。同样,当我们往cout写数据的时候,数据是输出到同一个窗口中的。
A Program That Uses the IO Library
一个使用IO库的程序
In our bookstore problem, we’ll have several records that we’ll want to combine into a single total. As a simpler, related problem, let’s look first at how we might add two numbers. Using the IO library, we can extend our main program to prompt the user to give us two numbers and then print their sum:
在我们的书店问题中,我们将会遇到这种情况:存在若干交易记录,我们要把它们汇总成一条交易记录。在处理这个问题前,让我们先看看一个相关的但更为简单的问题:我们怎样相加两个数。借助IO库,我们能够扩展我们的main程序以提示用户提供两个数,然后打印出这两个数之和:
1 #include <iostream> 2 int main() 3 { 4 std::cout << "Enter two numbers:" << std::endl; 5 int v1 = 0, v2 = 0; 6 std::cin >> v1 >> v2; 7 std::cout << "The sum of " << v1 << " and " << v2 8 << " is " << v1 + v2 << std::endl; 9 return 0; 10 }
This program starts by printing
一开始,这个程序在用户的屏幕上打印:
Enter two numbers:
on the user’s screen and then waits for input from the user.
接着,就等待用户的输入。
If the user enters
如果用户输入
3 7
followed by a newline, then the program produces the following output:
后跟一个换行符,那么这个程序就生成下列输出:
The sum of 3 and 7 is 10
The first line of our program
我们程序中的第一行
1 #include <iostream>
tells the compiler that we want to use the iostream library. The name inside angle brackets (iostream in this case) refers to a header. Every program that uses a library facility must include its associated header. The #include directive must be written on a single line—the name of the header and the #include must appear on the same line. In general, #include directives must appear outside any function. Typically, we put all the #include directives for a program at the beginning of the source file.
告知编译器,我们要使用iostream库。尖括号里面括着的是一个头文件名(在这个例子中是iostream)。对于每一个要使用库设施(library facility)的程序,都必须包括一个相关的头文件。#include指示必须单独写成一行——即,头文件名和#include必须处于同一行上。通常,#include必须处于任一个函数的外部。一般情况下,我们把程序中的所有#include指示都放在源文件的开始处。
Writing to a Stream
写出到流
The first statement in the body of main executes an expression. In C++ an expression yields a result and is composed of one or more operands and (usually) an operator. The expressions in this statement use the output operator (the « operator) to print a message on the standard output:
main函数体中的第一条语句执行了一条表达式。在C++中,一条表达式产生一个结果,表达式由一个或多个操作数和(在通常情况下)一个操作符组成。这条语句中的表达式使用了输出操作符(<<操作符)向标准输出打印了一条信息:
1 std::cout << "Enter two numbers:" << std::endl;
The << operator takes two operands: The left-hand operand must be an ostream object; the right-hand operand is a value to print. The operator writes the given value on the given ostream. The result of the output operator is its left-hand operand. That is, the result is the ostream on which we wrote the given value.
<<操作符接受两个操作数:左操作数必须是一个ostream对象;右操作数是一个将要打印的值。<<操作符将给定的右操作数写到给定的ostream中去。输出操作符的执行结果是其左操作数[其实是左操作数的引用,即ostream&]。也就是说,这个结果是刚才我们写入给定值的ostream。
Our output statement uses the << operator twice. Because the operator returns its left-hand operand, the result of the first operator becomes the left-hand operand of the second. As a result, we can chain together output requests. Thus, our expression is equivalent to
我们的输出语句两次使用了<<操作符。由于这个操作符返回的是它的左操作数,这样第一个操作符的运算结果就成为了第二个操作符的左操作数。于是,我们就可以将输出请求链接在一起。因此,我们的表达式等价于:
1 (std::cout << "Enter two numbers:") << std::endl;
Each operator in the chain has the same object as its left-hand operand, in this case std::cout. Alternatively, we can generate the same output using two statements:
在这个请求链中的每一个操作符都会生成一个和它的左操作数一样的对象,正如这个例子中的std::cout。作为另外一种选择,我们也可以用下面的语句来产生相同的输出:
1 std::cout << "Enter two numbers:"; 2 std::cout << std::endl;
The first output operator prints a message to the user. That message is a string literal, which is a sequence of characters enclosed in double quotation marks. The text between the quotation marks is printed to the standard output.
其中,第一个输出操作符向用户输出一条信息。这个信息是一个字符串文字,即一些被一对双引号引住的字符序列。双引号之间的文本被打印到标准输出中去。
The second operator prints endl, which is a special value called a manipulator. Writing endl has the effect of ending the current line and flushing the buffer associated with that device. Flushing the buffer ensures that all the output the program has generated so far is actually written to the output stream, rather than sitting in memory waiting to be written.
第二个输出操作符打印出endl,它是一个被称为操纵符的特殊值。往输出流中输出endl会起结束当前行的作用,并且会刷新与设备关联的缓冲区。刷新缓冲区可以确保程序到当前时刻为止所产生的所有输出被写到输出流中去,而不是处于驻留在内存中并等待被写往输出流这种状态。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Warning
警示
Programmers often add print statements during debugging. Such statements should always flush the stream.
程序员们经常在调试程序的时候加入打印语句。这些语句都应该刷新输出流。
Otherwise, if the program crashes, output may be left in the buffer, leading to incorrect inferences about where the program crashed.
否则,如果程序崩溃了,输出的内容有可能还滞留在缓冲区中,这将导致不能正确地推断出程序的崩溃位置。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Using Names from the Standard Library
使用标准库中的名字
Careful readers will note that this program uses std::cout and std::endl rather than just cout and endl. The prefix std:: indicates that the names cout and endl are defined inside the namespace named std. Namespaces allow us to avoid inadvertent collisions between the names we define and uses of those same names inside a library. All the names defined by the standard library are in the std namespace.
细心的读者会注意到这个程序使用的是std::cout和std::endl,而不是cout和endl。前缀std::表明cout和endl这两个名字是定义在名为std的命名空间中的。命名空间使我们能够避免由于我们定义的名字与库中定义的名字相同而引起的无意冲突。标准库定义的名字都在std命名空间中。
One side effect of the library’s use of a namespace is that when we use a name from the library, we must say explicitly that we want to use the name from the std namespace. Writing std::cout uses the scope operator (the :: operator) to say that we want to use the name cout that is defined in the namespace std. § 3.1 (p. 82) will show a simpler way to access names from the library.
标准库使用命名空间的一个副作用是,当我们使用库中的名字时,我们必须显式地指明我们所用的名字来自于命名空间std。std::cout的写法通过使用作用域操作符(::操作符)来表明cout这个名字是定义在命名空间std中的。§3.1(第82页)将会展示一种更为简便的访问标准库中的名字的方法。
Reading from a Stream
从流读入
Having asked the user for input, we next want to read that input. We start by defining two variables named v1 and v2 to hold the input:
要求用户输入了数据后,下一步我们就要读取用户的输入。首先,我们定义两个变量v1和v2以存储这些输入:
1 int v1 = 0, v2 = 0;
We define these variables as type int, which is a built-in type representing integers. We also initialize them to 0. When we initialize a variable, we give it the indicated value at the same time as the variable is created.
我们是以int类型来定义这两个变量的,int是一个用于表示整数的内置类型。在定义的同时,我们也把这两个变量初始化为0。初始化一个变量就是,在变量被创建的同时我们赋予它一个指定的值。
The next statement
下一条语句
1 std::cin >> v1 >> v2;
reads the input. The input operator (the » operator) behaves analogously to the output operator. It takes an istream as its left-hand operand and an object as its right-hand operand. It reads data from the given istream and stores what was read in the given object. Like the output operator, the input operator returns its left-hand operand as its result. Hence, this expression is equivalent to
用于读取用户的输入。输入操作符(>>操作符)的行为与输出操作符类似。它接受两个对象分别作为它的左操作数和右操作数,其中左操作数是一个istream对象。输入操作符从给定的istream中读取数据,并把所读到的数据存储到给定的对象中。像输出操作符一样,输入操作符会返回它的左操作数作为它的执行结果。因此,这个表达式也等价于:
1 (std::cin >> v1) >> v2;
Because the operator returns its left-hand operand, we can combine a sequence of input requests into a single statement. Our input operation reads two values from std::cin, storing the first in v1 and the second in v2. In other words, our input operation executes as
因为输入操作符会返回它的左操作数,这样我们就可以把一系列的输入请求组合为一条单独的语句。我们的输入操作从std::cin中读取两个值,然后把第一个值存储在v1中,第二个值存储在v2中。也就是说,我们的输入操作是以下面的方式来执行的:
1 std::cin >> v1; 2 std::cin >> v2;
Completing the Program
完成我们的程序
What remains is to print our result:
剩下来的任务就是打印我们的结果:
1 std::cout << "The sum of " << v1 << " and " << v2 << " is " << v1 + v2 << std::endl;
This statement, although longer than the one that prompted the user for input, is conceptually similar. It prints each of its operands on the standard output. What is interesting in this example is that the operands are not all the same kinds of values. Some operands are string literals, such as "The sum of ". Others are int values, such as v1, v2, and the result of evaluating the arithmetic expression v1 + v2. The library defines versions of the input and output operators that handle operands of each of these differing types.
尽管这条语句比提示用户输入数据那条语句要长一些,但从概念上说,这两条语句是类似的。这条语句在标准输出中打印出该语句的每一个操作数。有意思的是,这个例子中并非所有的操作数都是同一类型的值。有些操作数是字符串文字,比如"The sum of ",另一些是int类型的值,比如v1、v2,还有一些是计算算术表达式v1 + v2所得的结果。标准库定义了各种版本的输入、输出操作符,以处理不同类型的操作数。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Exercises Section 1.2
练习
Exercise 1.3: Write a program to print Hello, World on the standard output.
习题1.3:编写一个程序,在标准输出中打印Hello, World。
Exercise 1.4: Our program used the addition operator, +, to add two numbers. Write a program that uses the multiplication operator, *, to print the product instead.
习题1.4:我们的程序使用加法操作符(+)来使两个数相加。编写一个使用乘法操作符(*)的程序,然后输出它们的乘积。
Exercise 1.5: We wrote the output in one large statement. Rewrite the program to use a separate statement to print each operand.
习题1.5:在我们的程序中,我们曾经把输出操作写在一条长长的语句中。重写那个程序,为每一个操作数用单独一条语句进行输出。
Exercise 1.6: Explain whether the following program fragment is legal.
习题1.6:解释下面这个程序片段是否合法。
1 std::cout << "The sum of " << v1; 2 << " and " << v2; << " is " << v1 + v2 << std::endl;
If the program is legal, what does it do? If the program is not legal, why not? How would you fix it?
如果这个程序合法,它进行了哪些操作?如果不合法,为何不合法?你将会如何修改。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++