similar Perl data structure?

L

Lew Pitcher

Keith said:
jacob navia said:
Keith Thompson wrote:
Because the library is not available,
because the project doesn't want to use public
domain source code for copyright reasons,
and for many other reasons
[...]

I'm just going to address this one point:

What "copyright reasons" could there be for not wanting to use public
domain source code? (Note that "public domain" is not the same as
"open source".)
Many. If you are selling your sources, you can't sell
that part.

Why not?

[...]

Obviously because they are in the public domain!

Nonsense. "Public domain" specifically means that the author (and any other
stakeholders) have explicitly given up any rights to the work. There
are /no/ restrictions as to what you can do with "public domain" source
code; you are /not/ obliged to divulge it, or even acknowledge that you are
using it. It's yours to use in any way you see fit.


--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
 
J

jacob navia

Lew said:
Nonsense. "Public domain" specifically means that the author (and any other
stakeholders) have explicitly given up any rights to the work. There
are /no/ restrictions as to what you can do with "public domain" source
code; you are /not/ obliged to divulge it, or even acknowledge that you are
using it. It's yours to use in any way you see fit.
Sure. But imagine somebody that buys some code for $$$ dollars.
Reading it, he/she discovers:

WHAT????
This guy has included public domain code in the stuff that is
selling me!!!

And I paid US$ XXX the line!!!

I will sue him.


Then, you have to put the public domain code in a separate
file, etc etc. A hassle.
 
L

Lew Pitcher

Sure. But imagine somebody that buys some code for $$$ dollars.
Reading it, he/she discovers:

WHAT????
This guy has included public domain code in the stuff that is
selling me!!!

And I paid US$ XXX the line!!!

I will sue him.

And his lawyer tells him that he has no recourse as such use of PD code is
entirely legal and aboveboard. Then his lawyer charges him US$ XXX for the
consultation.

If he persists, the judge tosses the suite out as frivolous, and grants
relief to the defendant, including court costs.
Then, you have to put the public domain code in a separate
file, etc etc. A hassle.

Again, nonsense. That's your paranoia talking, not the law.

--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
 
G

Guest

Keith said:
jacob navia said:
William Pursell wrote:
If we would have a simple
getline()
function in the standard, we wouldn't have to rewrite each time
a new one.
Sigh.  Really, do you really rewrite it each time you need it?
I thought that just in this thread you mentioned using CBF's
ggets.  Clearly you understand the concept of libraries.
Why do you insist on perpetuating the ridiculous idea
that people "rewrite each time".
Because the library is not available,
because the project doesn't want to use public
domain source code for copyright reasons,
and for many other reasons [...]

I'm just going to address this one point:
What "copyright reasons" could there be for not wanting to use public
domain source code?  (Note that "public domain" is not the same as
"open source".)

Many. If you are selling your sources, you can't sell
that part. And most of those "reasons" are just paranoia from
managers that do not understand all legal issues involved and do
not want to take any risks.


http://en.wikipedia.org/wiki/Public_domain
 
I

Ian Collins

jacob said:
The problem with C is not the language itself.

In this example, part of the problem is the language.

One big difference between the two versions is the user of your C
function has to remember to free all the allocated memory (which the
example fails to do). The C++ version takes care of this though those
(in your opinion) horrible destructors.
 
K

Keith Thompson

jacob navia said:
Sure. But imagine somebody that buys some code for $$$ dollars.
Reading it, he/she discovers:

WHAT????
This guy has included public domain code in the stuff that is
selling me!!!

And I paid US$ XXX the line!!!

I will sue him.


Then, you have to put the public domain code in a separate
file, etc etc. A hassle.

Your own lcc-win includes Chuck Falconer's public domain ggets.
<http://www.q-software-solutions.de/products/lcc-win32/changelog.shtml>

As I recall, lcc-win is not free for commercial use, so, unless I've
missed something, you're charging money for a software package that
includes public domain software. And there's nothing wrong with that,
either legally or ethically. (You're even allowed to omit the
readme.txt that normally accompanies it.)
 
J

jacob navia

Ian said:
In this example, part of the problem is the language.

One big difference between the two versions is the user of your C
function has to remember to free all the allocated memory (which the
example fails to do). The C++ version takes care of this though those
(in your opinion) horrible destructors.

Not if you use lcc-win and use the GC.

But there is an important point in your objection. Either a function
to free the memory should be supplied or a SINGLE call to free
should be required. I am rewriting the program to use a different
algorithm. Instead of reading line by line I read it in a single
read, then count the lines, and allocate a single buffer with
all the pointers AND the data.

