read and write columns

  • Thread starter Bill Cunningham
  • Start date
S

santosh

Ron said:
Out of n tests against EOF, how many do you think were unnecessary?

None. In a typical read loop each return of getc must be tested for EOF.
If feof and ferror are called for each character for ensuring against
unlikely situations then the number of tests are doubled.
 
R

Richard Tobin

[...]

None. In a typical read loop each return of getc must be tested for EOF.[/QUOTE]

Somewhere along the line the question seems to have changed from
putchar() to getc(). It's certainly not always necessary to test
every return value while writing.

-- Richard
 
C

CBFalconer

Richard said:
.... snip ...


Somewhere along the line the question seems to have changed from
putchar() to getc(). It's certainly not always necessary to test
every return value while writing.

If you can affort to ignore write errors. Which is usually so, or
they are extremely rare.
 
S

santosh

Richard said:
I see. What I was getting at was more like:
putchar(anything)!=EOF ....
[...]

None. In a typical read loop each return of getc must be tested for
EOF.

Somewhere along the line the question seems to have changed from
putchar() to getc(). It's certainly not always necessary to test
every return value while writing.[/QUOTE]

Oops missed that. For putchar, testing for EOF may be over-engineering,
at least for stdout and stderr.
 
S

santosh

santosh said:
Richard said:
santosh said:
I see. What I was getting at was more like:
putchar(anything)!=EOF ....
[...]

None. In a typical read loop each return of getc must be tested for
EOF.

Somewhere along the line the question seems to have changed from
putchar() to getc(). It's certainly not always necessary to test
every return value while writing.

Oops missed that. For putchar, testing for EOF may be
over-engineering, at least for stdout and stderr.

No correct that. Any write to stdout must certainly be verified and any
failure reported on stderr. But there is no point in verifying writes
to stderr, since there is usually nothing that can be done on failure.

But I wonder how much C code meticulously tests putchar/printf etc. In
much code that I have encountered even writes to named files were
unverified.

If there is one thing that I find somewhat frustrating in C, it is the
necessity to constantly test the execution of almost every standard
library and user-defined function at each call, if you want robust
code.
 
R

Richard Tobin

Oops missed that. For putchar, testing for EOF may be
over-engineering, at least for stdout and stderr.
[/QUOTE]
No correct that. Any write to stdout must certainly be verified and any
failure reported on stderr.

I said you don't have to test every return value, not that you don't
have to test for errors. For output it's often adequate to test
for errors at the end of the output instead of after every call:
extra failing writes are usually unimportant.

Obviously this doesn't apply to input, where the values read usually
determine when you stop reading.

-- Richard
 
R

Richard Tobin

Somewhere along the line the question seems to have changed from
putchar() to getc(). It's certainly not always necessary to test
every return value while writing.
[/QUOTE]
If you can affort to ignore write errors. Which is usually so, or
they are extremely rare.

I don't suggest ignoring them in general, just not checking after every
character. Real i/o errors are rare on general-purpose computers, but
write errors caused by full disks, unplugged memory sticks, and closed
terminal sessions are quite common.

-- Richard
 
S

santosh

pete said:
That should be "as the standard output stream?"

No. However, in many cases stdout happens to be redirected to a disk
file while stderr is still linked to the terminal. In such cases it
might be worthwhile to log failure on stdout to stderr.

<snip>
 
L

lawrence.jones

CBFalconer said:
If you can affort to ignore write errors.

Or you check for them (via ferror) at the end, like most people do.

-- Larry Jones

These child psychology books we bought were such a waste of money.
-- Calvin's Mom
 
R

Richard Bos

Ron Ford said:
My impkemenation is sometimes more clever than the monkey on the keyboard.

Exactly. So use EOF, which is guaranteed by the Standard to be valid for
all implementations, not -1, which your monkey believes to be valid
right here, right now.

Richard
 
R

Ron Ford

No. However, in many cases stdout happens to be redirected to a disk
file while stderr is still linked to the terminal. In such cases it
might be worthwhile to log failure on stdout to stderr.

<snip>

I found the snippet that I was thinking was overcautious with checking
against EOF:

if (iscntrl(ch)) {
if (putchar('^') == EOF ||
putchar(ch == '\177' ? '?' :
ch | 0100) == EOF)
break;
continue;
}

It was an uphill climb for me to understand this at all, and without Keith
commenting on it at length, I would have been stalled. In simpler versions
that I wrote, I left off the checks against EOF as I was concentrating on
understanding the short-circuit thing, the ? : syntax and the mask.

Then I thought "under what circumstances is windows with 40 gigs of free
space going to tell my puny C program that there's no room for the next
char, and what the heck could I do about it anyways?"
 
S

santosh

Ron said:
No. However, in many cases stdout happens to be redirected to a disk
file while stderr is still linked to the terminal. In such cases it
might be worthwhile to log failure on stdout to stderr.

