A small game

A

arnuld

My friend sent me the prototype of a game written in C++ and asked for
advice:

IDEA: Game will ask the user to thin of a number. User will press a
keystroke after he has thought of a number. Then program will ask him to
do some little arithmetic and will finally ask for the result. It will
then print what user has thought of.

Here is what I finished with. Any advice is appreciated :)



#include<iostream>

int main()
{
const int think_time = 5;

std::cout << std::endl;
std::cout << "<<<<<<< Let's play a Game >>>>>>\n" << std::endl;


std::cout << "\tThink of a number between 1 to 9\n"
<< "\tPress Ctrl-D when you are done";


char ch;
while( std::cin >> ch )
{
continue;
}

std::cout << std::endl << std::endl;
std::cout << "\t*Add 10 to that number\n";
sleep(think_time);
std::cout << "\t*Now subtract 5 from it\n";
sleep(think_time);
std::cout << "\t*Add another 20 to it\n";
sleep(think_time);
std::cout << "\t*Subtract 7 from it\n";
sleep(think_time);
std::cout << "\t*Subtract 3 from it\n";
sleep(think_time);
std::cin.clear();
std::cout <<"\tHow Much U Have Now :- ";

int think_num;
std::cin >> think_num;

int result = think_num - 15;

if(result < 0)
{
result = -(result);
}

std::cout <<".....Number you thought is :- "
<< result
<< std::endl;


return 0;
}
 
T

tony_in_da_uk

Here is what I finished with. Any advice is appreciated :)
std::cout << std::endl << std::endl;
std::cout << "\t*Add 10 to that number\n";
sleep(think_time);

std::endl writes a newline ('\n') and flushes the output stream. You
want to do this when you want to be sure the message will be displayed
on the screen before the next command runs. So, you should use endl
rather than \n before calling sleep (or you may not see the message on
all platforms), and you should not use endl for each of the couple
prefixed newlines (or you'll get into a bad habit that will make your
larger programs write their output slowly). Same principles can be
applied in many other places in your program.

Also, expecting to be able to resume reading from cin after a control-
D may not be portable. I suggest you just ask the user to press
"Enter", and read/ignore characters until you receive a '\n'. That
has other small benefits, like you can test your program ala "( echo;
echo 22 ) | ./program".

Cheers,
Tony
 
M

Michael DOUBEZ

arnuld a écrit :
[snip]
Here is what I finished with. Any advice is appreciated :)
[snip]
std::cout << "\t*Add 10 to that number\n";
sleep(think_time);
std::cout << "\t*Now subtract 5 from it\n";
sleep(think_time);
std::cout << "\t*Add another 20 to it\n";
sleep(think_time);
std::cout << "\t*Subtract 7 from it\n";
sleep(think_time);
std::cout << "\t*Subtract 3 from it\n";
sleep(think_time);


I guess it is a metter of taset but in this case, I prefer iterating on
the content of a table:

static char const* const instructions[]=
{"Add 10 to that number"
,"Now subtract 5 from it"
,"Add another 20 to it"
,"Subtract 7 from it"
,"Subtract 3 from it"
,NULL //end table with NULL
};

for(const char* it=instructions;*it;++it)
{
std::cout << "\t*"<<*it<<"\n";
sleep(think_time);
}
std::cin.clear();
std::cout <<"\tHow Much U Have Now :- ";

int think_num;

clear cin Just before reading it.
std::cin.clear();
std::cin >> think_num;

Check the operation succeeds and offer a way to stop the program:

