What is the problem with this piece of code?

A

Alexander

In my idea it should:
- get the current time
- print 'a'
- do nothing until a second passes
- print 'b':
and repeat for eternity. Instead, it does nothing, and the program
does not exit (probably enters into an infinite loop without producing
any input).

Thanks!

#include <stdio.h>
#include <time.h>

int main() {
char c = 'a';
while(1) {
time_t startTime = time(NULL);
putchar(c);
if (c < 'z') c++;
else c = 'a';
while(startTime == time(NULL));
}
}
 
M

Mara Guida

In my idea it should:
  - get the current time
  - print 'a'

You need to flush the output stream (or print a line break) to see the
output.
Try fflush(stdout) soewhere inside your loop.
 
A

Alexander

Ok, thanks. I wasn't aware that when I call an output function, it's
not immediately applied.
 
K

Keith Thompson

Alexander said:
In my idea it should:
- get the current time
- print 'a'
- do nothing until a second passes
- print 'b':
and repeat for eternity. Instead, it does nothing, and the program
does not exit (probably enters into an infinite loop without producing
any input).

Thanks!

#include <stdio.h>
#include <time.h>

int main() {
char c = 'a';
while(1) {
time_t startTime = time(NULL);
putchar(c);
if (c < 'z') c++;
else c = 'a';
while(startTime == time(NULL));
}
}

It's already been pointed out that output buffering is the problem.

I'll also point out a couple of assumptions you're making.

On many systems, time() returns an integer representing the number
of seconds since a fixed point in the past, so its value changes once
per second, but the standard doesn't guarantee that. If time() has a
finer resolution (for example, if time_t is a floating-point type or
represents a count of milliseconds), you might get a lot more output
that you expect. Note that the resolution of the type time_t doesn't
necessarily match the resolution of the values returned by time().
You're not very likely to run into a system where this is an issue.

The standard doesn't guarantee that the values of 'a' through 'z'
are contiguous. If you were on an EBCDIC system, for example,
you'd see some other characters, some of them undefined, between
some of the letters. Again, unless you work with IBM mainframes,
you're unlikely to run into this.

The first iteration of the loop will take less than a second,
depending on when you start the program.

Your busy loop:

while(startTime == time(NULL));

could cause your program to consume a great deal of CPU time.
This could be bad if you're on a multi-user, or even multi-process,
system.

Finally, just because I can't help myself, "int main()" is better
written as "int main(void)".
 
N

Nobody

Well, the putchar(c) is "immediately applied". However, FILEs can use
buffered I/O, and stdout, by default, uses "line buffering",

Unix convention is that stdin and stdout are line-buffered when associated
with a terminal, and fully-buffered (aka block-buffered) otherwise. stderr
is always unbuffered.

The ISO C standard is slightly less specific; 7.19.3.p7:

As initially opened, the standard error
stream is not fully buffered; the standard input and
standard output streams are fully buffered if and only if
the stream can be determined not to refer to an interactive
device.

POSIX mirrors the ISO C definition, but all real Unices (SysV, BSD,
Linux) follow the stricter convention.
 
J

Jorgen Grahn

.
Your busy loop:

while(startTime == time(NULL));

could cause your program to consume a great deal of CPU time.
This could be bad if you're on a multi-user, or even multi-process,
system.

Or even a single-process system where wasting cycles means wasting
battery life, global warming and other nastiness ...

(He probably knew already that busy loops are a bad idea, but perhaps he
should have mentioned that he knew.)

/Jorgen
 
M

Morris Keesan

....
Well, the putchar(c) is "immediately applied". However, FILEs can use
buffered I/O, and stdout, by default, uses "line buffering", meaning
that the output buffer isn't flushed until a newline is encountered, or
when the output buffer is full.

By adding an explicit fflush(stdout) or putchar('\n') after the
putchar(c), you explicitly force the buffer to be flushed for every
character.

It would be simpler to call setbuf(stdout, NULL) before starting any of
the output, instead of having multiple calls to fflush().
 
K

Keith Thompson

Kenneth Brody said:
I have to
explain the concepts of buffered I/O, and tell them to test it under an
environment closer to how it would be run from our program, with something like:

cat -u | their_program | cat -u

Then, they can immediately see that their program sends "no output" to the
screen until they add the necessary fflush(stdout).

I think somebody already mentioned that the GNU coreutils version of
"cat" ignores the "-u" option.
 

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

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,114
Members
46,702
Latest member
VernitaGow

Latest Threads

Top