That should be more efficient and gives an easier interface.

But as you see if you use the GC, you do not need destructors
in this case!
 
S

Stefan Ram

ela said:
Is there any similar structure in C that I can easily get the strings in a
file like:
Example file
bicycle
bus
ferry
plane
train
so I can print them generically? In Perl, I just read them into an array,
e.g. @vehicle
then get them back by foreach. Thanks for telling me if there's similar
handy function in C

Actually it is very easy in C, you just reserve a buffer of
the appropriate size and then, er, simply read the lines into
the buffer. And you're done!

My attempt follows - written in ISO/IEC 9899:1999 (E) C,
without the need for any additional libraries.

I have the impression that I made a lot of off-by-1 errors,
which I hid under some dirty hacks. There also are still some
redundancies in the code. But I do not have the time for a
code clean-up right now.

However, I would be pleased to read how to improve the
following code.

For the program to be self-contained, it first /writes/ the file
to the path »tmp.txt«.

WARNING: this will overwrite any existing file named »tmp.txt«
in the current directory.

»writelines« is used to create the file.
»getc_count« gets the size of the file to be read.
»readfile« reads the whole file into a buffer.
»getlines« fills in the array of lines.
»printlines« then prints these lines.

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

int getc_count
( const char * const path, size_t * const result )
{ FILE * input = fopen( path, "rb" );
size_t size = 0;
int failed = 1;
int error = 0;
int overflow = 0;
if( input )
{ int ch = getc( input );
while( ch != EOF )
{ if( !++size )overflow = 1, ch = EOF;
else ch = getc( input ); }
if( ferror( input ))error = 1;
if( fclose( input )== 0 && !overflow && !error )failed = 0; }
*result = size;
return failed; }


int writelines
( char const * const path,
char const * const * const source,
size_t const n )
{ FILE * const file = fopen( path, "w" );
int result = -1;
if( file )
{ for( size_t i = 0; i < n; ++i )
if
( strlen( source[ i ])+ 1 !=
( size_t )fprintf( file, "%s\n", source[ i ]))
{ result = 2; break; }
if( fclose( file ))result = 3;
if( result == -1 )result = 0;
else result = 1; }
else result = 19;
return result; }

int readfile2
( char const * const path, char * * const buffer,
size_t * const linecount,
size_t * const size )
{ int result = -1;
char * const buff = *buffer;
char * p = buff;
size_t s = 0;
{ FILE * input = fopen( path, "r" );
if( input )
{ int ch = getc( input );
if( ch == '\n' ){ ch = 0; ++*linecount; }
if( !++s )result = 8, ch = EOF;
else if( s >= *size )result = 13, ch = EOF;
else if( ch != EOF )*p++ = ch;
while( ch != EOF )
{ ch = getc( input );
if( ch == '\n' ){ ch = 0; ++*linecount; }
if( !++s )result = 5, ch = EOF;
else if( s - 1 > *size )result = 6, ch = EOF;
else if( ch != EOF )*p++ = ch; }
if( ferror( input ))result = 7;
if( fclose( input ))result = 9;
if( result == -1 )
{ if( !++s )result = 10;
else if( s - 2 > *size )result = 11;
else
{ *p++ = 0; result = 0;
*size = p - buff; }}}
else result = 12; }
return result; }

int readfile1
( char const * const path, char * * const buffer,
size_t * const linecount,
size_t * const size )
{ int result = -1;
if( *buffer = malloc( *size + 3 ))
{ result = readfile2( path, buffer, linecount, size );
if( result )
{ free(( void * )*buffer ); *buffer = 0; }}
else result = 4;
return result; }

int readfile
( char const * const path, char * * const buffer,
size_t * const size,
size_t * const linecount )
{ int result = -1;
if( !getc_count( path, size ))
{ if( *size + 1 == 0 )result = 14;
else if( *size + 2 == 0 )result = 17;
else if( *size + 3 == 0 )result = 18;
else result = readfile1( path, buffer, linecount, size ); }
return result; }

int getlines
( char * buffer, size_t size,
char const * * * const lines, size_t linecount )
{ int result = -1;
size_t need = sizeof( char const * )* linecount;
size_t test = need / sizeof( char const * );
if( test == linecount )
{ *lines = malloc( need );
if( *lines )
{ char const * p = buffer;
int looping = 1;
size_t i = 0;
char const * * const l = *lines;
while( looping )
{ l[ i++ ]= p;
while( p < buffer + size && *p != 0 )++p;
++p;
if( p < buffer + size + 1 ); else return 15;
if( i == linecount )break; }
result = 0; }
else result = 16; }
else result = 17;
return result; }

