From: Malcolm McLean on

"Richard Harter" <cri(a)tiac.net> wrote in message
> I disagree. A common usage is read all of the lines of a file
> and keep them in memory. If the buffers holding the lines are
> all maximum size then you get memory bloat. The purpose of
> maxsize is to serve as a sanity check.
>
That's a good point.
If we're going to support reading the whole file, efficiently, which is
worth doing, it means we should also support reading in a file structure in
only a few lines.

while(1)
{
fg = fgetline(fptr, 0, 0, FG_MAXSIZE);
if(fg.status != fg_normal)
{
if(fg.status == end_of_file)
break;
/* error handling code */
}
temp = realloc(lines, (N+1) * sizeof(char *));
if(!temp)
{
/* error handling code */
}
lines = temp;
lines[N] = fg.line;
N++;
}

it's not an utter disaster, but it is too much.

How about.

while(line = fg_getline(fptr, 0, 0, FG_MAXSIZE))
{
temp = realloc(lines, (N+1) * sizeof(char *));
if(!temp)
{
/* error-handline code here */
}
lines = temp;
lines[N] = line;
N++;
}
/* error handler if fg_getline encounters a problem */
if(fg_error(fptr))
{
switch(fg_error(fptr))
{
}
}

Don't really like that either. We've got the while() actually testing the
condition, and we've moved some but not all of the error handling code out
of the loop, but it still isn't a boiler-plate idiom.

The other alternative is to have two functions, one for getting a single
line, one for reading a whole file.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

From: CBFalconer on
Malcolm McLean wrote:
> "Richard Harter" <cri(a)tiac.net> wrote in message
>
>> I disagree. A common usage is read all of the lines of a file
>> and keep them in memory. If the buffers holding the lines are
>> all maximum size then you get memory bloat. The purpose of
>> maxsize is to serve as a sanity check.
>
> That's a good point. If we're going to support reading the whole
> file, efficiently, which is worth doing, it means we should also
> support reading in a file structure in only a few lines.
>
.... snip code example ...

Here is another example, from the testing suite for ggets. Note
the simplicity and safety of capturing the entire file in memory
(assuming sufficient memory exists). No excess memory is used.
ggets.zip is available at:

<http://cbfalconer.home.att.net/download>

/* File freverse.c - testing ggets */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ggets.h"

typedef struct node {
struct node *next;
char *ln;
} node, *nodeptr;

/* ======================= */
/* reverse string in place */
/* return length of string */
size_t revstring(char *stg)
{
char *last, temp;
size_t lgh;

lgh = strlen(stg);
if (lgh > 1) {
last = stg + lgh; /* points to '\0' */
while (--last > stg) {
temp = *stg; *stg++ = *last; *last = temp;
}
}
return lgh;
} /* revstring */

/* ======================= */
/* reverse file */
int main(void)
{
char *line;
nodeptr root, temp;
int lncount, chcount;

fprintf(stderr, "Reversing stdin to stdout\n");
root = NULL;
lncount = chcount = 0;
while (0 == ggets(&line)) {
if (NULL == (temp = malloc(sizeof *temp))) {
fprintf(stderr, "Out of memory\n");
return EXIT_FAILURE;
}
temp->next = root;
chcount += revstring(line);
lncount++;
temp->ln = line;
root = temp;
}

/* file captured, and in reverse ordered list */

while (root) {
(void)puts(root->ln);
temp = root;
root = root->next;
free(temp->ln);
free(temp);
}
fprintf(stderr, "%d chars in %d lines\n", chcount, lncount);
return 0;
} /* main */
/* END freverse.c - testing ggets */

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>



--
Posted via a free Usenet account from http://www.teranews.com

From: �a/b on
In data Sun, 14 Oct 2007 11:23:16 -0400, CBFalconer scrisse:
>/* File freverse.c - testing ggets */
>
>#include <stdio.h>
>#include <stdlib.h>
>#include <string.h>
>#include "ggets.h"
>
>typedef struct node {
> struct node *next;
> char *ln;
>} node, *nodeptr;
>
>/* ======================= */
>/* reverse string in place */
>/* return length of string */
>size_t revstring(char *stg)
>{
> char *last, temp;
> size_t lgh;
>
> lgh = strlen(stg);
> if (lgh > 1) {
> last = stg + lgh; /* points to '\0' */
> while (--last > stg) {
> temp = *stg; *stg++ = *last; *last = temp;
> }
> }
> return lgh;
>} /* revstring */
>
>/* ======================= */
>/* reverse file */
>int main(void)
>{
> char *line;

so it is ok even if here line!=0 ?

> nodeptr root, temp;
> int lncount, chcount;
>
> fprintf(stderr, "Reversing stdin to stdout\n");
> root = NULL;
> lncount = chcount = 0;
> while (0 == ggets(&line)) {
> if (NULL == (temp = malloc(sizeof *temp))) {
> fprintf(stderr, "Out of memory\n");
> return EXIT_FAILURE;
> }
> temp->next = root;
> chcount += revstring(line);
> lncount++;
> temp->ln = line;
> root = temp;
> }
>
> /* file captured, and in reverse ordered list */
>
> while (root) {
> (void)puts(root->ln);
> temp = root;
> root = root->next;
> free(temp->ln);
> free(temp);
> }
> fprintf(stderr, "%d chars in %d lines\n", chcount, lncount);
> return 0;
>} /* main */
>/* END freverse.c - testing ggets */
>
>--
> Chuck F (cbfalconer at maineline dot net)
> Available for consulting/temporary embedded and systems.
> <http://cbfalconer.home.att.net>

