Retiring gets

Walter Bright bright at Data-IO.COM
Tue Dec 6 04:26:32 AEST 1988


In article <649 at umecs.cs.umu.se> eao at zeus.umu.se () writes:
>When I retire gets() I would like a function like this fgetline() to replace
>it. Are there any drawbacks I have missed? or is recursion to simple to use
>in problems like this? (To parse a input in search of newline.)
>/*
> * char *fgetline(file) 
> *	FILE *file;
> * returns a null terminated line from stdin allocated with *some_malloc
> */
> [ code deleted for brevity ]

My objections to the code presented are:
	1. It depends on static variables. This makes it non-reentrant, and
	   therefore a bug waiting to happen on multi-threaded systems
	   like OS2.
	2. If a 0 byte is read, the behavior is undefined.

So I present this:

   size_t fgetline(FILE *file, char **pbuffer, size_t *pbufsize);

Semantics:
	Reads a line from the file. The end of the line is defined by
	reading a \n, or encountering the EOF. If a \n was read, it's
	included in the read line. 0s may also be read, and are included
	in the read line, thus the count of bytes read that's returned
	may be larger than that obtained by strlen(*pbuffer).

Input:
	file		input stream pointer
	pbuffer		pointer to the buffer pointer. If the buffer pointer
			is NULL, one is malloc'd. The buffer pointer must
			be NULL or point to data allocated by malloc, realloc
			or calloc.
	pbufsize	pointer to variable containing the allocated length
			of the buffer
Output:
	*pbuffer	If the buffer needs to be realloc'd, this is set
			to the new buffer.
	*pbufsize	Set to the size of the buffer, which may be larger
			than the actual amount of data in the buffer.
Errors:
	If EOF or an error occurs while a partially read line is being
	read, it is treated as the end of the line.
	If no bytes are read yet, 0 is returned.

	If malloc or realloc run out of memory, fgetline will return what
	it's already got, and errno will be set.
Returns:
	number of bytes read into *pbuffer, excluding terminating 0

Example (in ANSI C):

	typefile(FILE *f)	/* copy file to stdout	*/
	{	char *buffer = NULL;
		size_t buflen = 0;
		size_t linelen;

		while (1)
		{	linelen = fgetline(f,&buffer,&buflen);
			if (linelen == 0)	/* error or EOF	*/
				break;
			if (fwrite(buffer,1,linelen,stdout) != linelen)
				break;		/* error	*/
		}
		free(buffer);
	}

Put a quarter in the juke,
Boogie 'till yah puke.



More information about the Comp.lang.c mailing list