int printlines
( size_t const linecount, char const * const * lines )
{ for( size_t i = 0; i < linecount; ++i )
printf( "%s\n", lines[ i ]);
return 0; }

int main( void )
{ char const * const source[] =
{ "bicycle", "bus", "ferry", "plane", "train" };
int const writelinesstatus = writelines
( "tmp.txt", source, sizeof source / sizeof 0[ source ]);
if( writelinesstatus )fprintf( stderr, "%d\n", writelinesstatus );
else
{ char * buffer = 0; size_t linecount = 0; size_t size = 0;
int const readfilestatus =
readfile( "tmp.txt", &buffer, &size, &linecount );
if( readfilestatus )fprintf( stderr, "%d\n", readfilestatus );
else
{ char const * * lines = 0;
int const getlinesstatus =
getlines( buffer, size, &lines, linecount );
if( getlinesstatus )fprintf( stderr, "%d\n", getlinesstatus );
else printlines( linecount, lines );
if( lines ){ free(( void * )lines ); lines = 0; }
if( buffer ){ free(( void * )buffer ); buffer = 0; }}}}
 
S

Stefan Ram

int getc_count
( const char * const path, size_t * const result )
{ FILE * input = fopen( path, "rb" );

This is using binary mode. It should use text mode,
because the file will be read using text mode.
if
( strlen( source[ i ])+ 1 !=
( size_t )fprintf( file, "%s\n", source[ i ]))
{ result = 2; break; }
if( fclose( file ))result = 3;
if( result == -1 )result = 0;
else result = 1; }

Here, the error status handling can be improved:
An fclose error hides a previous fprintf error,
and then, »result = 1« hides some previous errors.
Maybe this would be better:

if
( strlen( source[ i ])+ 1 !=
( size_t )fprintf( file, "%s\n", source[ i ]))
{ result = 2; break; }
if( fclose( file ))
{ if( result == 2 )result = 20; else result = 3; }
if( result == -1 )result = 0;

Now, »20« means »both fprintf and fclose failed«.
 
L

luserXtrog

Is there any similar structure in C that I can easily get the strings in a
file like:

Example file

bicycle
bus
ferry
plane
train

so I can print them generically? In Perl, I just read them into an array,
e.g. @vehicle

then get them back by foreach. Thanks for telling me if there's similar
handy function in C

An array is an array; in any language that has them.
The complication in C relative to PERL is that you have to know
what the array will contain. A line is a string which is also
an array. So we need a two-dimensional array of characters.
C makes use of these, but sadly offers no simple, standard way
of magically creating one with the contents of a file.

But if you start with reasonable assumptions and generalize the
details later (when needed), you can bottom-up such a creature
in relatively short order.

I realize this question has been answered more than once, but
I simply can't bring myself to try to read the other two posted
elsethread.

Also, there is no foreach general iterator in C. You'll have to
iterate manually with for, while or do-while (probably not useful
here, but good to know).

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

#define NBUF 256

char **aloadfile(FILE *f) {
char **arr = NULL;
size_t narr = 0;
int i = 0;
char buf[NBUF];

while ( fgets(buf, NBUF, f) != NULL ) {

/* grow as needed */
if (i<=narr) {
narr += 100;
if ( (arr=realloc(arr, narr * sizeof *arr)) == NULL )
perror("can'nae allocate!"),exit(EXIT_FAILURE);
}

arr[i++] = strdup(buf);
}
arr = 0;

/* optional trimming of the fat */
if ( (arr=realloc(arr, (i+1) * sizeof *arr)) == NULL )
perror("can'nae allocate!"),exit(EXIT_FAILURE);

return arr;
}

int main() {
char **lines = NULL;
FILE *fp;

if ( (fp=fopen("file","r")) == NULL )
perror("can'nae open it!"),exit(EXIT_FAILURE);

lines = aloadfile(fp);

/* n.b. this is a leak */
while(*lines)
printf("%s", *lines++);

return 0;
}

//eof

hth
ps. I'm assuming from your example data that these lines are
relatively short. The program above uses 256 character buffer.
Lines longer than this will be split into 2 (or more) cells
of the array (but only the last partial will end in a newline;
so printing them back should still work).
 
K

Keith Thompson