while (!(std::cin >> think_num))
{
if(std::cin.eof())
{
std::cout<<"Tired of playing ?\nBye"<<std::endl;
return -1;
}
std::cout << "That's not a number"<<std::endl;
std::cin.clear();
int result = think_num - 15;

if(result < 0)
{
result = -(result);
}

If result is negative, the player lied or made a mistake.
std::cout <<".....Number you thought is :- "
<< result
<< std::endl;

So better not to provide answer if result is invalid.

const int result = think_num - 15;

if((result >= 1) && (result <= 9))
{
std::cout <<".....Number you thought is :- " << result << std::endl;
}
else
{
std::cout <<"Really ? How odd !"<<std::endl;
}
 
J

James Kanze

std::endl writes a newline ('\n') and flushes the output
stream. You want to do this when you want to be sure the
message will be displayed on the screen before the next
command runs. So, you should use endl rather than \n before
calling sleep (or you may not see the message on all
platforms), and you should not use endl for each of the couple
prefixed newlines (or you'll get into a bad habit that will
make your larger programs write their output slowly). Same
principles can be applied in many other places in your
program.

You should use endl until you understand buffering issues.
Given the level of the posting, he's far from that yet. Also,
by default, std::cin and std::cout are tied, so any attempt to
read on std::cin will flush the buffer on std::cout. (A simple
but useful general rule might be to use endl at the end of an
output statement, but '\n' when more text immediately follows.
So he might write the above:
std::cout << "\n\n\t*Add 10 to that number" << std::endl ;
.. Which comes out to what you recommend, in this case, but
the rule doesn't require any understanding of buffering.)
Also, expecting to be able to resume reading from cin after a
control-D may not be portable.

I'd consider it an error if it worked. Without a
std::cin.clear(), the standard guarantees that it won't work;
with an std::cin.clear(), it's a QoI issue, but it really
shouldn't work either.
I suggest you just ask the user to press "Enter", and
read/ignore characters until you receive a '\n'.

Much better design.
That has other small benefits, like you can test your program
ala "( echo; echo 22 ) | ./program".

He really should write a number of scripts to automate testing
of the program.
 
J

James Kanze

[...]
clear cin Just before reading it.
std::cin.clear();

It's not sufficient. The C++ standard doesn't say so directly,
but the intent is clear: successive calls to streambuf::sgetc()
should always return the same thing. (Otherwise, the function
is pretty useless.) And it doesn't make sense that
streambuf::sbumpc() and streambuf::snextc() are not consistent
with this behavior. I have seen Unix implementations of
streambuf in which successive calls to streambuf::sgetc() might
return different things if the first call returned EOF, but I
would consider this a defect. This means, however, that
std::filebuf must memorize EOF, in order to return it
consistently. And since this isn't standard, there's no
standard way of resetting the condition.

As an earlier poster said: instead of the while loop at the
beginning, he should just use:
std::cout << "Press enter to start:" ;
std::cin.ignore( INT_MAX, '\n' ) ;
or something along those lines.
 
J

Juha Nieminen

James said:
You should use endl until you understand buffering issues.
Given the level of the posting, he's far from that yet.

I find that a bit contradictory with what you wrote immediately after:
Also,
by default, std::cin and std::cout are tied, so any attempt to
read on std::cin will flush the buffer on std::cout.

Given that the most usual reason for flushing std::cout is so that the
text will be displayed before the user is asked for some input with
std::cin, and given that, as you say, std::cout *is* automatically
flushed when std::cin is used, there doesn't seem to be too many reasons
to use std::endl.

The biggest problem with std::endl is precisely that it flushes the
output stream. If a new user is taught that std::endl is good and should
always be used by default, he will learn that bad habit, and it will
carry on a long time. At some point he will start creating programs
which write enormous amounts of (text) data to an output file, and by
custom he will use std::endl to write newlines to it. If these newlines
are very common in this output, in most systems the writing will be
slowed down by a rather big factor. He might not even realize that
something is wrong, and could think that that writing speed is normal
when in fact it's completely hindered by the constant needless flushing.

IMO the difference between "\n" and std::endl can and should be taught
from the very beginning, and the recommendation given that "\n" should
be used by default. Just say something like "if at some point you are
outputting some text with std::cout and then your program pauses or
whatever and the text is not appearing on screen, output an std::endl or
std::flush to force it to show the text".

Also when creating CLI applications which might require showing some
progress percentage, this "trick" is useful:

std::cout << "\rProgress: " << percentage << "%" << std::flush;
 
J

James Kanze

I find that a bit contradictory with what you wrote
immediately after:

There's no relationship. What I wrote afterwards is additional
information.
Given that the most usual reason for flushing std::cout is so
that the text will be displayed before the user is asked for
some input with std::cin, and given that, as you say,
std::cout *is* automatically flushed when std::cin is used,
there doesn't seem to be too many reasons to use std::endl.

The usual reason for flushing an ostream (not just cout, any
ostream) is to ensure that the data has been output. In
practice, very few programs write to the console, and even less
read exclusively from std::cin. Unless you know what you are
doing, some of the data you think you've written will in fact be
in the buffers, and not have been output. This can have many
consequences: the most obvious are when someone is reading the
data using tail -f, or when the program crashes for some
reason.
The biggest problem with std::endl is precisely that it
flushes the output stream.

And how is that a real problem? It's purely a performance
issue, and doesn't affect most programs at all.
If a new user is taught that std::endl is good and should
always be used by default, he will learn that bad habit,

If a new user is taught to only use '\n', he will learn that bad
habit, and wonder why he's not getting the expected output.
endl is never wrong. Not flushing when a flush is needed is
wrong. Without a certain amount of experience, and
understanding buffering, you don't know when a flush is needed;
using endl isn't perfect, but if your output is line oriented,
it's close enough. And once you understand the issues, you'll
stop programming by habit, think about it, and do the right
thing. (Which is still to use endl 99% of the time; I use it by
default even today, and I pretty much understand the issues.)
and it will carry on a long time. At some point he will start
creating programs which write enormous amounts of (text) data
to an output file, and by custom he will use std::endl to
write newlines to it. If these newlines are very common in
this output, in most systems the writing will be slowed down
by a rather big factor.

That sounds like vacuous speculation to me. I've been writing
C++ for more than fifteen years now; I regularly use endl, as a
default, and I've never had a performance problem because of it.
(Hint: on real systems, most large output goes to a data base,
not to an ordinary file. With one notable exception: our log
files often reach several gigabytes. But a log file is
precisely where you absolutely must flush after each write.)
He might not even realize that something is wrong, and could
think that that writing speed is normal when in fact it's
completely hindered by the constant needless flushing.

More likely, if he gets into the habit of using "\n", he'll use
it when writing log files as well, which will cause no end of
problems when the program crashes, and someone tries to debug
it.
IMO the difference between "\n" and std::endl can and should
be taught from the very beginning, and the recommendation
given that "\n" should be used by default.

And that's just wrong. Experienced programmers use endl by
default, and most of the time, don't even worry about the
difference.
Just say something like "if at some point you are outputting
some text with std::cout and then your program pauses or
whatever and the text is not appearing on screen, output an
std::endl or std::flush to force it to show the text".
Also when creating CLI applications which might require
showing some progress percentage, this "trick" is useful:
std::cout << "\rProgress: " << percentage << "%" <<
std::flush;

Anytime your output isn't in an entire block. About the only
time "\n" is acceptable is when you're outputting in a loop (and
do a flush after the loop), or when you have a long sequence of
output statements (and end them with an endl or a flush).
 
J

Juha Nieminen

James said:
The usual reason for flushing an ostream (not just cout, any
ostream) is to ensure that the data has been output.

But the proper way to ensure that is to use std::flush, not std::endl
(which, ie. the newline, might not even be the last thing you wrote to
the output stream).

Also the need to explicitly flush an output stream is quite rare. The
only situation where you must do it is when you open a file, write
something to it, and then *keep it open* while the program does other
things (and want to make sure that what you wrote is flushed to the file
rather the residing on an output buffer). While there are practical
cases where you need to keep a file open during the execution of a
program, the more usual situation is that you open the file, write data
to it and then close it (or simply let the ofstream instance go out of
scope), which will effectively flush it.
In
practice, very few programs write to the console, and even less
read exclusively from std::cin.

More the reason to not to use std::endl. If you ever want to
explicitly flush an output stream which is writing to a file, use
std::flush. Usually there's no need, though (especially if you write
something and then close the file).
And how is that a real problem? It's purely a performance
issue, and doesn't affect most programs at all.

