Topics To Cover
- Blocks
- Scope
- How to use an if-statement to parse a line of complicated input.
Blocks
if( )
{
// then-block
}
else
{
// else-block
}
|
|
Code in between {}'s forms a block. Therefore:
- The
if is
followed by a block (i.e., the then block)
- The else is followed by a block (i.e., the else block).
|
- You've already seen one example of a block: The block following
main(). Anything you can write inside of the main
block, you can write inside of any block.
-
Likewise, our then-blocks and else-blocks can declare variables, read input, make
assignments to variables ... anything.
So, suppose I wanted to write a program that works as follows:
Compute areas of circles and triangles for the user, first asking the user
which kind of object he was interested in.
Important: See if you can write the program on your own.
Although this problem looks simple, a lot of students have struggled to solve
this problem (or its similar kind).
Sample runs (with user input in red):
$ ./area
Do you have a circle or a triangle? circle
Enter the radius of your circle: 1
Area equals 3.14
$ ./area
Do you have a circle or a triangle? triangle
Enter base length: 1
Enter height: 1
Area equals 0.5
For simplicity, use 3.14 for π.
Hint: Read the input over multiple stages. In
addition, it's better to declare necessary variables inside the relevant block.
Solutions: the program.
Scope
Consider the following code.
int k;
cin >> k;
if ((k % 2) == 0)
{
string s;
s = "even";
}
else
{
string s;
s = "odd";
}
cout << s << endl;
|
|
The code is slightly different from what we saw in the
last lecture. In particular:
- We assign a variable of type string the value
"even" if k is even and "odd"
otherwise.
- Then, after the if-statment, we'll do the printing. We
might implement it like this:
However, when we try to compile this the compiler complains as
follows:
s is an undeclared identifier.
This is exactly what the compiler would say if we'd never defined
s at all.
Well, as far as the compiler is concerned when it processes the
"cout << s << endl;" statement, we
haven't defined s.
|
int k;
cin >> k;
if ((k % 2) == 0)
{}
else
{}
cout << s << endl;
|
|
The above problem is caused by the scope of variables in C++.
- The scope of a variable is the portion of the code that "sees" the
variable, i.e. that knows it exists.
- The scope of a variable ends with the innermost block in which it
was defined.
- In this case, each blue rectangle shows the scope of each variable s.
The statement cout << s << endl; is outside of the
scope, in which the variable s doesn't exist!
|
int k;
cin >> k;
| string s;
if ((k % 2) == 0)
{
s = "even";
}
else
{
s = "odd";
}
cout << s << endl;
|
|
|
To fix the problem, we simply need to move the declaration of s
outside of the if/else-blocks so that its scope extends to cout
statement.
|
Let's check your understanding on scope
Given the code below, what should be the output?
| code | output
|
int a;
a = 3;
cout << a << endl;
{
// you can create a block without an if statement!
int a;
a = 5;
cout << a << endl;
}
cout << a << endl;
|
Drag your mouse below.
3
5
3
|
To see what is going on in more detail, let's check the address of the
variables.
| code | output | memory diagram
|
// ...
1: int a; // location 0
2: a = 3;
3: cout << a << endl;
4: cout << &a << endl;
5:
6: {
7: int a; // location 1
8: a = 5;
9: cout << a << endl;
10: cout << &a << endl;
11: }
12:
13: cout << a << endl;
14: cout << &a << endl;
|
3
0x7fffd00e5240
5
0x7fffd00e5244
3
0x7fffd00e5240
|
address contents (variables)
...
0x7fffd845c238
0x7fffd845c23c
0x7fffd845c240 3 a in location 0
0x7fffd845c244 5 a in location 1
0x7fffd845c248
0x7fffd845c24c
0x7fffd845c250
...
- As you see in the above diagram, the variable
a defined in
location 0 is located at address 0x...240. This variable is accessed in lines 2-4 and lines 13-14.
- However, the variable
a defined in location 1 is located at address 0x...244.
This variable is accessed in lines 8-10.
- In summary, you are allowed to define a variable in an inner block whose
name is the same as an variable outside of the block. However, these variables
each have their own storage, even though the name is the same.
|
Other questions on scope
- (True/False) The following code compiles successfully.
int a;
a = 4;
int a;
a = 5;
Answer:
False. You are not allowed to define different variables with the same name in the same block.
- Consider the following code and its output.
| code | output
|
//...
1: int a;
2: cout << &a << endl;
3:
4: {
5: int b;
6: cout << &b << endl;
7: }
8:
9: int c;
10: cout << &c << endl;
|
0x7fffce54efa0
0x7fffce54efa4
0x7fffce54efa4
|
Why is the address of variable b the same as the address of
variable c?
Answer (Drag your mouse below):
|
The variable b was destroyed when the inner block ends at line 7. This space
(for variable b) was reused when variable c is newly defined at line 9.
|
Blocks and Indentation
Read the section of "Curly Braces" in Programming
Style Guide
Shortcut: Dropping {}'s from one-statement blocks
If your then-block (or else-block) consists of a single statement,
you can drop the {}'s - but only if it consists of a single
statement! This is just a shorthand to save you some keystrokes
and a little bit of screen realestate.
So, for example, in the previous code fragment we may remove the
{}'s, since both blocks consist of a single statement.
int k;
cin >> k;
string s;
if ((k % 2) == 0)
s = "even";
else
s = "odd";
cout << s << endl;
This is just a shortcut to save keystroks and screen
space, but you will see this shortcut often.
A common pitfall
If you try to drop the {}'s when you have more than one thing in the block,
you'll run into trouble.
| Wrong | Right
|
if ((k % 2) == 0)
s = "even";
cout << s << endl;
else
s = "odd";
cout << s << endl;
if ((k % 2) == 0)
{
s = "even";
cout << s << endl;
}
else
{
s = "odd";
cout << s << endl;
}
|
|
The code snippet on the left will not compile successfully.
- Your compiler will complain and give you a "parse error". As far as the
compiler is concerned, that "
else" doesn't belong to any
"if"!
- It's not impressed with the fact that the
cout << s << endl;
is indented as if it belonged to the else-block. Note that indentation is only
for human readability; the compiler doesn't really care.
- The compiler thinks that we're dealing with an "
if" from which
the else-block has been dropped. Therefore, it is unhappy when it sees the
"else" from out of nowhere!
Mandatory Practice Problems
Other Practice Problems
- Remainders - this is a toy problem that forces
you to face a fundamental problem in computer science: swapping values.
This is important to know and understand!
Do you know ...
- What is a block?
- What do we mean by a variable's "scope"?