Sujet : Re: Whaddaya think?
De : already5chosen (at) *nospam* yahoo.com (Michael S)
Groupes : comp.lang.cDate : 16. Jun 2024, 22:45:33
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <20240617004533.00002093@yahoo.com>
References : 1 2 3 4 5 6 7 8 9 10 11 12 13
User-Agent : Claws Mail 4.1.1 (GTK 3.24.34; x86_64-w64-mingw32)
On Sun, 16 Jun 2024 17:37:34 +0200
Janis Papanagnou <janis_papanagnou+
ng@hotmail.com> wrote:
On 16.06.2024 13:31, Michael S wrote:
On Sun, 16 Jun 2024 12:03:21 +0200
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
On 16.06.2024 11:38, Michael S wrote:
>
Again; which ones?
>
Janis
[...]
>
The main misconceptions are about what is returned by fgets() and by
realloc().
fgets() returns its first argument in all cases except EOF or FS
read error. That includes the case when the buffer is too short to
accommodate full input line.
fgets() return s on success, and NULL on error or when end
of file occurs while no characters have been read.
I am interested in the success case, thus "fgets() != NULL".
The buffer size is controlled by the second function parameter.
With realloc() there are two issues:
1. It can sometimes return its first argument, but does not have
to. In scenario like yours it will return a different pointer quite
soon. 2. When realloc() returns NULL, it does not de-allocate its
first argument.
The second case, of course, is not important in practice, because in
practice you're very unlikely to see realloc() returning NULL, and
if nevertheless it did happen, you program is unlikely to survive
and give meaningful result anyway. Still, here on c.l.c we like to
pretend that we can meaningfully handle allocation failures.
You may provide "correct" code (if you think mine is wrong). Or just
inspect how it behaves; here's the output after two printf's added:
$ printf "123 456 789 101112 77 88 99 101 999" | realloc
+++>123 456 78<+++
===>123 456 78<===
+++>9 101112 7<+++
===>123 456 789 101112 7<===
+++>7 88 99 10<+++
===>123 456 789 101112 77 88 99 10<===
+++>1 999<+++
===>123 456 789 101112 77 88 99 101 999<===
123 456 789 101112 77 88 99 101 999
The +++data+++ is the chunk read, and the ===data=== is the overall
buffer content, and the final line again the result (as before, with
the added newline as documented for puts()).
Even though my code is just an "ad hoc test code" to demonstrate the
procedure I outlined - and as such test code certainly lacking quite
some error handling and much more - it does exactly what I intended it
to do, and what I've implemented according to what I read in the man
pages. I cannot see any "misconception", it does what was _intended_.
There's indeed one point that I _deliberately_ ignored for the test
code; actually the point you mentioned as "not important in practice".
Again: You may provide "correct" code (if you think mine is "wrong"),
or "better" code, usable for production instead of a test code.
But your tone and statements were (as observed so often) inadequate;
I quote from your post that started the subthread:
"However it looks unlikely that it does what you meant for it to do."
>
Did you consider that, may be, your understanding of C library is
inadequate?
It does exactly what I meant to do (as you can see in the logs above).
>
Janis
The only thing I see in your logs is that your testing skills are on par
with your coding skills.
I am not quite sure what your code is supposed to do.
However, my impression was that we wanted to read text file line by
line and to process lines separately. You code certainly does not do
it. As I said above it contains several mistakes, including one that is
particularly serious and hard to diagnose - a use of de-allocated
buffer.
Below is an example of how to do it correctly.
It's not the only possible method, but any correct method would have
similar complexity.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
const int sz_incr = 10;
size_t bufsz = 32;
char* buffer = malloc(bufsz);
if (!buffer) {
perror("malloc()");
return 1;
}
size_t rdi = 0;
int err = 0;
for (size_t line_i = 1; ;) {
buffer[bufsz-1] = 1; // set guard
if (!fgets(&buffer[rdi], bufsz-rdi, stdin))
break; // eof or error
if (buffer[bufsz-1] != 0 || buffer[bufsz-2] == '\n') {
// Full line - we can process it here
// As an example, let's print our line as hex
printf("%10zu:", line_i);
size_t len = (char*)memchr(&buffer[rdi], '\n',
bufsz-rdi-1)+1-buffer; for (size_t i = 0; i < len; ++i)
printf(" %02x", (unsigned char)buffer[i]);
printf("\n");
rdi = 0;
++line_i;
} else {
// line is longer then bufsz-1
rdi = bufsz-1;
bufsz += sz_incr;
char* tmp = realloc(buffer, bufsz);
if (!tmp) {
perror("realloc()");
err = 1;
break;
}
buffer = tmp;
}
}
free(buffer);
if (ferror(stdin)) {
perror("fgets(stdin)");
err = 2;
}
return err;
}