Sujet : Re: Buffer contents well-defined after fgets() reaches EOF ?
De : already5chosen (at) *nospam* yahoo.com (Michael S)
Groupes : comp.lang.cDate : 14. Feb 2025, 15:51:08
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <20250214165108.00002984@yahoo.com>
References : 1 2 3 4 5 6 7 8
User-Agent : Claws Mail 4.1.1 (GTK 3.24.34; x86_64-w64-mingw32)
On Thu, 13 Feb 2025 07:14:28 -0800
Tim Rentsch <
tr.17687@z991.linuxsc.com> wrote:
Michael S <already5chosen@yahoo.com> writes:
On Sun, 9 Feb 2025 17:22:43 -0800
Andrey Tarasevich <noone@noone.net> wrote:
On Sun 2/9/2025 5:06 PM, Andrey Tarasevich wrote:
On Sun 2/9/2025 3:52 PM, Lawrence D'Oliveiro wrote:
On Sat, 8 Feb 2025 23:12:44 -0800, Andrey Tarasevich wrote:
If `fgets` reads nothing (instant end-of-file), the entire
buffer remains untouched.
>
You mean, only a single null byte gets written.
>
No. The buffer is not changed at all in such case.
>
... which actually raises an interesting quiz/puzzle/question:
>
Under what circumstances `fgets` is expected to return an empty
string? (I.e. set the [0] entry of the buffer to '\0' and return
non-null)?
>
The only answer I can see right away is:
>
When one calls it as `fgets(buffer, 1, file)`, i.e. asks it to
read 0 characters.
>
This is under assumption that asking `fgets` to read 0 characters
is supposed to prevent it from detecting end-of-file condition or
I/O error condition. One can probably do some nitpicking at the
current wording... but I believe the above is the intent.
>
fgets() is one of many poorly defined standard library functions
inherited from early UNIX days. [...]
What about the fgets() function do you think is poorly defined?
Second question: by "poorly defined" do you mean "defined
wrongly" or "defined ambiguously" (or both)?
For starter, it looks like designers of fgets() did not believe in
their own motto about files being just streams of bytes.
I don't know the history, so, may be, the function was defined this way
for portability with systems where text files have special record-based
structure?
Then, everything about it feels inelegant.
A return value carries just 1 bit of information, success or failure.
So why did they encode this information in baroque way instead of
something obvious, 0 and 1?
Appending zero at the end also feels like a hack, but it is necessary
because of the main problem. And the main problem is: how the user is
supposed to figure out how many bytes were read?
In well-designed API this question should be answered in O(1) time.
With fgets(), it can be answered in O(N) time when input is trusted to
contain no zeros. When input is arbitrary, finding out the answer is
even harder and requires quirks.
What is my suggestion for alternative?
Without too deep thinking I'd suggest (ignoring issues of restrict for
sake of brevity) function that gives the same answer like foo() below,
but hopefully does it faster:
char* foo(FILE* fp, char* dst, int count, char last_c)
{
while (count > 0) {
int ch = fgetc(fp);
if (ch == EOF) {
if (ferror(fp))
dst = NULL;
break;
}
*dst++ = ch;
if (ch == last_c)
break;
--count;
}
return dst;
}
The function foo() is more generic than fgets(). For use instead of
fgets() it should be accompanied by standard constant EOL_CHAR.
I am not completely satisfied with proposed solution. The API is
still less obvious than it could be. But it is much better than fgets().