From: Richard Harter on
On Sun, 14 Oct 2007 07:52:17 +0100, "Malcolm McLean"
<regniztar(a)btinternet.com> wrote:

>
>"Richard Harter" <cri(a)tiac.net> wrote in message
>> I disagree. A common usage is read all of the lines of a file
>> and keep them in memory. If the buffers holding the lines are
>> all maximum size then you get memory bloat. The purpose of
>> maxsize is to serve as a sanity check.
>>
>That's a good point.
>If we're going to support reading the whole file, efficiently, which is
>worth doing, it means we should also support reading in a file structure in
>only a few lines.
>
>while(1)
>{
> fg = fgetline(fptr, 0, 0, FG_MAXSIZE);
> if(fg.status != fg_normal)
> {
> if(fg.status == end_of_file)
> break;
> /* error handling code */
> }
> temp = realloc(lines, (N+1) * sizeof(char *));
> if(!temp)
> {
> /* error handling code */
> }
> lines = temp;
> lines[N] = fg.line;
> N++;
>}
>
>it's not an utter disaster, but it is too much.
>
>How about.
>
>while(line = fg_getline(fptr, 0, 0, FG_MAXSIZE))
>{
> temp = realloc(lines, (N+1) * sizeof(char *));
> if(!temp)
> {
> /* error-handline code here */
> }
> lines = temp;
> lines[N] = line;
> N++;
>}
>/* error handler if fg_getline encounters a problem */
>if(fg_error(fptr))
>{
> switch(fg_error(fptr))
> {
> }
>}
>
>Don't really like that either. We've got the while() actually testing the
>condition, and we've moved some but not all of the error handling code out
>of the loop, but it still isn't a boiler-plate idiom.
>
>The other alternative is to have two functions, one for getting a single
>line, one for reading a whole file.

To be honest, I don't much like either alternative. However that
may merely be a case of I like my wheel better. I have come up
with an alternative that I like, but I haven't gone through the
work of writing it all up. The essence is to have three
routines, an open, a read, and a close, along with an include
file, and an opaque struct to hold state. The usage looks
something like this:

#include "rdfline.h"
....
struct rdf_info *rdf; /* Opaque, allocated by fg_open */
FILE * fptr;
char * line;
size_t len;
int status;

...

if (!rdf_open(rdf,fptr,&line,&len,&status,maxsize,flags)) {
/* Can't open - probably fopen failed */
/* Do something about problem and goaway */
}
...
while (rdf_read(rdf)) {
/* Optional error test code */
/* Do stuff with line */
}
/* Optional error test code */
rdf_close(rdf);

The flags variable uses various bits to set flags that control
things like error handling, memory management, and whether to
produce clean or transient copies. Passing in a 0 uses the
defaults which are:

(a) The package does nothing about errors (writing to a log file,
etc) except set an error bit in the status word.

(b) A clean copy is produced; the user is responsible for freeing
it.

(c) rdf_read reads as much as it can and doesn't worry about a
premature EOF or memory failure - set a flag bit if you want it
to care.

More later.




Richard Harter, cri(a)tiac.net
http://home.tiac.net/~cri, http://www.varinoma.com
In the fields of Hell where the grass grows high
Are the graves of dreams allowed to die
From: Malcolm McLean on

"CBFalconer" <cbfalconer(a)yahoo.com> wrote in message
> Here is another example, from the testing suite for ggets. Note
> the simplicity and safety of capturing the entire file in memory
> (assuming sufficient memory exists). No excess memory is used.
> ggets.zip is available at:
>
The ggets() interface isn't too bad at all. I didn't think so before this
thread, but looking at the alternatives, its deficiencies are quite minor.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8 9 10
Prev: problem analysis chart
Next: Please help!