Preprocessors
- Preprocessor commands, which begins with
#
, performs some actions before the complier does the translation.- The
include
command is to include a header file:- Files containing definitions of common variables and functions.
- Written to be included by other programs.
#include <iostream>
: Before the compilation, the complier looks for theiostream
header file and copy the codes therein to replace this line.- We may define our own variables and functions into self-defined header files and include them by ourselves:
#include "myHeader"
- Use double quotation marks instead of angle brackets.
- A path must be specified.
- The
Namespaces
-
Suppose all roads in Taiwan have different names. In this case, we do not need to include the city/county name in our address.
-
This is why we do not need to specify the district for an address in the Taipei city.
-
But we need to specify the district for an address in the New Taipei County.
-
A C++ namespace is a collection (space) of names.
- For C++ variables, functions, object, etc.
- The objects
cout
,cin
, and all other items defined in the C++ standard library are defined in the namespacestd
.
-
By writing
using namespace std;
, whenever the complier sees a name, it searchs whether it is defined in this program or the namespacestd
. -
The scope resolution operator (
::
)- We may specify the namespace of
cout
each time when we use it with the scope resolution operation::
- We may specify the namespace of
#include <iostream>
int main()
{
std::cout << "Hello World!\n" << std::endl; // \a std::
return 0;
}
Selection
- The
if
statement
if (condition)
{
statements
}
- The
if-else
statement
if (condition)
{
statements1
}
else
{
statement2
}
- Example
int income = 0, tax = 0;
cout << "Please enter your income: ";
cin >> income;
if (income <= 10000)
{
tax = 0.02 * 10000;
}
else
{
tax = 0.08 * (income - 10000) + 200;
}
- An
if
or anif-else
statement can be nested in anif
block or/andelse
block.
#include <iostream>
using namespace std;
int main()
{
int a = 0, b = 0, c = 0;
cout << "Enter three numbers: ";
cin >> a >> b >> c;
if (a <= b)
{
if (a <= c)
{
cout << a << " is the smallest\n";
}
else
{
cout << c << " is the smallest\n";
}
}
else
{
if (b <= c)
{
cout << b << " is the smallest\n";
}
else
{
cout << c << " is the smallest\n";
}
}
}
- Revised version:
#include <iostream>
using namespace std;
int main()
{
int a = 0, b = 0, c = 0;
cout << "Enter three numbers: ";
cin >> a >> b >> c;
int min = c;
if (a <= b)
{
if (a <= c)
{
min = a;
}
}
else
{
if (b <= c)
{
min = b;
}
}
cout << min << " is the smallest";
}
-
The ternary
if
operator? :
-
In many cases, what to do after an
if-else
selection is simple. -
The ternary
if
operator? :
can be helpful in this case. -
condition ? operation A : opertion B;
: ifcondition
is true, dooperation A
; otherwise,operation B
. -
Second revised version:
#include <iostream>
using namespace std;
int main()
{
int a = 0, b = 0, c = 0;
cout << "Enter three numbers: ";
cin >> a >> b >> c;
int min = c;
if (a <= b)
a < c ? min = a : min = c;
else
min = b <= c ? b : c;
cout << "The smallest number is " << min << endl;
}
-
Ternary
if
operators can also be nested (but not suggested) -
min = a <= b ? a <= c? a : c : b <= c ? b : c;
-
min = (a <= b ? (a <= c? a : c) : (b <= c ? b : c));
-
Dangling
if-else
- What does this mean?
if (a == 10)
if (b == 10)
cout << "a and b are both ten. \n";
else
cout << "a is not ten. \n";
- In the current C++ standard, it is actually:
if (a == 10)
{
if (b == 10)
cout << "a and b are both ten. \n";
else
cout << "a is not ten. \n";
}
-
When we drop
{}
, our programs may be grammatically ambiguous. -
In the field of Programming Languages, it is called the dangling program.
-
To handle this, C++ defines that “one
else
will be paired to the closestif
that has not been paired with anelse
.” -
Good programming style:
- Drop
{ }
only when you know what you are doing. - Align your
{ }
. - Indent your codes properly.
- Drop
-
Logical operators
&&
: and.||
: or.!
: not.- These operators have their aliases (
and
,or
, andnot
).
-
Each of the two conditions must be complete by itself.
if (a >= 10 && <= 20) // error! \a
cout << "a is between 10 and 20";
- Two conditions can be combined only with a logical operator.
if (10 <= a <= 20) // error! \a
cout << "a is between 10 and 20";
- Associativity and precedence
- The
&&
and||
operators both associate the two conditions from left to right. - It is possible that the second condition is not evaluated at all.
- If evaluating the first one is enough.
- There is a precedence rule for operators.
- Use parentheses.
- The
#include <iostream>
using namespace std;
int main()
{
int a = 0, b = 0;
if ((a > 10) && (b = 1))
;
cout << b << endl; // result: 0 \a
if ((a > 10) || (b = 5))
;
cout << b << endl; // result: 5 \a
}
switch-case
switch (operation)
{
case value 1:
statements
break;
case value 2:
statements
break;
...
default:
statements
break;
}
- it is particularly useful for responding to multiple values of a single operation.
- For the operatoion:
- It can contain only a single operand.
- It must return an integer.
- After each
case
, there is a value. - If the returned value of the operation equals that value, those statements in the case block will be executed.
- No curly brackets are needed for blocks.
- A colon is needed after the value.
- A
break
marks the end of a block.- The
break
of the last section is optional.
- The
- Restriction on those values:
- Cannot be (non-constant) variables.
- Must be different integers.
- What will happen if we enter 10?
int a;
cin >> a;
switch (a)
{
case 10:
cout << "ten";
case 6:
cout << "six";
break
}
-
Example:
-
Given a year and a month, how many days is in that month?
-
There are four possibilities:
- 31 days: January, March, May, July, August, October, December.
- 30 days: April, June, September, November.
- 29 days: Februray in a leap year.
- 28 days: Februray in a ordinary year.
-
A year is a leap year if:
- It is a multiple of 400, or
- It is a multiple of 4 but not a multiple of 100.
-
Version 1
#include <iostream>
using namespace std;
int main()
{
int year = 0, month = 0;
cout << "Enter year and month: ";
cin >> year >> month;
int days = 0;
if (month ==1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
days = 31;
else if (month == 4 || month == 6 || month == 9 || month == 11)
days = 30;
else if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0))
days = 29;
else
days = 28;
cout << "Number of days: " << days << endl;
}
- Version 2
#include <iostream>
using namespace std;
int main()
{
int year = 0, month = 0;
cout << "Enter year and month: ";
cin >> year >> month;
int days = 0;
switch (month)
{
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
days = 31;
break;
case 4: case 6: case 9: case 11:
days = 30;
break;
case 2:
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
days = 29;
else
days = 28;
}
cout << "Number of days: " << days << endl;
}
Repetition
while
anddo-while
while (operation)
{
statements
}
do
{
statements
} while (operation); // semicolon \a
-
loop counter
-
Using the unary increment/decrement operator
++
/--
can be more convenient.(NOTE: postfix/prefix?) -
Binary self-assigning operators (e.g.,
+=
). -
For modifying
i
,i++
has the same effect asi = i + 1
. -
For modifying
i
,i--
has the same effect asi = i -1
. -
They can be applied on all basic data types.
- But we should only apply them on integers.
- Typically, using them is faster than using the corresponding addition/subtraction and assignment operation.
-
Both can be put at the left or the right of the operand.
- This changes the order of related operations.
i++
: returns the value ofi
, and then incrementi
.++i
: incrementsi
, and then returns the incremented value ofi
.- So is
i = i + 1
equivalent toi++
or++i
? (ans:++i
)
-
Self-assigning operations
- Typically
a += b
is ** ** thana = a + b
, etc.
- Typically
-
for
for (init; condition; some)
{
statements
}
-
You need those two
;
in the( )
. -
The typical way of using a for statement is:
init
: Initialize a counter variable.cond
: Set up the condition on the counter variable for the loop to continue.some
: Modify (mostly increment or decrement) the counter variable.statements
: The things that we really want to do.
-
Multi-counter
for
loops- Inside one
for
statement:- You may initialize multiple counters at the same time.
- You may also check multiple counters at the same time.
- You may also modify multiple counters at the same time.
- Use
&&
or||
to connect operations on multiple counters.
- Inside one
for (int i = 0, j = 0; i < 10 && j > -5; i++, j--)
cout << i << " " << j << endl;
-
Good programming style:
- When you need to execute a loop for a fixed number of iterations, use a
for
statement with a counter declared only for the loop- This also applies if you know the maximum number of iterations.
- This avoids poetential conflicts on variable names.
- Use the loop that makes your program the most readable.
- Typically only the counter variable enters the
()
of afor
statement. - You may use fractional numbers for a counters, but this not recommended.
- Use integer only.
- Drop
{}
only when you know what you are doing. - Align your
{}
. Indent your codes properly.
- When you need to execute a loop for a fixed number of iterations, use a
-
Scope of variable
- variables live only in the block in which they are declared.
- Two variables declared in the same level cannot have the same name.
int i = 0;
for (; i< 10; i++)
cout << i << endl;
// ...
int i = 0; // error! \a
for (; i < 10; i++)
cout << i << endl;
- This is a good reasons to use
for
: All loops at the same level may use the same name for loop counters.
for (int i = 0; i< 10; i++)
cout << i << endl;
// ...
for (int i = 0; i < 10; i++)
cout << i << endl;
- However, a variable of an existing name is allowed to be declared in an inner block.
- In the inner block, after the same variable name is used to declare a new variable, it “replace” the original one.
- However, its life ends when the inner block ends.
int a = 0;
if (a == 0)
{
cout << a << endl;
int a = 10;
cout << a << endl;
}
cout << a << endl;
break
andcontinue
- When we implement a repetition process, sometimes we need to further change the flow of execution of the loop
- A
break
statement brings us to exit the loop immediately. - When
continue
is executed, statements after it in the loop are skipped.- The looping condition will be checked immediately.
- If it is satisfied, the loop starts from the beginning again.
- How to write a program to print out all integers from 1 to 100 except multiples of 10.
for (int a = 1; a <= 100; a++)
{
if (a % 10 != 0)
cout << a << endl;
}
for (int a = 1; a <= 100; a++)
{
if (a % 10 == 0)
continue;
cout << a << endl;
}
- The effect of
break
andcontinue
is just on the current level.- If a
break
is used in an inner loop, the execution jumps to the outer loop - If a
continue
is used in an inner loop, the execution jumps to the condition check of the inner loop.
- If a
- What will be printed out at the end of this program
#include <iostream>
int main()
{
using namespace std;
int a = 0, b = 0;
while (a <= 10)
{
while (b <= 10)
{
if (b == 5)
break;
cout << a * b << endl; // result: a = 0, b = 0: 0, 0, 0, 0, 0; a = 1, b = 5:
b++;
}
a++;
}
cout << a << endl; // result: 11
return 0;
}
- Using
break
gives a loop multiple exits- It becomes harder to track the flow of a program.
- It becomes harder to know the state after a loop
- Using
continue
highlights the need of getting to the next iteration.- Having too many continue still gets people confused.
- Be careful not to hurt the readability of a program too much.