Because it's a BIG performance issue. We are talking in the worst case
about an order of magnitude slowdown. It is a very important issue if
you are writing lots of data to a file.
If a new user is taught to only use '\n'

I never said that he should be taught to *only* use that. I said that
he should be taught both, and why use one or the other.
That sounds like vacuous speculation to me.

I wouldn't have written that if I didn't have personal experience.
And that's just wrong. Experienced programmers use endl by
default, and most of the time, don't even worry about the
difference.

I suppose you are calling me an inexperienced programmer then.

(Yes, I *do* have actual literal experience of the speed differences
between writing std::endl and "\n".)
 
J

James Kanze

But the proper way to ensure that is to use std::flush, not
std::endl (which, ie. the newline, might not even be the last
thing you wrote to the output stream).

There's a long tradition for using line buffering, which is what
std::endl is meant to emulate.
Also the need to explicitly flush an output stream is quite rare.

That's simply not true. Except for small, Unix type filter
programs, I don't think I've ever output where there wasn't a
need to flush. It's the rule, rather than the exception.
The only situation where you must do it is when you open a
file, write something to it, and then *keep it open* while the
program does other things (and want to make sure that what you
wrote is flushed to the file rather the residing on an output
buffer). While there are practical cases where you need to
keep a file open during the execution of a program, the more
usual situation is that you open the file, write data to it
and then close it (or simply let the ofstream instance go out
of scope), which will effectively flush it.

