Discussion:
Open file for both reading and writing?
(too old to reply)
Philipp Klaus Krause
2017-08-02 14:09:36 UTC
Permalink
Does C support the opening of a file for both reading and writing, such
that an empty file is created when the file does not yet exist?

Is there a standard equivalent of POSIX open(., O_RDWR | O_CREAT)?

Philipp
bartc
2017-08-02 15:08:04 UTC
Permalink
Post by Philipp Klaus Krause
Does C support the opening of a file for both reading and writing, such
that an empty file is created when the file does not yet exist?
Is there a standard equivalent of POSIX open(., O_RDWR | O_CREAT)?
Philipp
Does fopen(filename, "rw") work?
Philipp Klaus Krause
2017-08-02 15:18:19 UTC
Permalink
Post by bartc
Post by Philipp Klaus Krause
Does C support the opening of a file for both reading and writing, such
that an empty file is created when the file does not yet exist?
Is there a standard equivalent of POSIX open(., O_RDWR | O_CREAT)?
Philipp
Does fopen(filename, "rw") work?
This would be undefined behaviour.
The C standard doesn't list "rw" as an allowed mode argument (and
neither does POSIX).

Philipp
Joe Pfeiffer
2017-08-02 20:45:51 UTC
Permalink
Post by Philipp Klaus Krause
Post by bartc
Post by Philipp Klaus Krause
Does C support the opening of a file for both reading and writing, such
that an empty file is created when the file does not yet exist?
Is there a standard equivalent of POSIX open(., O_RDWR | O_CREAT)?
Philipp
Does fopen(filename, "rw") work?
This would be undefined behaviour.
The C standard doesn't list "rw" as an allowed mode argument (and
neither does POSIX).
Though the C standard does define

r+ open text file for update (reading and writing)
r+b open binary file for update (reading and writing)

and quite a few other variations specifying whether to append or
truncate.
Dan Cross
2017-08-02 20:52:49 UTC
Permalink
Post by Joe Pfeiffer
Post by Philipp Klaus Krause
Post by bartc
Post by Philipp Klaus Krause
Does C support the opening of a file for both reading and writing, such
that an empty file is created when the file does not yet exist?
Is there a standard equivalent of POSIX open(., O_RDWR | O_CREAT)?
Philipp
Does fopen(filename, "rw") work?
This would be undefined behaviour.
The C standard doesn't list "rw" as an allowed mode argument (and
neither does POSIX).
Though the C standard does define
r+ open text file for update (reading and writing)
r+b open binary file for update (reading and writing)
Sadly, those will fail if the file does not already exist.
Post by Joe Pfeiffer
and quite a few other variations specifying whether to append or
truncate.
In POSIX, `int fd = open("foo", O_RDWR | O_CREAT);` will open an
existing file without trunctating, or create an empty file if
the file did not already exist. In both cases, the file
descriptor will be open for reading and writing, and the current
file read and write pointers will be positioned at the beginning
of the file; writes will be at the current file write pointer
(as opposed to O_APPEND, where writes *always* happen at the end
of the file).

Unforuntately, there's no single "mode" option for fopen() that
results in equivalent behavior in pure ISO C.

- Dan C.
bartc
2017-08-02 15:26:58 UTC
Permalink
Post by bartc
Post by Philipp Klaus Krause
Does C support the opening of a file for both reading and writing, such
that an empty file is created when the file does not yet exist?
Is there a standard equivalent of POSIX open(., O_RDWR | O_CREAT)?
Philipp
Does fopen(filename, "rw") work?
I tried rw and rw+ and they gave some odd results.

