By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,417 Members | 1,856 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,417 IT Pros & Developers. It's quick & easy.

A small game

P: n/a
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;
}


--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 16 '08 #1
Share this Question
Share on Google+
23 Replies


P: n/a
On Sep 16, 10:12*am, arnuld <sunr...@invalid.addresswrote:
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;

}

--www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming
Hi Arnuld
It is a simple program that exercises about I/O streams,
input loop, and simple arithmetic. Here are few simple things:
1. It is assumed program is running under Unix environment.
Use Ctrl+D/Ctrl+Z in your message:
2. Include the interface header file for "sleep" function.
3. Use a function like Abs for the following code:
if(result < 0)
{
result = -(result);
}

int abs(int a) { return a 0 ? a : -a; }

Good luck
Saeed Amrollahi
Sep 16 '08 #2

P: n/a
On Sep 16, 4:12 pm, arnuld <sunr...@invalid.addresswrote:
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
Sep 17 '08 #3

P: n/a
On Sep 17, 4:01 am, tony_in_da...@yahoo.co.uk wrote:
On Sep 16, 4:12 pm, arnuld <sunr...@invalid.addresswrote:
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.
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.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Sep 17 '08 #4

P: n/a
In article <e1**********************************@k30g2000hse. googlegroups.com>,
<eb********@gmail.comwrote:
>3. Use a function like Abs for the following code:
if(result < 0)
{
result = -(result);
}

int abs(int a) { return a 0 ? a : -a; }
#include <cstdlib>

result = std::abs(result);

Sep 17 '08 #5

P: n/a
James Kanze wrote:
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;
Sep 17 '08 #6

P: n/a
On Sep 17, 2:31 pm, Juha Nieminen <nos...@thanks.invalidwrote:
James Kanze wrote:
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:
There's no relationship. What I wrote afterwards is additional
information.
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 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).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 17 '08 #7

P: n/a
On Wed, 17 Sep 2008 13:38:24 -0700, James Kanze wrote:
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.
Sep 17 '08 #8

P: n/a
James Kanze wrote:
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.
Sep 17 '08 #9

P: n/a
On Sep 17, 11:32 pm, James Kanze <james.ka...@gmail.comwrote:
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
Sep 18 '08 #10

P: n/a
On Sep 18, 12:38 am, glen stark <m...@nospam.glenstark.netwrote:
On Wed, 17 Sep 2008 13:38:24 -0700, James Kanze wrote:
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.
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).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 18 '08 #11

P: n/a
On Sep 18, 1:46 am, Juha Nieminen <nos...@thanks.invalidwrote:
James Kanze wrote:
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?
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.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 18 '08 #12

P: n/a
On Sep 18, 3:48 am, tony_in_da...@yahoo.co.uk wrote:
On Sep 17, 11:32 pm, James Kanze <james.ka...@gmail.comwrote:
[...]
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::ofstream), 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.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 18 '08 #13

P: n/a
James Kanze wrote:
> 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.
So you are admitting here that you have written such programs.
>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.
And here you admit that at least *sometimes* you don't keep files open
for the entire execution of the program.
> I don't believe that.

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.)
Sep 18 '08 #14

P: n/a
James Kanze wrote:
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.)
Sep 18 '08 #15

P: n/a
On Sep 18, 5:49 pm, James Kanze <james.ka...@gmail.comwrote:
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
Sep 19 '08 #16

P: n/a
On Wed, 17 Sep 2008 09:39:42 +0200, Michael DOUBEZ wrote:
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::streamsiz e>::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
--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 19 '08 #17

P: n/a
On Tue, 16 Sep 2008 12:12:46 +0500, arnuld wrote:
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::streamsiz e>::max(), '\n');
}

return num;
}


--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 19 '08 #18

P: n/a
On Sep 19, 4:26 pm, arnuld <sunr...@invalid.addresswrote:
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();
Won't need this unless recovering from bad input, and you haven't seen
any yet....
while( std::cin >ch )
{
if( ch != '\n')
{
continue;
}
else
{
break;
}
}
You could simplify this to:

while (std::cin >ch && ch != '\n')
/* do nothing */;

or if that's uncomfortable (it's called "short-circuit boolean
evaluation" - takes a bit of getting used to ;-) )

while (std::cin >ch)
if (ch == '\n')
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();
As above. Just the one clear() below is enough....
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::streamsiz e>::max(), '\n');
}

return num;

}