Again, that doesn't seem to correspond to my experience. Maybe
in client programs? (But then, wouldn't they generally be
writing to some sort of database?)

[...]
Because it's a BIG performance issue. We are talking in the
worst case about an order of magnitude slowdown. It is a very
important issue if you are writing lots of data to a file.

And I repeat: I use endl most of the tie, I write lots of data
from time to time, and it has never been a performance problem.
I never said that he should be taught to *only* use that. I
said that he should be taught both, and why use one or the
other.

You can't teach everything at once. Before he's through, yes,
he should know both, and know how file buffering works. But
still, the default is std::endl.
I wouldn't have written that if I didn't have personal
experience.

Which disagrees with my experience.
I suppose you are calling me an inexperienced programmer then.
(Yes, I *do* have actual literal experience of the speed
differences between writing std::endl and "\n".)

I know that the difference exists, but I've never encountered a
case where it was significant. At any rate, it's a performance
issue, only to be addressed once the program actually works.

For beginners, it is absolutely essential that what they've
written be output, so that they don't get confused when
debugging. And even for experienced programmers, if the program
crashes, it's a lot easier to figure out what went wrong if the
data you wrote actually made it to the disk.
 
G

glen stark

I know that the difference exists, but I've never encountered a case
where it was significant. At any rate, it's a performance issue, only
to be addressed once the program actually works.

For beginners, it is absolutely essential that what they've written be
output, so that they don't get confused when debugging. And even for
experienced programmers, if the program crashes, it's a lot easier to
figure out what went wrong if the data you wrote actually made it to the
disk.

For the most part I agree with you. Generally, if I have a performance
critical application (numeric integration say, or and FDTD loop), I'll
pull the output somewhere outside the loop so I'm not writing output every
small step. If I do need output somewhere where the performance hit from
buffer flushing is critical, it's usually because I'm debugging, and so
I'm more concerned with reliable and complete output than with efficiency.

In defense of the parent however, there exist problem domains where these
arguments don't hold. I also encounter them from time to time. An
example is outputting largeish matrices. These kind of judgements often
depend heavily on what kind of coding you do.
 
J

Juha Nieminen

James said:
That's simply not true. Except for small, Unix type filter
programs, I don't think I've ever output where there wasn't a
need to flush. It's the rule, rather than the exception.

You have never written a program which opens a file for writing,
writes a bunch of data to it, and then closes the file? Do you mean you
always keep files open for the entire execution of the program?
I don't believe that.
 
T

tony_in_da_uk

If a new user is taught to only use '\n', he will learn that bad
habit, and wonder why he's not getting the expected output.
endl is never wrong. Not flushing when a flush is needed is
wrong. Without a certain amount of experience, and
understanding buffering, you don't know when a flush is needed;
using endl isn't perfect, but if your output is line oriented,
it's close enough. And once you understand the issues, you'll
stop programming by habit, think about it, and do the right
thing.

Solid logic to that (except the colourisation as a "bad habit" which
counteracts the notion of new users growing out of a simplification).

BTW / as you said earlier cin and cout are tied: that's why my initial
reply addressed only output before sleep().

As usual the appropriate balance for professionals is highly dependent
on their environment:
- volatile systems that need frequent debugging/troubleshooting and
aren't I/O bound and performance-sensitive can afford to flush
habitually,
- more stable I/O-bound performance-sensitive systems should not.