This page:
https://docs.microsoft.com/en-gb/cpp/c-runtime-library/reference/fopen-wfopen
includes of list of fopen modes and how they correspond to _O_
combinations (I don't know if those are the same as O_ flags).


Otherwise it is simple enough to write a wrapper function with the
required behaviour. (I thought I'd done exactly this, opening a file for
reading and writing, innumerable times but perhaps not.)
--
bartc
Lew Pitcher
2017-08-02 15:27:16 UTC
Permalink
Post by Philipp Klaus Krause
Does C support the opening of a file for both reading and writing, such
that an empty file is created when the file does not yet exist?
Is there a standard equivalent of POSIX open(., O_RDWR | O_CREAT)?
fopen(filename,"w+");

"w+": Truncate to zero length, or create text file for update (C11 (and
prior) standard, POSIX standard)

In plainer language: "w+": Open for reading and writing. The file is
created if it does not exist, otherwise it is
truncated. The stream is positioned at the
beginning of the file.

HTH
--
Lew Pitcher
"In Skills, We Trust"
PGP public key available upon request
bartc
2017-08-02 15:35:06 UTC
Permalink
Post by Lew Pitcher
Post by Philipp Klaus Krause
Does C support the opening of a file for both reading and writing, such
that an empty file is created when the file does not yet exist?
Is there a standard equivalent of POSIX open(., O_RDWR | O_CREAT)?
fopen(filename,"w+");
"w+": Truncate to zero length, or create text file for update (C11 (and
prior) standard, POSIX standard)
In plainer language: "w+": Open for reading and writing. The file is
created if it does not exist, otherwise it is
truncated. The stream is positioned at the
beginning of the file.
Doesn't that destroy the contents of an existing file? I thought the OP
wanted to preserve them.
--
bartc
Lew Pitcher
2017-08-02 15:39:37 UTC
Permalink
Post by bartc
Post by Lew Pitcher
Post by Philipp Klaus Krause
Does C support the opening of a file for both reading and writing, such
that an empty file is created when the file does not yet exist?
Is there a standard equivalent of POSIX open(., O_RDWR | O_CREAT)?
fopen(filename,"w+");
"w+": Truncate to zero length, or create text file for update (C11 (and
prior) standard, POSIX standard)
In plainer language: "w+": Open for reading and writing. The file is
created if it does not exist, otherwise it is
truncated. The stream is positioned at the
beginning of the file.
Doesn't that destroy the contents of an existing file?
fsck! You are correct. I misremembered the effects of O_CREAT
Post by bartc
I thought the OP wanted to preserve them.
--
Lew Pitcher
"In Skills, We Trust"
PGP public key available upon request
James R. Kuyper
2017-08-02 15:46:24 UTC
Permalink
Post by Philipp Klaus Krause
Does C support the opening of a file for both reading and writing, such
that an empty file is created when the file does not yet exist?
These are the modes defined by the C standard (7.21.5.3p3):> r open
text file for reading
Post by Philipp Klaus Krause
w truncate to zero length or create text file for writing
wx create text file for writing
a append; open or create text file for writing at end-of-file
rb open binary file for reading
wb truncate to zero length or create binary file for writing
wbx create binary file for writing
ab append; open or create binary file for writing at end-of-file
r+ open text file for update (reading and writing)
w+ truncate to zero length or create text file for update
w+x create text file for update
a+ append; open or create text file for update, writing at end-of-file
r+b or rb+ open binary file for update (reading and writing)
w+b or wb+ truncate to zero length or create binary file for update
w+bx or wb+x create binary file for update
a+b or ab+ append; open or create binary file for update, writing at end-of-file
Is is OK if the only things you can read are things written to the file
after it is opened? If so, w+ or w+b would do the job, depending upon
whether you want text mode or binary mode. Both modes truncate an
existing file to length 0, so you would not be able to read anything
that was in the file before it was opened.

Is it OK if the only place you can write is at the end of the file? Then
you can use either a+ and a+b.

However, if you want the ability to read things that were already in the
file before you opened it, and the ability to write to arbitrary
locations, and the creation of a new empty file if the file does not
already exist, you can't do that with a single call to fopen(). You'll
have to first attempt to open an existing file using either r+ or r+b.
If that attempt fails, it might be because the file does not exist, or
it might be because of other reasons (such as having insufficient
permissions). There's no portable way to distinguish those
possibilities, though in practice perror() will often be useful for that
purpose, but the standard does not require that. If that attempt fails,
then try to open it using w+x or w+b.

There are special rules to be followed when opening a file in update
mode (any mode containing a '+'):

"... both input and output may be performed on the associated stream.
However, output shall not be directly followed by input without an
intervening call to the fflush function or to a file positioning
function (fseek, fsetpos, or rewind), and input shall not be directly
followed by output without an intervening call to a file positioning
function, unless the input operation encounters end- of-file. Opening
(or creating) a text file with update mode may instead open (or create)
a binary stream in some implementations." (7.21.5.3p7)
Jerry Stuckle
2017-08-02 15:47:01 UTC
Permalink
Post by Philipp Klaus Krause
Does C support the opening of a file for both reading and writing, such
that an empty file is created when the file does not yet exist?
Is there a standard equivalent of POSIX open(., O_RDWR | O_CREAT)?
Philipp
Use "a+" - Opens for reading and appending. The appending operation
includes the removal of the EOF marker before new data is written to the
file. The EOF marker is not restored after writing is completed. Creates
the file if it does not exist.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Dan Cross
2017-08-02 16:15:33 UTC
Permalink
Post by Philipp Klaus Krause
Does C support the opening of a file for both reading and writing, such
that an empty file is created when the file does not yet exist?
Is there a standard equivalent of POSIX open(., O_RDWR | O_CREAT)?
Not directly. One can approximate it with two calls, however:

FILE *fp = fopen(filename, "r+");
if (fp == NULL)
fp = fopen(filename, "w+");
if (fp == NULL) {
// Handle error here.
}

Of course, there is a race condition here, but if your program
can handle that this would be ok. And the first `fopen` may
have failed for a reason that would make the second not the
appropriate thing to do (the implicit assumption is that it
failed because the file did not exist, so it's okay to create
an empty file by opening with "w+"). Again, if your program
can handle the edge-cases then this would be OK.

Another option *might* be something like:

FILE *fp = fopen(filename, "a+");
if (fp != NULL)
fp = freopen(NULL, "r+", fp);

Here, opening in "a+" mode non-destructively opens an existing
file or creates a new one for updating; the freopen() call
essentially clears the "append-write" behavior of the "a" mode.

It is implementation-defined whether this works. A simple test
on a few of my systems showed that it worked the way I expected
on Linux, macOS and FreeBSD but fails on OpenBSD and NetBSD.
Note that if `fp` is null after the `freopen(...)` call, it's
possible that the underlying file is still open, which could
lead to a file-descriptor leak.

I'd stick to trying "r+" and then "w+" if that fails over this
technique.

One might also write something like:

FILE *fp = fopen(filename, "a+");
if (fp != NULL)
fp = freopen(filename, "r+", fp);

Which should more or less do the right thing without danger of
truncating a file accidentally; freopen() with a non-NULL first
argument will close the file associated with `fp` and then
reopen in the new mode. We're back to it being at least a tad
racy if something else might come along and delete the file out
from under us, but the behavior is well-defined.

- Dan C.
Tim Rentsch
2017-08-03 00:48:28 UTC
Permalink
Post by Dan Cross
Post by Philipp Klaus Krause
Does C support the opening of a file for both reading and writing, such
that an empty file is created when the file does not yet exist?
Is there a standard equivalent of POSIX open(., O_RDWR | O_CREAT)?
FILE *fp = fopen(filename, "r+");
if (fp == NULL)
fp = fopen(filename, "w+");
if (fp == NULL) {
// Handle error here.
}
Of course, there is a race condition here, but if your program
can handle that this would be ok. And the first `fopen` may
have failed for a reason that would make the second not the
appropriate thing to do (the implicit assumption is that it
failed because the file did not exist, so it's okay to create
an empty file by opening with "w+"). Again, if your program
can handle the edge-cases then this would be OK.
FILE *fp = fopen(filename, "a+");
if (fp != NULL)
fp = freopen(NULL, "r+", fp);
Here, opening in "a+" mode non-destructively opens an existing
file or creates a new one for updating; the freopen() call
essentially clears the "append-write" behavior of the "a" mode.
It is implementation-defined whether this works. A simple test
on a few of my systems showed that it worked the way I expected
on Linux, macOS and FreeBSD but fails on OpenBSD and NetBSD.
Note that if `fp` is null after the `freopen(...)` call, it's
possible that the underlying file is still open, which could
lead to a file-descriptor leak.
Can I ask what behavior you saw on the two systems where it
fails? My first impression reading the description of freopen()
in the Standard is that a call with a null first argument either
will succeed or it will fail and the FILE * argument will be left
open. But the text is maddeningly vague. Checks in the usual
places (Annex J, Rationale document) didn't turn anything up
either. Does anyone know of any evidence (DR, etc) that might
indicate what was intended for such cases?
Dan Cross
2017-08-03 01:49:04 UTC
Permalink
Post by Tim Rentsch
[snip]
FILE *fp = fopen(filename, "a+");
if (fp != NULL)
fp = freopen(NULL, "r+", fp);
Here, opening in "a+" mode non-destructively opens an existing
file or creates a new one for updating; the freopen() call
essentially clears the "append-write" behavior of the "a" mode.
It is implementation-defined whether this works. A simple test
on a few of my systems showed that it worked the way I expected
on Linux, macOS and FreeBSD but fails on OpenBSD and NetBSD.
Note that if `fp` is null after the `freopen(...)` call, it's
possible that the underlying file is still open, which could
lead to a file-descriptor leak.
Can I ask what behavior you saw on the two systems where it
fails? My first impression reading the description of freopen()
in the Standard is that a call with a null first argument either
will succeed or it will fail and the FILE * argument will be left
open. But the text is maddeningly vague. Checks in the usual
places (Annex J, Rationale document) didn't turn anything up
either. Does anyone know of any evidence (DR, etc) that might
indicate what was intended for such cases?
So please note that my code is sloppy and I overwrite `fp`
with the return value from `freopen`; so if `freopen` returns
NULL then the underlying FILE* stream may still be "open"
(for whatever that means on the target system), but is
inaccessible since I've thrown the pointer to it away.

Anyway, to address your specific question: freopen() returns
NULL and errno is set to EFAULT. Here is a transcript of a
sample session (the string ': gaja; ' is my prompt):

: gaja; cat f.c
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

const char *filename = "foo.txt";

int
main(void)
{
FILE *fp = fopen(filename, "a+");
if (fp != NULL)
fp = freopen(NULL, "r+", fp);
if (fp == NULL) {
perror(filename);
return EXIT_FAILURE;
}
assert(fwrite("Hey", 1, 3, fp) == 3);
fclose(fp);

return EXIT_SUCCESS;
}
: gaja; rm -f f foo.txt
: gaja; make f
cc -O2 -pipe -o f f.c
: gaja; ./f
foo.txt: Bad address
: gaja; cat foo.txt
: gaja; ls -l foo.txt
-rw-r--r-- 1 cross staff 0 Aug 3 01:23 foo.txt
: gaja; ./f
foo.txt: Bad address
: gaja; echo 'Bye world!' >foo.txt
: gaja; ./f
foo.txt: Bad address
: gaja; cat foo.txt
Bye world!
: gaja;

I looked at the libc code on both OpenBSD and NetBSD, and
neither even attempts to handle the "first argument is NULL"
case; the 'EFAULT' is apparently generated by the underlying
open() call.

Upon closer inspection, this seems conformant with C90; the
behavior of changing the mode of the stream if the first
argument is NULL seems to make its first introduction to the
world in C99. Neither man page on either of those systems
makes any mention of it.

Note that my alternate form, where I pass the filename to the
freopen() call, seems to work on all of my platforms but is as
I noted racy.

- Dan C.
Jerry Stuckle
2017-08-03 01:56:15 UTC
Permalink
Post by Dan Cross
Post by Tim Rentsch
[snip]
FILE *fp = fopen(filename, "a+");
if (fp != NULL)
fp = freopen(NULL, "r+", fp);
Here, opening in "a+" mode non-destructively opens an existing
file or creates a new one for updating; the freopen() call
essentially clears the "append-write" behavior of the "a" mode.
It is implementation-defined whether this works. A simple test
on a few of my systems showed that it worked the way I expected
on Linux, macOS and FreeBSD but fails on OpenBSD and NetBSD.
Note that if `fp` is null after the `freopen(...)` call, it's
possible that the underlying file is still open, which could
lead to a file-descriptor leak.
Can I ask what behavior you saw on the two systems where it
fails? My first impression reading the description of freopen()
in the Standard is that a call with a null first argument either
will succeed or it will fail and the FILE * argument will be left
open. But the text is maddeningly vague. Checks in the usual
places (Annex J, Rationale document) didn't turn anything up
either. Does anyone know of any evidence (DR, etc) that might
indicate what was intended for such cases?
So please note that my code is sloppy and I overwrite `fp`
with the return value from `freopen`; so if `freopen` returns
NULL then the underlying FILE* stream may still be "open"
(for whatever that means on the target system), but is
inaccessible since I've thrown the pointer to it away.
Anyway, to address your specific question: freopen() returns
NULL and errno is set to EFAULT. Here is a transcript of a
: gaja; cat f.c
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
const char *filename = "foo.txt";
int
main(void)
{
FILE *fp = fopen(filename, "a+");
if (fp != NULL)
fp = freopen(NULL, "r+", fp);
if (fp == NULL) {
perror(filename);
return EXIT_FAILURE;
}
assert(fwrite("Hey", 1, 3, fp) == 3);
fclose(fp);
return EXIT_SUCCESS;
}
: gaja; rm -f f foo.txt
: gaja; make f
cc -O2 -pipe -o f f.c
: gaja; ./f
foo.txt: Bad address
: gaja; cat foo.txt
: gaja; ls -l foo.txt
-rw-r--r-- 1 cross staff 0 Aug 3 01:23 foo.txt
: gaja; ./f
foo.txt: Bad address
: gaja; echo 'Bye world!' >foo.txt
: gaja; ./f
foo.txt: Bad address
: gaja; cat foo.txt
Bye world!
: gaja;
I looked at the libc code on both OpenBSD and NetBSD, and
neither even attempts to handle the "first argument is NULL"
case; the 'EFAULT' is apparently generated by the underlying
open() call.
Upon closer inspection, this seems conformant with C90; the
behavior of changing the mode of the stream if the first
argument is NULL seems to make its first introduction to the
world in C99. Neither man page on either of those systems
makes any mention of it.
Note that my alternate form, where I pass the filename to the
freopen() call, seems to work on all of my platforms but is as
I noted racy.
- Dan C.
Now we know what kind of code YOU write!
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Dan Cross
2017-08-03 02:12:07 UTC
Permalink
Post by Jerry Stuckle
Now we know what kind of code YOU write!
http://pub.gajendra.net/software
https://github.com/dancrossnyc/

Have fun!

- Dan C.
Jerry Stuckle
2017-08-03 02:34:06 UTC
Permalink
Post by Dan Cross
Post by Jerry Stuckle
Now we know what kind of code YOU write!
http://pub.gajendra.net/software
https://github.com/dancrossnyc/
Have fun!
- Dan C.
We don't need to look elsewhere. We see it right here in this group.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Dan Cross
2017-08-03 03:05:22 UTC
Permalink
Post by Jerry Stuckle
Post by Dan Cross
Post by Jerry Stuckle
Now we know what kind of code YOU write!
http://pub.gajendra.net/software
https://github.com/dancrossnyc/
Have fun!
We don't need to look elsewhere. We see it right here in this group.
Sure! I've posted some source code here over the years; there
is a bit more in response to Richard and his requested code
review should you like a wider sample. But you'll find a much
wider selection at those two URLs, and that's just what I've
gotten around to putting online.

Would you like me to license some of it to you? For the things
that are original works, I can give you a suitable commercial
license of the type you prefer, I think; I'll have to check with
my employer, of course, but if so my standard consulting rate is
$500/hr, minimum of four hours.

Let me know; I accept bitcoin!

- Dan C.
Jerry Stuckle
2017-08-03 17:51:57 UTC
Permalink
Post by Dan Cross
Post by Jerry Stuckle
Post by Dan Cross
Post by Jerry Stuckle
Now we know what kind of code YOU write!
http://pub.gajendra.net/software
https://github.com/dancrossnyc/
Have fun!
We don't need to look elsewhere. We see it right here in this group.
Sure! I've posted some source code here over the years; there
is a bit more in response to Richard and his requested code
review should you like a wider sample. But you'll find a much
wider selection at those two URLs, and that's just what I've
gotten around to putting online.
Would you like me to license some of it to you? For the things
that are original works, I can give you a suitable commercial
license of the type you prefer, I think; I'll have to check with
my employer, of course, but if so my standard consulting rate is
$500/hr, minimum of four hours.
Let me know; I accept bitcoin!
- Dan C.
No thanks. I want code that works, not the crap you write. And if
someone on one of the projects I worked on posted code like you did for
Richard, they wouldn't be employed for very long.

No, you've shown your lack of competence - both in code and
understanding plain English.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Real Troll
2017-08-03 16:55:00 UTC
Permalink
Post by Jerry Stuckle
Post by Dan Cross
Post by Jerry Stuckle
Now we know what kind of code YOU write!
http://pub.gajendra.net/software
https://github.com/dancrossnyc/
Have fun!
- Dan C.
We don't need to look elsewhere. We see it right here in this group.
Dan is half Indian (or very much influenced by his stay in India) and so
very good at technical stuff but very poor at designing and styling.
Jerry Stuckle
2017-08-03 18:00:48 UTC
Permalink
Post by Real Troll
Post by Jerry Stuckle
Post by Dan Cross
Post by Jerry Stuckle
Now we know what kind of code YOU write!
http://pub.gajendra.net/software
https://github.com/dancrossnyc/
Have fun!
- Dan C.
We don't need to look elsewhere. We see it right here in this group.
Dan is half Indian (or very much influenced by his stay in India) and so
very good at technical stuff but very poor at designing and styling.
That actually would explain a lot. One of my clients at one time got
suckered into hiring a few (Asian) Indians on H-1B visas through a
headhunter. It didn't take long to find out how incompetent they were.
Unfortunately, they had six month contract and the headhunter (for
obvious reasons) wouldn't let them out of it (don't ask me why their
legal department didn't catch the potential problem). So basically they
were stuck for the duration of the contract. The "programmers"
basically ended up doing menial labor for the term of the contract the
client hired some American contractors.

Now I'm not saying all Indian's are this bad - but I've heard more
horror stories than I have success stories.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Dan Cross
2017-08-03 18:50:47 UTC
Permalink
Post by Jerry Stuckle
Post by Real Troll
Dan is half Indian (or very much influenced by his stay in India) and so
very good at technical stuff but very poor at designing and styling.
That actually would explain a lot. One of my clients at one time got
suckered into hiring a few (Asian) Indians on H-1B visas through a
headhunter. It didn't take long to find out how incompetent they were.
Wow, and you're a racist to boot.
Post by Jerry Stuckle
[snip]
Now I'm not saying all Indian's are this bad - but I've heard more
horror stories than I have success stories.
You really are irredemable.

- Dan C.
James R. Kuyper
2017-08-03 19:01:51 UTC
Permalink
[Somewhat racist comments]
...
You really are irredemable.
If you really believe that (and I certainly think it's true), there's
one obvious course of (in)action to follow. Are you ready to follow that
course yet?
Dan Cross
2017-08-03 20:40:36 UTC
Permalink
Post by James R. Kuyper
[Somewhat racist comments]
...
You really are irredemable.
If you really believe that (and I certainly think it's true), there's
one obvious course of (in)action to follow. Are you ready to follow that
course yet?
Yeah, it's clearly time to put Stuckle back in the kill file.

- Dan C.
Jerry Stuckle
2017-08-04 02:38:48 UTC
Permalink
Post by Dan Cross
Post by James R. Kuyper
[Somewhat racist comments]
...
You really are irredemable.
If you really believe that (and I certainly think it's true), there's
one obvious course of (in)action to follow. Are you ready to follow that
course yet?
Yeah, it's clearly time to put Stuckle back in the kill file.
- Dan C.
Please do. My life will be so much easier without having to put up with
your bullshit.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Jerry Stuckle
2017-08-03 19:14:48 UTC
Permalink
Post by Dan Cross
Post by Jerry Stuckle
Post by Real Troll
Dan is half Indian (or very much influenced by his stay in India) and so
very good at technical stuff but very poor at designing and styling.
That actually would explain a lot. One of my clients at one time got
suckered into hiring a few (Asian) Indians on H-1B visas through a
headhunter. It didn't take long to find out how incompetent they were.
Wow, and you're a racist to boot.
Not at all. Just observant of the typical lack of expertise of Indian
programmers. There is nothing racist about it - except to someone
trying to justify his incompetence.
Post by Dan Cross
Post by Jerry Stuckle
[snip]
Now I'm not saying all Indian's are this bad - but I've heard more
horror stories than I have success stories.
You really are irredemable.
- Dan C.
The truth hurts, doesn't it?
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Dan Cross
2017-08-03 18:51:59 UTC
Permalink
Post by Real Troll
Dan is half Indian (or very much influenced by his stay in India) and so
very good at technical stuff but very poor at designing and styling.
No, I'm not half-Indian, but if I were, how would that matter?
Why would that, or any other similar trait, make me "very good
at technical stuff but very poor at designing and styling."

- Dan C.
Richard Heathfield
2017-08-03 19:27:21 UTC
Permalink
Post by Dan Cross
Post by Real Troll
Dan is half Indian (or very much influenced by his stay in India) and so
very good at technical stuff but very poor at designing and styling.
No, I'm not half-Indian, but if I were, how would that matter?
I invite you to reflect on your correspondent's choice of "handle". :-)
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
Richard Heathfield
2017-08-03 06:51:19 UTC
Permalink
Post by Dan Cross
Post by Jerry Stuckle
Now we know what kind of code YOU write!
http://pub.gajendra.net/software
https://github.com/dancrossnyc/
Have fun!
Ah, plenty of scope there for the nit-comb. Alas, I don't have the time
right now to do to you what you did to meESC8bCpost a full review of
even one of those programs (and besides, I'm not /quite/ certain that
"Have fun!" constitutes an invitation so to do), but if that /is/ what
you are inviting I will try to find the time.

(Also, just as my code pushes some people's buttons, your code pushes
some of mine (example: return is /not/ a function!), and so you might
find that many of my criticisms of your code would be the complement of
your criticisms of mine, so there might not be much point.)
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
Dan Cross
2017-08-03 11:52:00 UTC
Permalink
Post by Richard Heathfield
Post by Dan Cross
Post by Jerry Stuckle
Now we know what kind of code YOU write!
http://pub.gajendra.net/software
https://github.com/dancrossnyc/
Have fun!
Ah, plenty of scope there for the nit-comb. Alas, I don't have the time
right now to do to you what you did to meESC8bCpost a full review of
even one of those programs (and besides, I'm not /quite/ certain that
"Have fun!" constitutes an invitation so to do), but if that /is/ what
you are inviting I will try to find the time.
It's entirely up to you; if you'd like to take one and critique
it I'd be open.
Post by Richard Heathfield
(Also, just as my code pushes some people's buttons, your code pushes
some of mine (example: return is /not/ a function!), and so you might
find that many of my criticisms of your code would be the complement of
your criticisms of mine, so there might not be much point.)
That may be true. Another perspective is always (well, usually)
valuable, though things that are purely stylistic are less
likely to be incorporated into revisions. Interestingly, the
`return` thing is something that's evolved in my code over the
years. I used to be fairly consisting in parenthesizing the
expression in the return; now I strive to be consistent in NOT
doing so, older code not withstanding.

- Dan C.
Jerry Stuckle
2017-08-03 18:01:56 UTC
Permalink
Post by Richard Heathfield
Post by Dan Cross
Post by Jerry Stuckle
Now we know what kind of code YOU write!
http://pub.gajendra.net/software
https://github.com/dancrossnyc/
Have fun!
Ah, plenty of scope there for the nit-comb. Alas, I don't have the time
right now to do to you what you did to meESC8bCpost a full review of
even one of those programs (and besides, I'm not /quite/ certain that
"Have fun!" constitutes an invitation so to do), but if that /is/ what
you are inviting I will try to find the time.
(Also, just as my code pushes some people's buttons, your code pushes
some of mine (example: return is /not/ a function!), and so you might
find that many of my criticisms of your code would be the complement of
your criticisms of mine, so there might not be much point.)
And now you know why I won't fall for Dan's trap.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Malcolm McLean
2017-08-03 12:07:26 UTC
Permalink
Post by Dan Cross
Post by Jerry Stuckle
Now we know what kind of code YOU write!
http://pub.gajendra.net/software
https://github.com/dancrossnyc/
"A six function integer calculator (including exponentiation and square roots)
that can include randomized values via dice factors. Dice are specified using
the standard "d" notation (e.g. 3d6)."

Do you like role-playing games? (hobbits, not dominatrices or anything icky).
Dan Cross
2017-08-03 12:09:41 UTC
Permalink
Post by Malcolm McLean
Post by Dan Cross
Post by Jerry Stuckle
Now we know what kind of code YOU write!
http://pub.gajendra.net/software
https://github.com/dancrossnyc/
"A six function integer calculator (including exponentiation and square roots)
that can include randomized values via dice factors. Dice are specified using
the standard "d" notation (e.g. 3d6)."
Do you like role-playing games? (hobbits, not dominatrices or anything icky).
I do! There's a fairly serious (logic) error in that program
that I've frankly been too lazy to repair; the program works but
does something very surprising. Kudos to anyone that finds
it. :-)

- Dan C.
Richard Heathfield
2017-08-03 07:15:04 UTC
Permalink
<snip>
Post by Jerry Stuckle
Post by Dan Cross
: gaja; cat f.c
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
const char *filename = "foo.txt";
int
main(void)
{
FILE *fp = fopen(filename, "a+");
if (fp != NULL)
fp = freopen(NULL, "r+", fp);
if (fp == NULL) {
perror(filename);
return EXIT_FAILURE;
}
assert(fwrite("Hey", 1, 3, fp) == 3);
fclose(fp);
return EXIT_SUCCESS;
}
<snip>
Post by Jerry Stuckle
Now we know what kind of code YOU write!
Yes, we do, because he showed us, because he knows he can write code.

Indeed, for throw-away code written in response to a Usenet query, the
code looks reasonable to me except for the abuse of assert(), which I
suspect is tongue-in-cheek anyway.

It's easy (and a bit pathetic) to criticise code in vague general terms,
but rather harder to write it, and harder still to criticise it in
specific terms that hold water in discussion with the experts in the
language that frequent this group.

Unlike the "real experts" with which you share a secret squirrel server,
the experts in this group actually exist, and arguing with them can be
educational, for those willing to be educated. You can't be educated by
a phantom.

Anyway, if you think I'm going to use the above reply as a hook on which
to hang another response to your chickening out of Dan's challenge,
don't worry. I'm not going to waste any more of my time on your pathetic
evasions on that subject.

Pace clc! Thunderbird has a "Mark as read" filter, so I don't have to
read this crap any more unless a good reason prompts me so to do.
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
Dan Cross
2017-08-03 12:08:22 UTC
Permalink
Post by Richard Heathfield
<snip>
Post by Jerry Stuckle
Post by Dan Cross
: gaja; cat f.c
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
const char *filename = "foo.txt";
int
main(void)
{
FILE *fp = fopen(filename, "a+");
if (fp != NULL)
fp = freopen(NULL, "r+", fp);
if (fp == NULL) {
perror(filename);
return EXIT_FAILURE;
}
assert(fwrite("Hey", 1, 3, fp) == 3);
fclose(fp);
return EXIT_SUCCESS;
}
<snip>
Post by Jerry Stuckle
Now we know what kind of code YOU write!
Yes, we do, because he showed us, because he knows he can write code.
Indeed, for throw-away code written in response to a Usenet query, the
code looks reasonable to me except for the abuse of assert(), which I
suspect is tongue-in-cheek anyway.
The assert() thing was pure laziness on my part.

I rather thought that the thing Stuckle was upset about was the
thing I commented on (twice): that the call to `freopen` may
leak a stream.

One could trivially fix that by using a second variable:

FILE *fp = NULL;
FILE *afp = fopen(filename, "a+");

if (afp != NULL)
fp = freopen(NULL, "r+", afp);
if (fp == NULL) {
perror(filename);
fclose(afp);
return EXIT_FAILURE;
}
fwrite("Hey", 1, 3, fp);
fclose(fp);

(I might even declare those two FILE * variables on the same
line.)

But as I already pointed out, this code won't work with a pre-99
library, so one is better off with the variant that passes
`filename` as the first argument to freopen():

FILE *fp = fopen(filename, "a+");
if (fp != NULL)
fp = freopen(filename, "r+", fp);
// etc.

Note that if the first argument to freopen() is non-NULL, then
the stream pointed to by the third argument will almost
certainly be closed (implementations have some special cases
that create special cases for weird edgecases and [arguably]
broken behavior. For instance on some Unix variants
`freopen("/dev/stdin", "r", stdin);` needs to work without
destroying a process's standard input).
Post by Richard Heathfield
[snip]
- Dan C.
Ben Bacarisse
2017-08-03 12:54:14 UTC
Permalink
***@spitfire.i.gajendra.net (Dan Cross) writes:
<snip>
Post by Dan Cross
I rather thought that the thing Stuckle was upset about was the
thing I commented on (twice): that the call to `freopen` may
leak a stream.
FILE *fp = NULL;
FILE *afp = fopen(filename, "a+");
if (afp != NULL)
fp = freopen(NULL, "r+", afp);
if (fp == NULL) {
perror(filename);
fclose(afp);
return EXIT_FAILURE;
}
fwrite("Hey", 1, 3, fp);
fclose(fp);
(I might even declare those two FILE * variables on the same
line.)
This is the sort of place where I like a little helper function:

FILE *try_to_reopen(FILE *fp, const char *new_mode)
{
return fp ? freopen(NULL, new_mode, fp) : fp;
}

so you can write

FILE *fp = try_to_reopen(fopen(filename, "a+"), "r+");

If C had nested functions, I'd probably put it the calling function. It
always seems a little heavy to have this sort of one-liner at file
scope, possible with a forward declaration.

<snip>
--
Ben.
Dan Cross
2017-08-03 19:01:47 UTC
Permalink
Post by Richard Heathfield
<snip>
Post by Dan Cross
I rather thought that the thing Stuckle was upset about was the
thing I commented on (twice): that the call to `freopen` may
leak a stream.
FILE *fp = NULL;
FILE *afp = fopen(filename, "a+");
if (afp != NULL)
fp = freopen(NULL, "r+", afp);
if (fp == NULL) {
perror(filename);
fclose(afp);
return EXIT_FAILURE;
}
fwrite("Hey", 1, 3, fp);
fclose(fp);
(I might even declare those two FILE * variables on the same
line.)
FILE *try_to_reopen(FILE *fp, const char *new_mode)
{
return fp ? freopen(NULL, new_mode, fp) : fp;
}
so you can write
FILE *fp = try_to_reopen(fopen(filename, "a+"), "r+");
If C had nested functions, I'd probably put it the calling function. It
always seems a little heavy to have this sort of one-liner at file
scope, possible with a forward declaration.
It's unclear to me how this helps.

Consider the case where `fopen(filename, "a+")` fails and
returns NULL. Then `fp` is in `try_to_reopen` is NULL and the
ternary returns "NULL". Ok. Fine.

Next consider where `fopen` returns non-NULL and `freopen` also
returns non-NULL: then the return is a valid stream. Also file.

Now consider where `fopen` returns non-NULL and `freopen` fails
and returns NULL: we're in the same boat as my earlier code.
In particular, since the caller didn't save the value of `fp`,
we don't have access to a pointer to the stream to close it.

I agree that in a "real" program abstracting this into a helper
function is probably wise; but we've still got to be careful to
make sure we don't throw away the value of the FILE pointer in
the failure case. Perhaps something like this:

FILE *
maybeopen(const char *filename)
{
FILE *nfp, *fp = fopen(filename, "a+");
if (fp == NULL)
return NULL;
nfp = freopen(NULL, "r+", fp);
if (nfp == NULL)
fclose(fp);
return nfp;
}


- Dan C.
Ben Bacarisse
2017-08-03 19:25:43 UTC
Permalink
Post by Dan Cross
Post by Richard Heathfield
<snip>
Post by Dan Cross
I rather thought that the thing Stuckle was upset about was the
thing I commented on (twice): that the call to `freopen` may
leak a stream.
FILE *fp = NULL;
FILE *afp = fopen(filename, "a+");
if (afp != NULL)
fp = freopen(NULL, "r+", afp);
if (fp == NULL) {
perror(filename);
fclose(afp);
return EXIT_FAILURE;
}
<snip>
Post by Dan Cross
Post by Richard Heathfield
FILE *try_to_reopen(FILE *fp, const char *new_mode)
{
return fp ? freopen(NULL, new_mode, fp) : fp;
}
so you can write
FILE *fp = try_to_reopen(fopen(filename, "a+"), "r+");
If C had nested functions, I'd probably put it the calling function. It
always seems a little heavy to have this sort of one-liner at file
scope, possible with a forward declaration.
It's unclear to me how this helps.
<snip>
Post by Dan Cross
... consider where `fopen` returns non-NULL and `freopen` fails
and returns NULL: we're in the same boat as my earlier code.
In particular, since the caller didn't save the value of `fp`,
we don't have access to a pointer to the stream to close it.
Yes, you're right. I was *thinking* about the latter version but
re-cast only the former (now snipped). I originally wanted a function
to keep the second FILE * variable "tucked away" but then forgot all
about it! Now, as I go to re-write it, I see 7.21.5.4 p4:

"The freopen function first attempts to close any file that is
associated with the specified stream. Failure to close the file is
ignored."

with similar wording in C99 and C90 so it seems to be a non-issue,
unless I've also lost track of the issue itself!

<snip>
--
Ben.
Dan Cross
2017-08-03 20:09:09 UTC
Permalink
Post by Ben Bacarisse
Yes, you're right. I was *thinking* about the latter version but
re-cast only the former (now snipped). I originally wanted a function
to keep the second FILE * variable "tucked away" but then forgot all
"The freopen function first attempts to close any file that is
associated with the specified stream. Failure to close the file is
ignored."
with similar wording in C99 and C90 so it seems to be a non-issue,
unless I've also lost track of the issue itself!
Hmm; for some reason I had it in my mind that the langauge in
paragraph (3) contradicted this, but you are correct: there is
no such clause.

The implementations I'm looking at always seem to fclose() the
file on error; on success the underlying *file descriptor* will
not necessarily be closed, however, which makes this form less
racy than the alternatives where a filename is given. But it's
less portable. If this behavior were wider-spread and better
defined, then it would be the superior solution.

- Dan C.
Jerry Stuckle
2017-08-03 18:08:44 UTC
Permalink
Post by Dan Cross
Post by Richard Heathfield
<snip>
Post by Jerry Stuckle
Post by Dan Cross
: gaja; cat f.c
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
const char *filename = "foo.txt";
int
main(void)
{
FILE *fp = fopen(filename, "a+");
if (fp != NULL)
fp = freopen(NULL, "r+", fp);
if (fp == NULL) {
perror(filename);
return EXIT_FAILURE;
}
assert(fwrite("Hey", 1, 3, fp) == 3);
fclose(fp);
return EXIT_SUCCESS;
}
<snip>
Post by Jerry Stuckle
Now we know what kind of code YOU write!
Yes, we do, because he showed us, because he knows he can write code.
Indeed, for throw-away code written in response to a Usenet query, the
code looks reasonable to me except for the abuse of assert(), which I
suspect is tongue-in-cheek anyway.
The assert() thing was pure laziness on my part.
No, pure sloppiness - which has no place in production.
Post by Dan Cross
I rather thought that the thing Stuckle was upset about was the
thing I commented on (twice): that the call to `freopen` may
leak a stream.
FILE *fp = NULL;
FILE *afp = fopen(filename, "a+");
if (afp != NULL)
fp = freopen(NULL, "r+", afp);
if (fp == NULL) {
perror(filename);
fclose(afp);
return EXIT_FAILURE;
}
fwrite("Hey", 1, 3, fp);
fclose(fp);
(I might even declare those two FILE * variables on the same
line.)
That's one thing. But it's problems like this with "simple fixes" which
can cause major trouble later.
Post by Dan Cross
But as I already pointed out, this code won't work with a pre-99
library, so one is better off with the variant that passes
FILE *fp = fopen(filename, "a+");
if (fp != NULL)
fp = freopen(filename, "r+", fp);
// etc.
Note that if the first argument to freopen() is non-NULL, then
the stream pointed to by the third argument will almost
certainly be closed (implementations have some special cases
that create special cases for weird edgecases and [arguably]
broken behavior. For instance on some Unix variants
`freopen("/dev/stdin", "r", stdin);` needs to work without
destroying a process's standard input).
Post by Richard Heathfield
[snip]
- Dan C.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Jerry Stuckle
2017-08-03 18:05:44 UTC
Permalink
Post by Richard Heathfield
<snip>
Post by Jerry Stuckle
Post by Dan Cross
: gaja; cat f.c
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
const char *filename = "foo.txt";
int
main(void)
{
FILE *fp = fopen(filename, "a+");
if (fp != NULL)
fp = freopen(NULL, "r+", fp);
if (fp == NULL) {
perror(filename);
return EXIT_FAILURE;
}
assert(fwrite("Hey", 1, 3, fp) == 3);
fclose(fp);
return EXIT_SUCCESS;
}
<snip>
Post by Jerry Stuckle
Now we know what kind of code YOU write!
Yes, we do, because he showed us, because he knows he can write code.
Indeed, for throw-away code written in response to a Usenet query, the
code looks reasonable to me except for the abuse of assert(), which I
suspect is tongue-in-cheek anyway.
It's easy (and a bit pathetic) to criticise code in vague general terms,
but rather harder to write it, and harder still to criticise it in
specific terms that hold water in discussion with the experts in the
language that frequent this group.
Unlike the "real experts" with which you share a secret squirrel server,
the experts in this group actually exist, and arguing with them can be
educational, for those willing to be educated. You can't be educated by
a phantom.
Anyway, if you think I'm going to use the above reply as a hook on which
to hang another response to your chickening out of Dan's challenge,
don't worry. I'm not going to waste any more of my time on your pathetic
evasions on that subject.
Pace clc! Thunderbird has a "Mark as read" filter, so I don't have to
read this crap any more unless a good reason prompts me so to do.
Well, Richard, here's something for you to think about. At one time,
there were real experts in this newsgroup - people who write compilers
commercially, people who were on the standards committee and people who
were otherwise recognized experts.

But now all of those experts have fled his newsgroup and are on a
private server. Maybe there is a reason.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Ian Collins
2017-08-03 19:55:11 UTC
Permalink
Post by Jerry Stuckle
Well, Richard, here's something for you to think about. At one time,
there were real experts in this newsgroup - people who write compilers
commercially, people who were on the standards committee and people who
were otherwise recognized experts.
But now all of those experts have fled his newsgroup and are on a
private server. Maybe there is a reason.
They enjoy conversing with the Unicorns?
--
Ian
Dan Cross
2017-08-03 20:30:47 UTC
Permalink
Post by Ian Collins
Post by Jerry Stuckle
Well, Richard, here's something for you to think about. At one time,
there were real experts in this newsgroup - people who write compilers
commercially, people who were on the standards committee and people who
were otherwise recognized experts.
But now all of those experts have fled his newsgroup and are on a
private server. Maybe there is a reason.
They enjoy conversing with the Unicorns?
Clearly because they wanted to get away from Jerry Stuckle.

- Dan C.
Jerry Stuckle
2017-08-04 02:40:04 UTC
Permalink
Post by Dan Cross
Post by Ian Collins
Post by Jerry Stuckle
Well, Richard, here's something for you to think about. At one time,
there were real experts in this newsgroup - people who write compilers
commercially, people who were on the standards committee and people who
were otherwise recognized experts.
But now all of those experts have fled his newsgroup and are on a
private server. Maybe there is a reason.
They enjoy conversing with the Unicorns?
Clearly because they wanted to get away from Jerry Stuckle.
- Dan C.
Except I am a member of that group.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Jerry Stuckle
2017-08-04 02:39:48 UTC
Permalink
Post by Ian Collins
Post by Jerry Stuckle
Well, Richard, here's something for you to think about. At one time,
there were real experts in this newsgroup - people who write compilers
commercially, people who were on the standards committee and people who
were otherwise recognized experts.
But now all of those experts have fled his newsgroup and are on a
private server. Maybe there is a reason.
They enjoy conversing with the Unicorns?
They enjoy conversing with other knowledgeable people.
--
==================
Remove the "x" from my email address
Jerry Stuckle
***@attglobal.net
==================
Loading...