On 04/11/2012 12:43 PM, John Reye wrote:
> Hello,
>
> The last character read from fgets(buf, sizeof(buf), inputstream) is:
> '\n'
> OR
> any character x, when no '\n' was encountered in sizeof(buf)-1
> consecutive chars, or when x is the last char of the inputstream
>
> ***How can one EFFICIENTLY determine if the last character is '\n'??
That's relatively easy - so long as you don't need to know where the
'\n' is.
> "Efficiently" means: don't use strlen!!!
>
> I only come up with the strlen method, which - to me - says that fgets
> has a bad design.
The following approach uses strchr() rather than strlen(), so it
technically meets your specification. However, I presume you would have
the same objections to strchr() as you do to strlen(). I'd like to point
out, however, that it uses strchr() only once per file, which seems
efficient enough for me. If you're doing so little processing per file
that a single call to strchr() per file adds significantly to the total
processing load, I'd be more worried about the costs associated with
fopen() and fclose() than those associated with strchr().
The key point is that a successful call to fgets() can fail to read in
an '\n' character only if fgets() meets the end of the input file, or
the end of your buffer, both of which can be checked for quite
efficiently. If it reaches the end of your buffer, there's one and only
one place where the '\n' character can be, if one was read in.
Therefore, it's only at the end of the file that a search is required.
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> int main(int argc, char *argv[])
> {
> char buf[6];
> FILE *fp = stdin;
buf[(sizeof buf)-1] = 1; // any non-zero value will do.
> while (fgets(buf, sizeof(buf), fp)) {
const char *prefix =
(buf[(sizeof buf)-1] == '\0' && buf[(sizeof buf)-2] != '\n'
|| feof(fp) && !strchr(buf, '\n')) ? "no " : "";
printf("Got a line which ends with %snewline: %s\n",
prefix, buf);
buf[(sizeof buf)-1] = 1;
> }
>
>
> return EXIT_SUCCESS;
> }
>
>
>
> A well-designed fgets function should return the length of characters
> read, should it not??
>
> Please surprise me, that there is a way of efficiently determining the
> number of characters read. 
> I've thought of ftell, but I think that does not work with stdin.
>
> Because right now, I think that fgets really seems useless.
> Why is the standard C library so inefficient?
Measure the inefficiency before deciding whether or not it's useless.
You may be surprised.
> Do I really have to go about designing my own library?
You don't need an entire library; a function equivalent to fgets() that
calls getc() and provides the information you're looking for wouldn't be
too difficult to write, and should compile fairly efficiently.