FWIW, my experience and preference generally coincides with Juha's. I
have seen many corporate C++ systems where logging is out of control:
- developers:
- put logging in during debugging and don't remove it,
- use ERROR, WARN or INFO level so they can see it without
changing to TRACE, DEBUG, DUMP or whatever might actually
be appropriate so they won't have to wade through everyone
else's trace
- some logging is found to be important but it's at TRACE/DEBUG/
DUMP and it's easier to change the process's threshold down
than find and modify all the relevant debug statements, so
production ends up with verbose logging permanently enabled.

Many such systems suffer noticeable and significant performance
degradation due to the I/O overheads.

Personally, I typically write important debugging/trace to std::cerr
which is line oriented anyway, and very rarely use endl. I generally
detest object streaming functions that choose to flush on behalf of
their caller. Note too: signal handlers can at least attempt to flush
cout/stdout in the event of a crash.

Cheers,
Tony
 
J

James Kanze

For the most part I agree with you. Generally, if I have a
performance critical application (numeric integration say, or
and FDTD loop), I'll pull the output somewhere outside the
loop so I'm not writing output every small step. If I do need
output somewhere where the performance hit from buffer
flushing is critical, it's usually because I'm debugging, and
so I'm more concerned with reliable and complete output than
with efficiency.
In defense of the parent however, there exist problem domains
where these arguments don't hold. I also encounter them from
time to time. An example is outputting largeish matrices.
These kind of judgements often depend heavily on what kind of
coding you do.

I didn't say you should never user '\n' instead of std::endl. I
sais that std::endl should be the default. If I'm outputting
something in a loop, I'll usually use '\n' in the loop, and
manually flush() the buffer after the loop (which is probably
premature optimization). But that's something that you learn to
do after you've mastered the basics. And it still means that
using std::endl is the "default" reaction.

Similarly, one can argue that you should never output two
string literals one after the other: let the compiler do the
contatenation, e.g.:

dest << "first line\n"
"second line\n" // Note the absense of <<
"line with " << variable << "\n"
"and so on" << std::endl ;

Again, it's not a good default (although I've been known to do
it is specific cases).
 
J

James Kanze

You have never written a program which opens a file for writing,
writes a bunch of data to it, and then closes the file?

Sure. My Unix filters, for example. Of course, the files they
deal with tend to be fairly small, so performance is really not
an issue.

I'm sure that there are applications which open a file, then
write tons of data to it in one go. And that in some of these
applications, replacing the std::endl with a '\n' in the tight
loop will make a significant difference. But I don't think that
such applications are that frequent, and it's easy to "optimize"
them once the performance problem has been spotted. In the mean
time, lots of applications output data from input or based on
external events, and it's much easier to figure out where they
went wrong if all of the data they'd written actually was
written.
Do you mean you always keep files open for the entire
execution of the program?

It depends on the program, but most of the time, yes. In most
programs, my files are open for the entire execution of the
program, or at least for a very long time. (Some of the
programs run for years, and the logs are rotated when the become
too big.)
I don't believe that.

And yet, it's true. (In one application, we kept our
persistency files open in permanence. And the application ran
for years on end.) But that doesn't really have much to do with
the issue here. If your outputting a very large amount of data,
in a tight loop, flushing after each line end can slow things up
somewhat; in such cases, you optimize by using '\n'. But
normally, it won't slow things up that much unless the files are
opened in synchronizing mode (which isn't possible with
ofstream), and if they're synchronized, it's precisely because
you need the flush, and you need it to really work.
(Persistency is a good example here: you can't send the
acknowledgement to the request until you are 100% sure that the
updated data is actually physically on disk.)
 
J

James Kanze

On Sep 17, 11:32 pm, James Kanze <[email protected]> wrote:

[...]
FWIW, my experience and preference generally coincides with Juha's. I
have seen many corporate C++ systems where logging is out of control:
- developers:
- put logging in during debugging and don't remove it,
- use ERROR, WARN or INFO level so they can see it without
changing to TRACE, DEBUG, DUMP or whatever might actually
be appropriate so they won't have to wade through everyone
else's trace
- some logging is found to be important but it's at TRACE/DEBUG/
DUMP and it's easier to change the process's threshold down
than find and modify all the relevant debug statements, so
production ends up with verbose logging permanently enabled.

That's interesting. My experience is that most professional
systems don't log enough.