--www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming
Sep 19 '08 #19

P: n/a
On Sep 18, 3:32 pm, Juha Nieminen <nos...@thanks.invalidwrote:
James Kanze wrote:
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.
So you are admitting here that you have written such programs.
I never said anything else. It was never a question, in fact,
and has little or nothing to do with the question of using endl
or '\n'.
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.
And here you admit that at least *sometimes* you don't keep
files open for the entire execution of the program.
Sure. Again, I never said anything else, and it has nothing to
do with the question.
I don't believe that.
And yet, it's true.
And here you deny both of your own admissions you just made
above. You are not writing very consistently.
You've cut what the "I don't believe that" referred to, but I'm
sure that it wasn't that I never did X or Y; it was either that
such cases were exceptional (which is true for second---it's
very, very rare that I have a file I'm writing to that isn't
open for the entire execution of the program), or that I've
never had performance problems due to using endl (which is true,
but I definitly said "I never had", and not that such problems
can't, or don't exist).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 19 '08 #20

P: n/a
On Sep 18, 3:37 pm, Juha Nieminen <nos...@thanks.invalidwrote:
James Kanze wrote:
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*.
Which certainly isn't forbidden. As I mentionned, Sun CC seeks
before and flushes after every << operator.

I'm not sure when "unitbuf" was introduced. I don't remember it
from the classical iostream, but that could very easily be
simply because I never used it. (It is present if I include
<iostream.hand compile with compat=4 with Sun CC, which is as
close to classical iostream as I can come today.) There is, at
any rate, some tradition for having standard error unbuffered,
although the C standard only requires it to not be fully
buffered, and the C++ standard that the unitbuf attribute be set
(but it can still have a buffer size of 0, if that's what the
implmentation wants to do).

I might add that the standard streams are synchronized with
stdio by default. This means that the cout must be flushed
before any output to stdout; since in most implementations, the
C library is separate and doesn't "know" of the existance of the
C++ library, this means that 1) all of the standard streams must
be unit buffered, and 2) that every output must start with a
fflush( NULL ). (In fact, I'm not sure how it's even
implementable for input, unless the implementation uses a
special streambuf which actually uses stdin to do the input.)
(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.)
Sort of. It's text output, and generally, with text, you should
not count on anything in an incomplete last line.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 19 '08 #21

P: n/a
On Sep 19, 10:29 am, tony_in_da...@yahoo.co.uk wrote:
On Sep 19, 4:26 pm, arnuld <sunr...@invalid.addresswrote:
while( std::cin >ch )
{
if( ch != '\n')
{
continue;
}
else
{
break;
}
}
You could simplify this to:

while (std::cin >ch && ch != '\n')
/* do nothing */;
or if that's uncomfortable (it's called "short-circuit boolean
evaluation" - takes a bit of getting used to ;-) )
while (std::cin >ch)
if (ch == '\n')
break;
The short-circuit evaluation is far clearer. In general, it's
best to avoid break or continue in a loop.

In this case, of course, he could simplify even more by using
istream::ignore.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 19 '08 #22

P: n/a
In article <48********@news.bluewin.ch>,
glen stark <ma**@nospam.glenstark.netwrote:
>On Wed, 17 Sep 2008 13:38:24 -0700, James Kanze wrote:

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.
Which should be covered by the statement made earlier by James that
one of the exception is outputing within a tight loop (e.g. each of
the matrice lines) and then flushing immediately once one exits the
loop.

Surely all James is recommending is not to do premature optimisation.
std::endl will always work and should be the first port of call. "\n"
is an optimisation and should be used when needed. That seems clear
and sensible to me.

The reverse suggestion to always use "\n" by default and only add a
std::flush when needed is premature optimisation. std::endl only
slows down application that it slows down. If it does, then by all
mean use "\n", if it doesn't, don't worry about it.
Yan

Sep 19 '08 #23

P: n/a
In article <e1**********************************@f36g2000hsa. googlegroups.com>,
James Kanze <ja*********@gmail.comwrote:
>On Sep 18, 3:48 am, tony_in_da...@yahoo.co.uk wrote:
>On Sep 17, 11:32 pm, James Kanze <james.ka...@gmail.comwrote:

[...]
>- 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.
My experience is that they far too often managed to do both at the
same time. Write too much data in the logs and not enough useful
data.
Yannick
Sep 19 '08 #24

This discussion thread is closed

Replies have been disabled for this discussion.