Stroustrup ch2 section 2.3.2 example

A

arnuld

i am trying to understand the mentioned programme, i modified it a
little so that i could understand it better. here is the code & output:

// Stroustrup - Tour of C++

#include <iostream>

int main() {
int tries = 1;

while(tries < 4) {
std::cout << "Do you want to proceed [y/n]: ";
char get_ans = 0;
std::cin >> get_ans;

switch(get_ans) {
case 'y':
return true;
case 'n':
return false;
default:
std::cout << "Sorry, did not get that.\n";
tries = tries + 1;
}

std::cout << "I will take that for a NO.\n";
return false;
}

std::cout << "print of *int main()* \n";
return 0;
}


-------------------OUTPUT ------------------------------

hurd@debian:~/programming/cpp$ g++-3.4 02_232-1.cpp

hurd@debian:~/programming/cpp$ ./a.out
Do you want to proceed [y/n]: y

hurd@debian:~/programming/cpp$ ./a.out
Do you want to proceed [y/n]: n

hurd@debian:~/programming/cpp$ ./a.out
Do you want to proceed [y/n]: j
Sorry, did not get that.
I will take that for a NO.

hurd@debian:~/programming/cpp$
-----------------------------------------------------------

i understand 3 things here:

1.) when i enter 'y' or 'n' /return/ breaks-out from the /main()/, not
from /switch/ or /while/. it is clear as the statement just above
/return 0/ never prints. it means /return/ breaks out from the whole
function & not from the innermost loop. why?

(i expected /return/ to break out of /switch/ only )

2.) from (1), it means i can use /return/ anywhere & it will break-out
from the nested-loops immediately even when i will have 3 nested loops
& i use /return/ in innermost loop.

3.) /switch/ executes only for once.

4.) there is no use of variable /tries/ here as /return/ always causes
/while/ to execute only once.
 
V

Victor Bazarov

arnuld said:
[..]
i understand 3 things here:

1.) when i enter 'y' or 'n' /return/ breaks-out from the /main()/, not
from /switch/ or /while/. it is clear as the statement just above
/return 0/ never prints. it means /return/ breaks out from the whole
function & not from the innermost loop. why?

That's how the "return" statement is defined. What do you mean by
"why"? Why is the language defined the way it's defined? Read "Design
and Evolution of C++", perhaps it's going to get clearer.
(i expected /return/ to break out of /switch/ only )

OK, now my turn to ask: why? What other language do you know that
has that feature? Logically speaking 'return' always makes the current
*function* in to stop processing immediately and *return* the control
to the *caller* of that function.
2.) from (1), it means i can use /return/ anywhere & it will break-out
from the nested-loops immediately even when i will have 3 nested loops
& i use /return/ in innermost loop.

It will *return* from the function to the caller of that function,
regardless of the nested-ness of any loops or if's or switch'es.
3.) /switch/ executes only for once.

Yes, you understand correctly. And you also observed it.
4.) there is no use of variable /tries/ here as /return/ always causes
/while/ to execute only once.

That's unfortunate, but yes, it seems to be extraneous. Are you sure
you copied the example correctly? I don't have TC++PL handy.

V
 
D

Daniel T.

arnuld said:
i am trying to understand the mentioned programme, i modified it a
little so that i could understand it better.

IMHO you didn't modify it "a little" you made major changes to the logic
of the program.

The actual code from 3rd ed. of the book:

bool accept3()
{
int tries = 1;
while (tries < 4) {
cout << "Do you want to proceed (y or n)?\n"; // write question
char answer = 0;
cin >> answer; // read answer
switch (answer) {
case 'y':
return true;
case 'n':
return false;
default:
cout << "Sorry, I don't understand that.\n";
tries = tries + 1;
}
}
cout << "I'll take that for a no.\n";
return false;
}
here is the code & output:

// Stroustrup - Tour of C++

#include <iostream>

int main() {
int tries = 1;

while(tries < 4) {
std::cout << "Do you want to proceed [y/n]: ";
char get_ans = 0;
std::cin >> get_ans;

switch(get_ans) {
case 'y':
return true;
case 'n':
return false;
default:
std::cout << "Sorry, did not get that.\n";
tries = tries + 1;
}

std::cout << "I will take that for a NO.\n";
return false;
}

std::cout << "print of *int main()* \n";
return 0;
}

i understand 3 things here:

1.) when i enter 'y' or 'n' /return/ breaks-out from the /main()/, not
from /switch/ or /while/. it is clear as the statement just above
/return 0/ never prints. it means /return/ breaks out from the whole
function & not from the innermost loop. why?

You would have to ask the designers of the C language that question.
2.) from (1), it means i can use /return/ anywhere & it will break-out
from the nested-loops immediately even when i will have 3 nested loops
& i use /return/ in innermost loop.

Right. You might also want to investigate uses of the 'break' statement.
4.) there is no use of variable /tries/ here as /return/ always causes
/while/ to execute only once.

That's because you put the "I'll take that for a No." and return false
inside the while loop. Note that in the original code from the book,
these two lines are outside the while loop.
 
A

arnuld

Victor said:
That's how the "return" statement is defined. What do you mean by
"why"? Why is the language defined the way it's defined?
aaaoooh!

Read "Design and Evolution of C++", perhaps it's going to get clearer.

i will read it after 3-6 months of programming with C++.
OK, now my turn to ask: why?
Ha...Haa..