luserXtrog said:
An array is an array; in any language that has them.
The complication in C relative to PERL is that you have to know
what the array will contain. A line is a string which is also
an array. So we need a two-dimensional array of characters.
C makes use of these, but sadly offers no simple, standard way
of magically creating one with the contents of a file.
[...]

A two-dimensional array is simply an array of arrays, and it's not the
best data structure to represent a sequence of lines (unless all lines
are the same length, or you don't mind wasting space for short lines
and being unable to store long lines).

A better data structure, and the one you used in your code (which I've
cruelly snipped) is an array of pointers, where each pointer points to
a dynamicalliy allocated string.
 
F

Flash Gordon

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

#define NBUF 256

char **aloadfile(FILE *f) {
char **arr = NULL;
size_t narr = 0;
int i = 0;

Why is i an int when narr is a size_t?
char buf[NBUF];

while ( fgets(buf, NBUF, f) != NULL ) {

/* grow as needed */
if (i<=narr) {
narr += 100;

You should check narr for wrap ;-)
More importantly, if i is left as an int you should check it fits in an int!
if ( (arr=realloc(arr, narr * sizeof *arr)) == NULL )
perror("can'nae allocate!"),exit(EXIT_FAILURE);
}

arr[i++] = strdup(buf);

At this point i could be incremented to narr
Also strdup in non-standard.
}
arr = 0;


Hmm. You have space for narr pointers, and i could be narr. A buffer
overflow, methinks!
/* optional trimming of the fat */
if ( (arr=realloc(arr, (i+1) * sizeof *arr)) == NULL )
perror("can'nae allocate!"),exit(EXIT_FAILURE);

If realloc failed you could return the buffer you already had rather
than aborting!
return arr;
}

int main() {
char **lines = NULL;
FILE *fp;

if ( (fp=fopen("file","r")) == NULL )
perror("can'nae open it!"),exit(EXIT_FAILURE);

lines = aloadfile(fp);

/* n.b. this is a leak */
while(*lines)
printf("%s", *lines++);

It would have been good to show the freeing as well.
return 0;
}

<snip>
 
I

Ian Collins

jacob said:
Not if you use lcc-win and use the GC.

Does that automatically close files for you, or release locks? Memory
is just one of the resources a programme has to manage.
But there is an important point in your objection. Either a function
to free the memory should be supplied or a SINGLE call to free
should be required. I am rewriting the program to use a different
algorithm. Instead of reading line by line I read it in a single
read, then count the lines, and allocate a single buffer with
all the pointers AND the data.

That should be more efficient and gives an easier interface.

In standard C? Probably not. Using platform specifics (file mapping)
probably yes.
But as you see if you use the GC, you do not need destructors
in this case!

You still have to close the file.
 
J

jacob navia

Ian said:
Does that automatically close files for you, or release locks? Memory
is just one of the resources a programme has to manage.

We are speaking about memory here
In standard C? Probably not. Using platform specifics (file mapping)
probably yes.

In standard C. Nothing forbids me to allocate a single
block for the data AND the array of pointers!

You still have to close the file.

Yes. This is not C++.

P.S. By the way I do not "hate" C++. That kind of emotion is
something I would have against HUMANS that I consider morally
abject. I can't imagine hating my washing machine, or a
piece of software, or my razor.
 
I

Ian Collins

jacob said:
We are speaking about memory here

As I said, Memory is just one of the resources a programme has to
manage. GC is one solution to releasing one class or resource, but you
won't find it being used in many of the low level or real time domains
where C and C++ still reign supreme.
In standard C. Nothing forbids me to allocate a single
block for the data AND the array of pointers!

True, but how do you know how much to allocate?
P.S. By the way I do not "hate" C++. That kind of emotion is
something I would have against HUMANS that I consider morally
abject. I can't imagine hating my washing machine, or a
piece of software, or my razor.

You obviously haven't had a washing machine flood your laundry....
 
C

Curtis Dyer

You don't even need to store the lines in an array in Perl, if all
you do is output the file.

print while said:
Hi ela!
No there is none as far as I know. Usually a problem like this
(unknown number of inputs) would be solved with a dynamic data
structure like a linked list, however even then you need to know
some upper limit for the length of each individual input (unless
you want to keep reallocing ofc).

As far as I can tell, the OP doesn't explicitly require storing the
lines in memory before outputting. Therefore, it seems using an
approach like Nick Keighley's suggestion would be sufficient and much
simpler.

@OP: if you want to sort the lines, or otherwise do something with
the lines, before outputting, you might want to learn about "ragged
arrays" in C. Check out Question 20.2 in the C FAQ:

