In the preceding sections, we wrote programs that summed the numbers from 1 through 10. A logical extension of this program would be to ask the user to input a set of numbers to sum. In this case, we won’t know how many numbers to add. Instead, we’ll keep reading numbers until there are no more numbers to read:
#include <iostream>
int main()
{
int sum = 0, value = 0;
// read until end-of-file, calculating a running total of all values read
while (std::cin >> value)
sum += value; // equivalent to sum = sum + value
std::cout << "Sum is: " << sum << std::endl;
return 0;
}
If we give this program the input
3 4 5 6
then our output will be
Sum is: 18
The first line inside main
defines two int
variables, named sum
and value
, which we initialize to 0
. We’ll use value
to hold each number as we read it from the input. We read the data inside the condition of the while
:
while (std::cin >> value)
Evaluating the while
condition executes the expression
std::cin >> value
That expression reads the next number from the standard input and stores that number in value
. The input operator (§ 1.2, p. 8) returns its left operand, which in this case is std::cin
. This condition, therefore, tests std::cin
.
When we use an istream
as a condition, the effect is to test the state of the stream. If the stream is valid—that is, if the stream hasn’t encountered an error—then the test succeeds. An istream
becomes invalid when we hit end-of-file or encounter an invalid input, such as reading a value that is not an integer. An istream
that is in an invalid state will cause the condition to yield false.
Thus, our while
executes until we encounter end-of-file (or an input error). The while
body uses the compound assignment operator to add the current value to the evolving sum
. Once the condition fails, the while
ends. We fall through and execute the next statement, which prints the sum
followed by endl
.
Entering an End-of-File from the Keyboard
When we enter input to a program from the keyboard, different operating systems use different conventions to allow us to indicate end-of-file. On Windows systems we enter an end-of-file by typing a control-z—hold down the Ctrl key and press z
—followed by hitting either the Enter or Return key. On UNIX systems, including on Mac OS X machines, end-of-file is usually control-d.
Part of the compiler’s job is to look for errors in the program text. A compiler cannot detect whether a program does what its author intends, but it can detect errors in the form of the program. The following are the most common kinds of errors a compiler will detect.
Syntax errors: The programmer has made a grammatical error in the C++ language. The following program illustrates common syntax errors; each comment describes the error on the following line:
// error: missing ) in parameter list for main
int main ( {
// error: used colon, not a semicolon, after endl
std::cout << "Read each file." << std::endl:
// error: missing quotes around string literal
std::cout << Update master. << std::endl;
// error: second output operator is missing
std::cout << "Write new master." std::endl;
// error: missing ; on return statement
return 0
}
Type errors: Each item of data in C++ has an associated type. The value 10, for example, has a type of int
(or, more colloquially, “is an int
”). The word "hello"
, including the double quotation marks, is a string literal. One example of a type error is passing a string literal to a function that expects an int
argument.
Declaration errors: Every name used in a C++ program must be declared before it is used. Failure to declare a name usually results in an error message. The two most common declaration errors are forgetting to use std::
for a name from the library and misspelling the name of an identifier:
#include <iostream>
int main()
{
int v1 = 0, v2 = 0;
std::cin >> v >> v2; // error: uses "v" not "v1"
// error: cout not defined; should be std::cout
cout << v1 + v2 << std::endl;
return 0;
}
Error messages usually contain a line number and a brief description of what the compiler believes we have done wrong. It is a good practice to correct errors in the sequence they are reported. Often a single error can have a cascading effect and cause a compiler to report more errors than actually are present. It is also a good idea to recompile the code after each fix—or after making at most a small number of obvious fixes. This cycle is known as edit-compile-debug.