<snip>

I found the snippet that I was thinking was overcautious with checking
against EOF:

if (iscntrl(ch)) {
if (putchar('^') == EOF ||
putchar(ch == '\177' ? '?' :
ch | 0100) == EOF)
break;
continue;
} [ ... ]
Then I thought "under what circumstances is windows with 40 gigs of
free space going to tell my puny C program that there's no room for
the next char, and what the heck could I do about it anyways?"

Things other than disk files or terminals are possible too, and could
fail. Consider that stdout has been redirected with a pipe and that the
pipe is closed by the reading process.
 
R

Richard Tobin

santosh said:
Things other than disk files or terminals are possible too, and could
fail. Consider that stdout has been redirected with a pipe and that the
pipe is closed by the reading process.

In unix, this very common case (consider "ls | more") will typically
cause the writing process to receive a SIGPIPE rather than getting an
error from putchar().

-- Richard
 
R

Ron Ford

In unix, this very common case (consider "ls | more") will typically
cause the writing process to receive a SIGPIPE rather than getting an
error from putchar().

Do you have a reference for what putchar() looks like for unix
implementations in as close to standard C as you can swing? I couldn't
turn up much with a google search "putchar() openbsd source."
 
S

santosh

Ron said:
Do you have a reference for what putchar() looks like for unix
implementations in as close to standard C as you can swing? I
couldn't turn up much with a google search "putchar() openbsd source."

It's likely to look similar to:

int putchar(int c) {
return putc(c, stdout);
}
 
R

Ron Ford


Thanks, Richard, I've bookmarked that link. Not only does it have the
current version of putchar, it has the whole history of it, including
rationalizations for the changes. It starts out, 14 years ago, looking
like standard C to me:

#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)putchar.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */

#include <stdio.h>

#undef putchar

/*
* A subroutine version of the macro putchar
*/
putchar(c)
int c;
{
register FILE *so = stdout;

return (__sputc(c, so));
}

#if defined(LIBC_SCCS) && !defined(lint)
#if 0
static char sccsid[] = "@(#)putchar.c 8.1 (Berkeley) 6/4/93";
#endif
static const char rcsid[] =
"$Id$";
#endif /* LIBC_SCCS and not lint */


Somewhere along the line, clc's Chris Torek became the "guy who writes
putchar for openbsd," and it adds on a couple non-standard headers that
apparently deal with threading:

#include <stdio.h>
#ifdef _THREAD_SAFE
#include <pthread.h>
#include "pthread_private.h"
#endif

#undef putchar

/*
* A subroutine version of the macro putchar
*/
int
putchar(c)
int c;
{
int retval;
register FILE *so = stdout;

#ifdef _THREAD_SAFE
_thread_flockfile(so,__FILE__,__LINE__);
#endif
retval = __sputc(c, so);
#ifdef _THREAD_SAFE
_thread_funlockfile(so);
#endif
return (retval);
}

The current version isn't shy about the non-standard headers:
#include "namespace.h"
#include <stdio.h>
#include "un-namespace.h"
#include "local.h"
#include "libc_private.h"
, but does the same thing: it undefines putchar and worries about something
being f locked. I was mildly surprised not to see a test against EOF.

I don't understand much of unix programming, but I find that the time I
spend on it bears dividends down the road. What a quirky thing to have a
header called un-namespace.h.
 
R

Ron Ford

It's likely to look similar to:

int putchar(int c) {
return putc(c, stdout);
}

I would rather say that that has a K&R flavor to it, except that K&R takes
putchar and getchar as elemental for the exposition.
 
C

CBFalconer

Ron said:
santosh posted:

I would rather say that that has a K&R flavor to it, except that
K&R takes putchar and getchar as elemental for the exposition.

No, they take "putc(char, FILE*);" and "getc(FILE*);" as the
primitives. From these you can build the rest. But not from
putchar/getchar.
 
U

user923005

Do you have a reference for what putchar() looks like for unix
implementations in as close to standard C as you can swing?  I couldn't
turn up much with a google search "putchar() openbsd source."

I guess that OpenBSD has the same fundamental nature as BSD:
http://www.manpagez.com/man/3/putchar/

In any case, it ought to be like this, if it knows how to behave:
From ©ISO/IEC ISO/IEC 9899:1999 (E)
"7.19.7.9 The putchar function
Synopsis
1 #include <stdio.h>
int putchar(int c);
Description
2 The putchar function is equivalent to putc with the second argument
stdout.
Returns
3 The putchar function returns the character written. If a write error
occurs, the error indicator for the stream is set and putchar returns
EOF.
§7.19.7.9 Library 297"
 

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,733
Messages
2,569,440
Members
44,830
Latest member
ZADIva7383

Latest Threads

Top