<http://www.c-faq.com/>

There's a fair amount of C fundamentals underlying this task, so you
may want to start with some beginner tutorials or K&R2, if you're
willing to purchase it (well worth the money). For some recommended
resources on the net, again, check the C FAQ, Question 18.9.

--
~Curtis
Email: s/sig.invalid/gmail.com/

Anonymous (1984 IOCCC winner):
int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}
 
L

luserXtrog

[...]> An array is an array; in any language that has them.
The complication in C relative to PERL is that you have to know
what the array will contain. A line is a string which is also
an array. So we need a two-dimensional array of characters.
C makes use of these, but sadly offers no simple, standard way
of magically creating one with the contents of a file.

[...]

A two-dimensional array is simply an array of arrays, and it's not the
best data structure to represent a sequence of lines (unless all lines
are the same length, or you don't mind wasting space for short lines
and being unable to store long lines).

A better data structure, and the one you used in your code (which I've
cruelly snipped) is an array of pointers, where each pointer points to
a dynamicalliy allocated string.

Agreed. I glossed over the whole array/pointer-to-dynamically-
allocated-area-with-equivalent-usage issue. For a beginner question
that was negligent.
 
L

luserXtrog

<snipped buggy code and useful critique>

Thanks, Flash. Corrections incorporated, as well as a truly bad
bug that you were too polite to mention.

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

#define NBUF 256

char *sdup(char *s) {
char *dup;
if ( (dup=malloc(strlen(s)+1)) == NULL )
perror("can'nae allocate!"),exit(EXIT_FAILURE);
return strcpy(dup,s);
}

char **aloadfile(FILE *f) {
char **arr = NULL;
size_t narr = 0, i = 0;
char buf[NBUF];

while ( fgets(buf, NBUF, f) != NULL ) {

/* grow as needed */
if (i+1 > narr) {
narr += 100;
if ( (arr=realloc(arr, narr * sizeof *arr)) == NULL )
perror("can'nae allocate!"),exit(EXIT_FAILURE);
}

arr[i++] = sdup(buf);
}
arr = 0;

/* optional trimming of the fat */
if ( (arr=realloc(arr, (i+1) * sizeof *arr)) == NULL )
/* ignore recoverable failure. n.b. this is a leak. */ ;

return arr;
}

int main() {
char **lines = NULL;
FILE *fp;

if ( (fp=fopen("file","r")) == NULL )
perror("can'nae open it!"),exit(EXIT_FAILURE);

lines = aloadfile(fp);

{ char **save = lines;
while(*lines) {
fputs(*lines, stdout);
free(*lines++);
}
free(save);
}

return 0;
}

/*eof*/
 
L

luserXtrog

ela said:
Is there any similar structure in C that I can easily get the strings in a
file like:
Example file
bicycle
bus
ferry
plane
train
so I can print them generically? In Perl, I just read them into an array,
e.g. @vehicle
then get them back by foreach. Thanks for telling me if there's similar
handy function in C

  Actually it is very easy in C, you just reserve a buffer of
  the appropriate size and then, er, simply read the lines into
  the buffer. And you're done!

  My attempt follows - written in ISO/IEC 9899:1999 (E) C,
  without the need for any additional libraries.

  I have the impression that I made a lot of off-by-1 errors,
  which I hid under some dirty hacks. There also are still some
  redundancies in the code. But I do not have the time for a
  code clean-up right now.

  However, I would be pleased to read how to improve the
  following code.

  For the program to be self-contained, it first /writes/ the file
  to the path »tmp.txt«.

  WARNING: this will overwrite any existing file named »tmp.txt«
  in the current directory.

  »writelines« is used to create the file.
  »getc_count« gets the size of the file to be read.
  »readfile« reads the whole file into a buffer.
  »getlines« fills in the array of lines.
  »printlines« then prints these lines.

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

int getc_count
( const char * const path, size_t * const result )
{ FILE * input = fopen( path, "rb" );
  size_t size = 0;
  int failed = 1;
  int error = 0;
  int overflow = 0;
  if( input )
  { int ch = getc( input );
    while( ch != EOF )
    { if( !++size )overflow = 1, ch = EOF;
      else ch = getc( input ); }
    if( ferror( input ))error = 1;
    if( fclose( input )== 0 && !overflow && !error )failed = 0; }
  *result = size;
  return failed; }