What other language do you know that
has that feature? Logically speaking 'return' always makes the current
*function* in to stop processing immediately and *return* the control
to the *caller* of that function.

ok *current function*. got it.
That's unfortunate, but yes, it seems to be extraneous. Are you sure
you copied the example correctly? I don't have TC++PL handy.

it is correct. Damn Sure
 
A

Alf P. Steinbach

* Victor Bazarov:
That's unfortunate, but yes, it seems to be extraneous. Are you sure
you copied the example correctly? I don't have TC++PL handy.

Arnuld's code:

// Stroustrup - Tour of C++

#include <iostream>

int main() {
int tries = 1;

while(tries < 4) {
std::cout << "Do you want to proceed [y/n]: ";
char get_ans = 0;
std::cin >> get_ans;

switch(get_ans) {
case 'y':
return true;
case 'n':
return false;
default:
std::cout << "Sorry, did not get that.\n";
tries = tries + 1;
}

std::cout << "I will take that for a NO.\n";
return false;
}

std::cout << "print of *int main()* \n";
return 0;
}

If the user enters (lowercase) 'y' or 'n' then yes, the corresponding
'case' of the 'switch' statement is executed, and there a 'return'
statement is executed and the function, er, returns, immediately.

If the user enters anything else then the 'default' clause of the
'switch' is executed, and increases the value of 'tries' by 1 (we say
it's incremented). Execution then reaches the closing } of the 'while'
loop's body, wereupon it jumps to the top of the loop again, and the
continuation condition (involving 'tries') is checked again.

If you have a visual debugger then you can check this out directly,
running the program statement by statement in the debugger. I'm told
there is such a debugger in Microsoft's free (except download time)
Visual Studio Express. If you're running Windows, that is.
 
S

Salt_Peter

arnuld said:
i am trying to understand the mentioned programme, i modified it a
little so that i could understand it better. here is the code & output:

// Stroustrup - Tour of C++

#include <iostream>

int main() {
int tries = 1;

while(tries < 4) {
std::cout << "Do you want to proceed [y/n]: ";
char get_ans = 0;
std::cin >> get_ans;

switch(get_ans) {
case 'y':
return true;
case 'n':
return false;
default:
std::cout << "Sorry, did not get that.\n";
tries = tries + 1;
}

std::cout << "I will take that for a NO.\n";
return false;
}

std::cout << "print of *int main()* \n";
return 0;
}


-------------------OUTPUT ------------------------------

hurd@debian:~/programming/cpp$ g++-3.4 02_232-1.cpp

hurd@debian:~/programming/cpp$ ./a.out
Do you want to proceed [y/n]: y

hurd@debian:~/programming/cpp$ ./a.out
Do you want to proceed [y/n]: n

hurd@debian:~/programming/cpp$ ./a.out
Do you want to proceed [y/n]: j
Sorry, did not get that.
I will take that for a NO.

hurd@debian:~/programming/cpp$
-----------------------------------------------------------

i understand 3 things here:

1.) when i enter 'y' or 'n' /return/ breaks-out from the /main()/, not
from /switch/ or /while/. it is clear as the statement just above
/return 0/ never prints. it means /return/ breaks out from the whole
function & not from the innermost loop. why?

because neither switch nor while are functions. These are loops with a
conditional expression with the purpose of controlling the sequence of
the program.
(i expected /return/ to break out of /switch/ only )

2.) from (1), it means i can use /return/ anywhere & it will break-out
from the nested-loops immediately even when i will have 3 nested loops
& i use /return/ in innermost loop.

Yes, return will terminate/exit whatever function it was called in,
regardless of the loops involved. Synctaticly, you could think of the
loops as nothing else but conditional scopes with their own stack.
In other words, there is more going on than meets the eye.
Obviously, if you return from within any scope, all the active scopes
in the function() cease to exist. That is, any automatic variable in
those scope(s) has its d~tor invoked. Returning from an inner scope
does not interrupt that process - on the contrary.

Unlike loops and scopes, functions return a state which may very well
be void. Loops and scopes don't return anything, they just live and
die, but die they do.

To prove the stack:
#include <iostream>

int main()
{
int i(0);
{ // a do_it_once loop
int i(1);
{ // another do_it_once loop
int i(2);
std::cout << "(inner loop) i = " << i << std::endl;
// returning here ends all scopes
}
std::cout << "(mid loop) i = " << i << std::endl;
}
std::cout << "(outer loop) i = " << i << std::endl;
return 0;
}

/*
(inner loop) i = 2
(mid loop) i = 1
(outer loop) i = 0
*/

Try see what happens if you access ::i instead from within an inner
loop. This is important because those scopes are really anonymous
namespaces.
3.) /switch/ executes only for once.

4.) there is no use of variable /tries/ here as /return/ alwaa parallel universeys causes
/while/ to execute only once.

To respect the purpose of the program, the above should be:

#include <iostream>

int proceed()
{
std::cout << "lets do it!\n";
// do some work here
return 0;
}

int main() {
int tries(0);

while(tries < 4) {
std::cout << "Do you want to proceed [y/n]: ";
char get_ans = 0;
std::cin >> get_ans;

switch(get_ans) {
case 'y':
return proceed();
case 'n':
std::cout << "aborting as requested.\n";
return 0;
default:
std::cout << "Sorry, did not get that.\n";
++tries;
}
}
std::cout << "I will take that for a NO.\n";
return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top