Note that unless the file is actually synchronized (which you
can't do with std::eek:fstream), flushing is actually very fast,
since it basically does nothing more than copy the data from one
buffer to another. The result is that we don't use ofstream for
critical data, since we have to ensure that the writes are
synchronized. For logging, however, it's fine, and the
performance problems we've encountered in logging have always
been due to too many string operations (with their memory
allocations and frees), rather than the time spent in the system
call.

Of course, this all depends on the implementation, as well. The
default library used with Sun CC practically does a flush and a
seek in each <<, regardless of what you do, and that is too
slow. (Truss showed three or more system calls per <<. When
compiled for multi-threading, at any rate.)
Many such systems suffer noticeable and significant
performance degradation due to the I/O overheads.
Personally, I typically write important debugging/trace to
std::cerr which is line oriented anyway, and very rarely use
endl.

There is no "line oriented" (I think you mean line buffered)
output in C++. std::cerr is "unit buffered", which means that
output is flushed after each operation (each << operator). If
performance is an issue with cerr, you might try turning unit
buffering off, then using endl. Or using clog (which normally
outputs to the same destination as cerr, but without the unit
buffering and the tie to cin).

More generally, for logging and tracing, I use a hand built
classes, which outputs through a wrapper which ensures proper
formatting (trace header with timestamp, filename and line
number, following lines in the same trace record indented, trace
record ends with a '\n', etc.) and also ensures thread safety
and one, single atomic write at the end of the trace record.
The actual output is through a streambuf which can forward to
several different physical destinations, depending on severity
and configuration: for critical errors, the "flush" results in
the buffer being sent as email, for example.
I generally detest object streaming functions that choose to
flush on behalf of their caller. Note too: signal handlers
can at least attempt to flush cout/stdout in the event of a
crash.

A signal handler cannot legally call any function on std::cout,
and almost certainly doesn't know about other files. In
practice, a signal handler which calls flush in std::cout could
easily provoke additional problems if the signal arrived when a
thread was in the middle of outputting to std::cout.
 
J

Juha Nieminen

James said:

So you are admitting here that you have written such programs.
It depends on the program, but most of the time, yes.

And here you admit that at least *sometimes* you don't keep files open
for the entire execution of the program.
And yet, it's true.

And here you deny both of your own admissions you just made above. You
are not writing very consistently.

(Yes, I know I'm nitpicking, and I understand what you really meant.
No need to sweat over it.)
 
J

Juha Nieminen

James said:
There is no "line oriented" (I think you mean line buffered)
output in C++. std::cerr is "unit buffered", which means that
output is flushed after each operation (each << operator).

Actually I remember I tested this once, and at least with gcc
std::cerr flushes after each written *character*.

(I have to admit, though, that this was a long time ago and I haven't
tested this recently, and I don't know if it has been changed. In a way
it doesn't makes sense, because if you are outputting eg. the value of
an integer variable which has several digits, and the program is
forcefully terminated in the middle of printing that value, the output
will have the first digits of the number but not the last ones, which
can make the output misleading and confusing.)
 
T

tony_in_da_uk

performance problems we've encountered in logging have always
been due to too many string operations (with their memory
allocations and frees), rather than the time spent in the system
call.

Interesting. I normally try to write each string directly to the
stream without doing string operations on it first, but sometimes it
can't be avoided, and some classes fail to provide streaming operators
or need formatting instruction and you end up calling some manner of
to-string member rather than operator<<.... Still, more full-featured
logging systems add features like accumulating log to be committed or
discarded depending on some eventual outcome etc - can be more needy
of short-term storage.
There is no "line oriented" (I think you mean line buffered)
output in C++. std::cerr is "unit buffered", which means that
output is flushed after each operation (each << operator).

Yes - sloppy of me. Mentally I just think "std::cerr: I write a line
I see it in a crash", but it's true I see partial lines too.
If
performance is an issue with cerr, you might try turning unit
buffering off, then using endl. Or using clog (which normally
outputs to the same destination as cerr, but without the unit
buffering and the tie to cin).

I haven't found performance an issue there - as mentioned I tend to
send bulky unimportant stuff to std::cout and important stuff to
std::cerr.
More generally, for logging and tracing, I use a hand built
classes, which outputs through a wrapper which ensures proper
formatting (trace header with timestamp, filename and line
number, following lines in the same trace record indented, trace
record ends with a '\n', etc.) and also ensures thread safety
and one, single atomic write at the end of the trace record.
The actual output is through a streambuf which can forward to
several different physical destinations, depending on severity
and configuration: for critical errors, the "flush" results in
the buffer being sent as email, for example.

Sounds good. Most professional systems at least aspire to that kind
of functionality.
A signal handler cannot legally call any function on std::cout,
and almost certainly doesn't know about other files. In
practice, a signal handler which calls flush in std::cout could
easily provoke additional problems if the signal arrived when a
thread was in the middle of outputting to std::cout.

If it's a SIGSEGV, you've first done everything you can legally expect
to work, and you're about to exit() anyway, then you've got nothing to
lose by trying to flush the buffers. If it happens to work in your
implementation, it's better than not....

Cheers,
Tony
 
A

arnuld

I guess it is a metter of taset but in this case, I prefer iterating on
the content of a table:

static char const* const instructions[]=
{"Add 10 to that number"
,"Now subtract 5 from it"
,"Add another 20 to it"
,"Subtract 7 from it"
,"Subtract 3 from it"
,NULL //end table with NULL
};
for(const char* it=instructions;*it;++it)
{
std::cout << "\t*"<<*it<<"\n";
sleep(think_time);
}


Looks okay to me but why use "static" in the array definition ?


clear cin Just before reading it.

I did, check again.



Check the operation succeeds and offer a way to stop the program:

while (!(std::cin >> think_num))
{
if(std::cin.eof())
{
std::cout<<"Tired of playing ?\nBye"<<std::endl;
return -1;
}
std::cout << "That's not a number"<<std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

okay, will put it in a separate function taking an "int&" argument, I
don't want to mess with main() all the time.


If result is negative, the player lied or made a mistake.

yes, he did :)

So better not to provide answer if result is invalid.

const int result = think_num - 15;

if((result >= 1) && (result <= 9))
{
std::cout <<".....Number you thought is :- " << result << std::endl;
}
else
{
std::cout <<"Really ? How odd !"<<std::endl;
}


okay, nice
 
A

arnuld

My friend sent me the prototype of a game written in C++ and asked for
advice:

IDEA: Game will ask the user to thin of a number. User will press a
keystroke after he has thought of a number. Then program will ask him to
do some little arithmetic and will finally ask for the result. It will
then print what user has thought of.

Here is what I finished with. Any advice is appreciated :)


