C
Chris Torek
The [file-reading] function receives a file name Chuck. There is NO
keyboard input...
What if the file name is "CON:" or "CON" or "/dev/tty" or "/tyCo/0"
or whatever external file name is used to represent "keyboard input"
on that system?
The way to read the whole text file is to read the whole text file.
int read_whole_text_file(const char *fname, char **memp, size_t *sizep) {
FILE *fp; /* the open file */
char *mem, *new; /* memory regions (current and new) */
size_t memsize, newsize; /* sizes of regions (current & new) */
size_t tot; /* total bytes read so far */
size_t rdattempt, rdresult; /* argument & result for fread */
*memp = NULL; /* optional */
*sizep = NULL; /* optional */
fp = fopen(fname, "r");
if (fp == NULL)
return UNABLE_TO_OPEN;
memsize = INITIAL_BLOCK_SIZE;
mem = malloc(memsize);
if (mem == NULL) {
fclose(fp);
return UNABLE_TO_GET_MEM;
}
tot = 0;
/* loop, reading what we can, until we get less than we ask for */
for (; {
rdattempt = memsize - tot;
rdresult = fread(mem + tot, 1, memsize - tot, fp);
if (rdresult < rdattempt)
break;
tot += rdresult;
newsize = memsize * 2; /* use whatever strategy you like */
new = realloc(mem, newsize);
if (new == NULL) {
/*
* Here, I choose to discard the data read so far.
* You have other options, including returning the
* partial result, or allocating a smaller incremental
* amount of memory.
*/
free(mem);
fclose(fp);
return UNABLE_TO_GET_MEM;
}
mem = new;
memsize = newsize;
}
/* we reach this line only when fread() stopped due to EOF or error */
/* if (ferror(fp)) ... -- optional, handle read-error */
/* optional (but required if adding '\0') */
new = realloc(mem, tot); /* or tot+1 if you want to add a '\0' */
if (new == NULL) {
/* since I'm not adding the '\0', can just use existing mem */
} else {
mem = new;
/* mem[tot] = '\0'; -- to add '\0' */
}
/* set return-value parameters */
*memp = mem;
*sizep = tot;
return SUCCEEDED;
}
(The code above is completely untested. Note that if you want to
add a '\0', you can subtract 1 from "rdattempt", and still skip
the final realloc() or allow it to fail, as long as INITIAL_BLOCK_SIZE
and the newsize computation allow forward progress with this
subtraction. Of course, you also have to define the initial block
size and the three return values -- one success, two error codes.)