int writelines
( char const * const path,
  char const * const * const source,
  size_t const n )
{ FILE * const file = fopen( path, "w" );
  int result = -1;
  if( file )
  { for( size_t i = 0; i < n; ++i )
    if
    ( strlen( source[ i ])+ 1 !=
      ( size_t )fprintf( file, "%s\n", source[ i ]))
    { result = 2; break; }
    if( fclose( file ))result = 3;
    if( result == -1 )result = 0;
    else result = 1; }
  else result = 19;
  return result; }

int readfile2
( char const * const path, char * * const buffer,
  size_t * const linecount,
  size_t * const size )
{ int result = -1;
  char * const buff = *buffer;
  char * p = buff;
  size_t s = 0;
  { FILE * input = fopen( path, "r" );
    if( input )
    { int ch = getc( input );
      if( ch == '\n' ){ ch = 0; ++*linecount; }
      if( !++s )result = 8, ch = EOF;
      else if( s >= *size )result = 13, ch = EOF;
      else if( ch != EOF )*p++ = ch;
      while( ch != EOF )
      { ch = getc( input );
        if( ch == '\n' ){ ch = 0; ++*linecount; }
        if( !++s )result = 5, ch = EOF;
        else if( s - 1 > *size )result = 6, ch = EOF;
        else if( ch != EOF )*p++ = ch; }
      if( ferror( input ))result = 7;
      if( fclose( input ))result = 9;
      if( result == -1 )
      { if( !++s )result = 10;
        else if( s - 2 > *size )result = 11;
        else
        { *p++ = 0; result = 0;
          *size = p - buff; }}}
    else result = 12; }
  return result; }

int readfile1
( char const * const path, char * * const buffer,
  size_t * const linecount,
  size_t * const size )
{ int result = -1;
  if( *buffer = malloc( *size + 3 ))
  { result = readfile2( path, buffer, linecount, size );
    if( result )
    { free(( void * )*buffer ); *buffer = 0; }}
  else result = 4;
  return result; }

int readfile
( char const * const path, char * * const buffer,
  size_t * const size,
  size_t * const linecount )
{ int result = -1;
  if( !getc_count( path, size ))
  { if( *size + 1 == 0 )result = 14;
    else if( *size + 2 == 0 )result = 17;
    else if( *size + 3 == 0 )result = 18;
    else result = readfile1( path, buffer, linecount, size ); }
  return result; }

int getlines
( char * buffer, size_t size,
  char const * * * const lines, size_t linecount )
{ int result = -1;
  size_t need = sizeof( char const * )* linecount;
  size_t test = need / sizeof( char const * );
  if( test == linecount )
  { *lines = malloc( need );
    if( *lines )
    { char const * p = buffer;
      int looping = 1;
      size_t i = 0;
      char const * * const l = *lines;
      while( looping )
      { l[ i++ ]= p;
        while( p < buffer + size && *p != 0 )++p;
        ++p;
        if( p < buffer + size + 1 ); else return 15;
        if( i == linecount )break; }
      result = 0; }
    else result = 16; }
  else result = 17;
  return result; }

int printlines
( size_t const linecount, char const * const * lines )
{ for( size_t i = 0; i < linecount; ++i )
  printf( "%s\n", lines[ i ]);
  return 0; }

int main( void )
{ char const * const source[] =
  { "bicycle", "bus", "ferry", "plane", "train" };
  int const writelinesstatus = writelines
  ( "tmp.txt", source, sizeof source / sizeof 0[ source ]);
  if( writelinesstatus )fprintf( stderr, "%d\n", writelinesstatus );
  else
  { char * buffer = 0; size_t linecount = 0; size_t size = 0;
    int const readfilestatus =
    readfile( "tmp.txt", &buffer, &size, &linecount );
    if( readfilestatus )fprintf( stderr, "%d\n", readfilestatus );
    else
    { char const * * lines = 0;
      int const getlinesstatus =
      getlines( buffer, size, &lines, linecount );
      if( getlinesstatus )fprintf( stderr, "%d\n", getlinesstatus );
      else printlines( linecount, lines );
      if( lines ){ free(( void * )lines ); lines = 0; }
      if( buffer ){ free(( void * )buffer ); buffer = 0; }}}}

Why are you opposed to having your messages archived?
It could easily take more than six days for anyone to find the time
and patience to wade through this. I've looked at it 3 or 4 times
already without coming away any wiser.

Withholding the message from the archive sort of flags you as a
non-participant.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,432
Messages
2,571,681
Members
48,796
Latest member
Greg L.

Latest Threads

Top