I have added most of the suggestions here. Likewise Ctrl-D is indeed
not portable because I am running Linux and my friend who asked me to
check the code uses Windows. So I used 'Enter' , which actually is a
newline , but code behaves little strangely with that:


// A small game which tells the number you think :)

#include<iostream>
#include <cstdlib>

int get_number();

int main()
{
const int think_time = 5;

std::cout << "\n\n<<<<<<< Let's play a Game >>>>>>\n\n";


std::cout << "Think of a number between 1 to 9.\n"
<< "Press 'Enter' when you are done: ";


char ch;
std::cin.clear();
while( std::cin >> ch )
{
if( ch != '\n')
{
continue;
}
else
{
break;
}
}

std::cout << "\n\n"
<< "\t*Add 10 to that number\n";
sleep(think_time);
std::cout << "\t*Now subtract 5 from it\n";
sleep(think_time);
std::cout << "\t*Add another 20 to it\n";
sleep(think_time);
std::cout << "\t*Subtract 7 from it\n";
sleep(think_time);
std::cout << "\t*Subtract 3 from it\n";
sleep(think_time);
std::cout <<"\tHow Much U Have Now :- ";

int think_num = get_number();
int result = think_num - 15;


if((result >= 1) && (result <= 9))
{
std::cout <<".....Number you thought is :- "
<< result
<< "\n\n its Magic! ;)\n"
<< std::endl;
}
else
{
std::cout <<"Really ? How odd !"<<std::endl;
}


return 0;
}



int get_number()
{
int num;

std::cin.clear();

while (!(std::cin >> num))
{
if(std::cin.eof())
{
std::cout<<"Tired of playing ?\nBye\n"<<std::endl;
return -1;
}

std::cout << "That's not a number"<<std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

return num;
}
 

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,773
Messages
2,569,594
Members
45,122
Latest member
VinayKumarNevatia_
Top