On 12/17/2010 12:08 PM, Francis Moreau wrote:
> Eric Sosman<> writes:
>
>> On 12/17/2010 5:26 AM, Francis Moreau wrote:
>>> Hello,
>>>
>>> I think this is undefined behaviour, but I prefer asking just in case
>>
>>> I'm missing something.
>>>
>>> Consider that a line is 8 characters long (including newline) and I pass
>>> to fgets a buffer which can store at least 32 characters.
>>>
>>> Can I assume that if fgets reads that line, then it won't modify any
>>> characters in the buffer whose offset is greater than 8 ?
>>
>> As I understand it, fgets() is allowed to scribble on any or all
>> of the buffer's bytes, except that if there's an immediate end-of-file
>> it will touch none of them.
>>
>> The wider question, I think, is "Why do you care?" Is this part
>> of a stratagem for dealing with lines that might contain '\0' or
>> some such?
>
> I'm wondering what is the most efficient way to see if fgets() read an
> entire line.
>
> For example consider this:
>
> char buf[16], *p;
> FILE *fp;
>
> /* initialise fp */
>
> p = fgets(buf, sizeof(buf), fp);
>
> from here you can do this:
>
> /* check if the line is entirely read */
> len = strlen(buf);
> if (len == 15&& buf[14] != '\n') {
> /* the line has not been read completely */
>
> }
Possibly simpler, certainly briefer:
if (strchr(buf, '\n') == NULL) {
// incomplete line (or missing '\n' at EOF)
}
> but you could also do:
>
> buf[14] = '\n';
> p = fgets(buf, sizeof(buf), fp);
> if (buf[14] != '\n') {
> /* the line has not been read completely */
... or consisted of thirteen characters plus '\n', and fgets()
dutifully set buf[14] = '\0'.
> }
>
> which seems more efficient.
Two thoughts: First, I/O is many orders of magnitude slower
than the CPU, so saving a few milliquavers probably just gets you
back to the idle loop sooner. Second, if it's really important to
get the answer ASAP you may be better off using getc() in a loop
and testing directly, rather than calling fgets() and then using
CSI forensics to post-analyze what it did.
It Would Be Nice If fgets() returned something more than a
single bit's worth of information, like the number of bytes read,
say, or a pointer to the '\0'. Unfortunately, the less-helpful
interface was already well-established before standardization got
underway, and (like some other features of the library) we're all
stuck with it.
Accept my best wishes for the holiday season, to you and yours
and all your vermiform appendices.
--
Eric Sosman
lid