[comp.lang.c] Yet another fgetline

ian@ipse2pt5.cs.man.ac.uk (Ian Cottam) (02/08/91)

I typed this in because I waited a while and no one else did.
(Of course, five minutes ago I just got one over the net :-) !)
Anyway, here it is; in case people would like something to
criticise.

Thanks to a local user for comments (Stephen Bevan). K&R I people
will have to hack-out the ANSI stuff.

___________________________________________________cut here_____________

/* Ian Cottam FEB 91 -- donated to public domain. */

#include <stdio.h>
#include <string.h>
#include <stddef.h>


/*
 * fgetline(FILE *f) - returns a pointer to the start of a line read
 *	     	       from f, or the null pointer on any error or eof.
 *		       Like fgets(), you may well want to get rid of the
 *		       \n at the end (if any), and check feof(f)! This is
 *		       not a wonderful interface, but it mimics fgets().
 *		       Caller should free memory if desired.
 */

#ifndef FGETLINE_BUFFSIZE
# define FGETLINE_BUFFSIZE 20
#endif
#if FGETLINE_BUFFSIZE < 2
#error FGETLINE_BUFFSIZE must be > 1
#endif


char *
fgetline(FILE *f)
{
	extern void *malloc(size_t);
	extern void free(void *);
	char *buffer= (char *)malloc(FGETLINE_BUFFSIZE);
	char *result;

	if (buffer == NULL) return NULL; /*out of memory*/
	result= fgets(buffer, FGETLINE_BUFFSIZE, f);
	if (result == NULL) return NULL; /* either error or at eof */
	if (buffer[strlen(buffer)-1] != '\n' && !feof(f)) {
		/* longer line than buffer can hold */
		char *restofline= fgetline(f);
		char *longline;
		if (restofline == NULL) return NULL; /*eof or error*/
		longline= (char *)malloc(strlen(buffer)+strlen(restofline)+1);
		if (longline == NULL) return NULL; /*out of memory*/
		(void) strcat(strcpy(longline, buffer), restofline );
		free(restofline);
		free(buffer);
		return longline;
	}
	else
		return buffer;
}
--
Ian Cottam, Room IT209, Department of Computer Science,
University of Manchester, Oxford Road, Manchester, M13 9PL, U.K.
Tel: (+44) 61-275 6157         FAX: (+44) 61-275-6280
Internet: ian%cs.man.ac.uk;  JANET: ian@uk.ac.man.cs

wollman@emily.uvm.edu (Garrett Wollman) (02/11/91)

Well, here is my version of the get-an-indefinite-length-string
routine.  I call it frgets, and it acts very much like gets().  I uses
malloc to get memory.  [Please note that I don't claim that it's at
all efficient, but it makes the most sense to me.  PErhaps a good
compiler can make something of it.]

#include <stdio.h>

static char *frgets_h(FILE *fp,int accum) {
  int c = fgetc(fp);
  char *retval;

  if((c == EOF)||(c == '\n')) {
    retval = malloc(accum+1);
    if(retval)
      retval[accum] = '\0';
    return(retval);
  }

  /* we didn't get an EOF or newline */
  retval = frgets_h(fp,accum+1);
  if(retval)
    retval[accum] = (char)c;  /* this may need fudging for signed chars < 0 */

  return(retval);
}

char *frgets(FILE *fp) {
  return(frgets_h(fp,0));
}

----------

Note that, if there is not enough memory available deep in the
recursion, then you lose all those characters that were read it.  Too
bad.  I think that if you can't malloc enough for a simple string,
that's probably the worst of your problems.  No doubt all the other
readers of comp.lang.c will come down from on high and condemn this.
That's too bad too.

-GAWollman


Garrett A. Wollman - wollman@emily.uvm.edu

Disclaimer:  I'm not even sure this represents *my* opinion, never
mind UVM's, EMBA's, EMBA-CF's, or indeed anyone else's.