Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.
int i = 0; while (i < 10) { i += 1; std::cout << i << std::endl; }
+
Solution & Results
The program writes 10 rows of numbers, starting from 1 to 10.
+
The while statement starts from testing the condition and then executes the while body if the condition is true. It stops executing the while body until the condition becomes false. Let’s analyse the first iteration
+
+
First, the condition of the first time iteration is true as 0 < 10 is true.
+
Second, the expression i += 1; is evaluated, and the variable i becomes 1 after the execution.
+
then, the following statement is executed and the variable i is written on the output device.
+
finally, the while loop starts all over again from testing the condition.
+
+
From above steps we have seen that
+
+
the first number to output is 1.
+
i is increased by 1 each iteration.
+
+
Accordingly, the final iteration can be deducted
+
+
when i = 9, the row of output is 9 and the condition is still true.
+
after the evaluation of i += 1;, i equals 10.
+
then the output is 10 in the following step.
+
the while statement starts again and tests the condition, but the condition 10 < 10 is false.
+
the while statement finishes.
+
+
Now I complete the program and test it
1 2 3 4 5 6 7 8 9 10 11 12
#include<iostream>
intmain() { int i = 0; while (i < 10) { i += 1; std::cout << i << std::endl; } return0; }
+
As expected, it writes 10 rows of outputs from 1 to 10 with one number in each row.
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
+
Note that the cursor appears on the next line of the final number 10 due to the following manipulator endl.
+
We can also explain the program from the perspective of its goal. Condiser that, we want the program to print out 10 rows, each of which contains a number, starting from 1 to 10 orderly. The loop invariant can be expressed as: we have written i rows now and the number in current row is i. To verify the loop invariant, we need to verify it at two specific points:
+
+
the first point is before the first time that the condition is evaluated. In this case, it is correct as there is 0 output at current position.
+
the second point is before the end of the while body. Once the first statement is executed, i is increased by 1. To maintain the loop invariant, it needs writing a row which contains the number i. Therefore, the loop statement works as expected in each iteration.
+
+
For clarity, I add comments for the program
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#include<iostream>
intmain() { // loop invariant: we have written i rows now and the number in current row is i int i = 0;
while (i < 10) { // i changes with increment of 1 i += 1;
// to maintain the loop invariant, write 1 row std::cout << i << std::endl; } return0; }
This exercise is similar to the program in the last exercise. There are 16 numbers in total and hence there should be overal 16 loop times. Naturally, we use the range [0, 16) to describe the loop statements. The loop invariant can be expressed as we have written i rows and the number that written in this row is j.
+
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include<iostream>
intmain() { // The loop invariant can be expressed as we have // written i rows and the number written in this row is j. int i = 0;
while (i < 16) { // write a row of outputs cout << endl;
// to maintain the loop invariant, increase the value of i by adding 1 ++i; } return0; }
+
What is the value of j? As mentioned above, the loop invariant needs to be verified at two specific points. First, before the first time that the condition is evaluated, we have written 0 rows. Second, before the end of the while body, we have written 1 row and the number should be 10. Therefore, the inital value of j should be 10. It is still not clear now. I’ll further verify the loop invariant in the second and third iteration.
+
The second iteration:
+
+
before the the condition is evaluated, the loop invariant is correct as currently there is one row and the output is 10.
+
before the end of the while body, i increases by 1. The number to output is 9. To maintain the loop invariant, j should be decreased by 1.
+
+
The third iteration:
+
+
before the the condition is evaluated, the loop invariant is correct as currently there are 2 rows and the second output is 9.
+
before the end of the while body, i increases by 1. The number to output is 8. To maintain the loop invariant, j should be decreased by 1.
+
+
It has been seen from above descriptions, each iteration i changes with increment by 1 while j changes with decrement by 1. Therefore, the sum of i and j should be constant, and hence j = 10 - i as j has initial value 10. In other words, the loop invariant is i + j = 10, of which the i represents the row number and j represents the number contained in the i row of outputs.
intmain() { // loop invariant: we have written i rows and the number // written in this row is j = 10-i.
int i = 0; int j = 10;
while (i < 16) { // write a row of outputs std::cout << j << std::endl;
// to maintain the loop invariant, increase the value // of i by adding 1, change the value o j to 10 - i ++i; j = 10 -i; } return0; }
+
The program works as expected with following outputs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
10 9 8 7 6 5 4 3 2 1 0 -1 -2 -3 -4 -5
+
+
Exercise 2-8
Write a program to generate the product of the numbers in the range [1, 10).
+
Solution & Results
The product of the numbers in the range [1, 10) is
1
1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9
+
Essentially, it is a factorial of number 9. I can transform above expression as
1
9! = 1 x 2 x 3 x ... x 8 x 9
+
or
+
1
9! = 9 x 8!
+
Therefore, the calculation can be designed as a loop statement containing 8 times loops. In each iteration, we calculate the factorial of a number from 2 till 9. The loop invariant is that we have calculated the factorial i times and the number f. I’ll use the range [0, 8) to count the loops. The complete program is shown as below
intmain() { cout << "Please enter two integers: "; // read two numbers int a, b; cin >> a >> b;
if (a == b) cout << a << " equals to " << b << endl; elseif (a > b) cout << a << " is greater than " << b << endl; elseif (a < b) cout << b << " is greater than " << a << endl; return0; }
+
Test 1
1 2
Please enter two numbers: 5 8 8 is greater than 5
+
Test 2
1 2
Please enter two numbers: 4 2 4 is greater than 2
+
Test 3
1 2
Please enter two numbers: 100 100 100 equals to 100
+
Exercise 2-10
Explain each of the uses of std:: in the following program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#include<iostream>
intmain() { int k = 0; while (k != 5) { // invariant: we have written k asterisks so far usingstd::cout; cout << "*"; ++k; } std::cout << std::endl; // std:: is required here return0; }
+
Solution & Results
The first std:: in line 9
1
usingstd::cout;
+
The using declaration qualify us to use the name cout, which is defined in the namespace std, directly instead of std::cout. However, the declaration is only valid within the block of the while statement as the curly braces form a name scope.
+
This also explains the requirements of the std:: in line 13. If one want to use the unqualified cout, endl inside the main function body, he should write the using declarations for each different name before the start of the main function. For example
intmain() { int k = 0; while (k != 5) { // invariant: we have written k asterisks so far // using std::cout - is not required now cout << "*"; ++k; } std::cout << std::endl; // std:: is not required now return0; }
Lines begining with # are preprocessor directives which are preprocessed before actual compilation, i.e. the compilation of the program itself. These preprocessor directives are not part of the program statement, and hence semicolons ;, marking the end of most statements in C++, are not required.
-
The directive #include gives preprocessor instructions to include a header file, i.e. copy the entire content of the specified header or file and insert. There are two ways to use **#include#:
-
1 2
#include<header> #include"file"
+
The directive #include gives preprocessor instructions to include a header file, i.e. copy the entire content of the specified header or file and insert. There are two ways to use **#include#:
1 2
#include<header> #include"file"
The angle-brackets <> are generally used to include a header of the standard library, e.g. iostream, string…, while the quotes “” include a file that is typically programmer-defined. For example, the program above includes a standard header named iostream to accomplish Input-Output (IO) as the C++ language doesn’t define any statements to do IO.
0.3 The main function
Every C++ program must contain a main function. The main function is being called when the operating system runs a program. As same as other functions, the main function also includes four elements: return type, function name, parameter list and function body.
The main function requires an int (i.e. integers) type return value. A return value of zero tells the implementation that the program ran successfully while a non-zero value indicates errors. The example above has an empty parameter list, showing that there is nothing between the parentheses (()).
The function body begins with an open curly brace ({) and ends with a close curly brace (}). The braces indicate that all the statements inside are part of the same function, of which the return statement terminates the execution of the function by returning a value to the function’s caller. Of course, the value that returned should has the same type as the defined return type of the function. In the case of main function, if the return statement is omitted, the implementation would assume a return value of zero (not recommended).
-
0.4 IO & using declarations
Before the return statement inside the braces, the first statement (as shown below) achieves the goal of this program.
-
1
std::cout << "Hello, world!" << std::endl;
+
0.4 IO & using declarations
Before the return statement inside the braces, the first statement (as shown below) achieves the goal of this program.
1
std::cout << "Hello, world!" << std::endl;
As mentioned above, the statement writes Hello, World! on the standard output. The std:: indicates the followed name is part of the namespace named std. The names std::cout and std::cin refer to the objects of the standard output stream (ostream) and input stream (istream), which had already been defined in the iostream library. Another two objects that are defined in the iostream library are cerr and clog. The cerr, representing standard error, is used to output warning or error messages. The clog is used to output the general information about the execution of the program. The name std::endl, which is a manipulator, ends the current line of output. The output operator (<<) and input operator (>>) indicate that what follows is inserted to std::cout and std::cin. To use these objects, firstly we need to include the associated standard header, namely iostream.
To simplify the usage of library names from namesapce std, one could use unqualified names cout or cin instead of std::cout or std::cin by the means of using declarations. For example, above program is exactly as same as the below program:
1 2 3 4 5 6 7 8 9 10 11 12 13
/* * A simple C++ Program * Author: Mr. Nobody */ #include<iostream> usingstd::cout; usingstd::endl; intmain() { // output Hello, world! cout << "Hello, world!" << endl; return0; }f