Taking a stab at getline

B

Barry Schwarz

// ritorna un puntatore da liberarsi tramite free()
// ritorna 0 per errore
char* __export GetLineI(char* testo)

What is __export? I don't se it in n1256 (C99) or n1570 (C11).
{unsigned s, i;
int c;
char *p,*t;
s=1024; p=malloc(s+4);

It would make your code much easier to read if you invested in some
horizontal white space.

You might also consider sticking to one statement per line.
if(p==0) return 0;
printf("%s", testo); fflush(stdout);

The second time you call this function, wouldn't like the output to be
on a new line? Does testo always terminate with a '\n'?
for(i=0; (c=getchar())!=EOF ; )
{if(i>=s)
{s=s+1024;
t=realloc(p, s+4);

What is the purpose of the extra 4 bytes?
if(t==0||(int)s<0)

If s exceeds INT_MAX, casting it to an int need not produce a negative
value. You would do better to simply compare s > INT_MAX. On the
other hand, if you made i unsigned, you wouldn't care. You can
probably assume that realloc will fail before s > UINT_MAX but if you
really think you will lines with gigabyte lengths you could impose an
arbitrary limit.
{free(p); return 0;}
p=t;
}
p=c; ++i;
if(c=='\n')
break;
}
p=0;
return p;
}
 
R

Rosario1903

What is __export? I don't se it in n1256 (C99) or n1570 (C11).


It would make your code much easier to read if you invested in some
horizontal white space.

You might also consider sticking to one statement per line.

i'm not agree, for me in a line there would be instructions,
statements that do togheter something simple, as for example swap :
"t=a; a=b; b=t;"
would be ok in one line
 
R

Rosario1903

On Sat, 09 Feb 2013 19:02:32 +0100, Rosario1903


What is __export? I don't se it in n1256 (C99) or n1570 (C11).


It would make your code much easier to read if you invested in some
horizontal white space.

You might also consider sticking to one statement per line.


The second time you call this function, wouldn't like the output to be
on a new line? Does testo always terminate with a '\n'?


What is the purpose of the extra 4 bytes?

i like some extra space and possibly not understand well or fear the 0
bytes case solution
If s exceeds INT_MAX, casting it to an int need not produce a negative
value. You would do better to simply compare s > INT_MAX.

yes but i not like write too much, and her in 386 cpu all 2 compilers
i use would be ok
On the
other hand, if you made i unsigned, you wouldn't care.

i don't like overflow
You can
probably assume that realloc will fail before s > UINT_MAX but if you

what about s+4 overflow s unsigned?
really think you will lines with gigabyte lengths you could impose an
arbitrary limit.
{free(p); return 0;}
p=t;
}
p=c; ++i;
if(c=='\n')
break;
}
p=0;
return p;
}


all error stream check is left by exercise for the reader...
 
B

Ben Bacarisse

Barry Schwarz said:
What is the purpose of the extra 4 bytes?

That bugged me until I saw that at least +1 is needed because of the way
the rest of the code is written: if the buffer is of size 's', a newline
written to the last byte will case the null to be written one past the
end. I guessed that having discovered a problem in testing, the +4 is
some sort of insurance.
if(t==0||(int)s<0)
{free(p); return 0;}
p=t;
}
p=c; ++i;
if(c=='\n')
break;
}
p=0;
return p;
}
 
R

Rosario1903

// ritorna un puntatore da liberarsi tramite free()
// ritorna 0 per errore
char* __export GetLineI(char* testo)
{unsigned s, i;
int c;
char *p,*t;

i add some error checking...
What about:?

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>

// ritorna un puntatore da liberarsi tramite free()
// 0 per errore
char* GetLineI(char* testo)
{unsigned s, i, vMax=UINT_MAX-1032; // 1024+4+1 [+ 3]=1032
int c;
char *p,*t;

s=1024; p=malloc(s+4);
if(p==0) return 0;
if(printf("%s", testo)<0)
{la: free(p); return 0;}
if(fflush(stdout)!=0)
goto la;
for(i=0; (c=getchar())!=EOF ; )
{if(i>=s)
{if(s>=vMax)
goto la;
s=s+1024;
t=realloc(p, s+4);
if(t==0)
goto la;
p=t;
}
p=c; ++i;
if(c=='\n')
break;
}
if(ferror(stdin))
goto la;
p=0;
return p;
}

int main(void)
{char *r;
r=GetLineI("Inserisci stringa: ");
if(r==0)
printf("Errore\n");
else {printf("Hai inserito: [%s]\n", r);
free(r);
}
return 0;
}
 
R

Rosario1903

// ritorna un puntatore da liberarsi tramite free()
// ritorna 0 per errore
char* __export GetLineI(char* testo)
{unsigned s, i;
int c;
char *p,*t;
s=1024; p=malloc(s+4);
if(p==0) return 0;
printf("%s", testo); fflush(stdout);
for(i=0; (c=getchar())!=EOF ; )
{if(i>=s)
{s=s+1024;
t=realloc(p, s+4);
if(t==0||(int)s<0)
{free(p); return 0;}

here there is one error if t!=0 and (int)s<0
free(p) free the wrong pointer...
p=t;
}
p=c; ++i;
if(c=='\n')
break;
}
p=0;
return p;
}
 
B

Ben Bacarisse

Rosario1903 said:
i add some error checking...
What about:?
if(printf("%s", testo)<0)
{la: free(p); return 0;}

If you are going to test the return form printf it would be better to
test for all errors. Even a non-negative return < strlen(testo) is an
error.

But fputs is both easier to use (no format) and easier to check for
errors:

if (fputs(testo, stdout) == EOF) ...

<snip>
 
R

Rosario1903

If you are going to test the return form printf it would be better to
test for all errors. Even a non-negative return < strlen(testo) is an
error.

book say that if printf fail it has to return a <0 value

if testo=="" the string that contain only \0
i think printf has to print nothing to stdin, and return 0
so the above test would be ok in this case too
 
R

Rosario1903

i add some error checking...
What about:?

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>

// ritorna un puntatore da liberarsi tramite free()
// 0 per errore
char* GetLineI(char* testo)
{unsigned s, i, vMax=UINT_MAX-1032; // 1024+4+1 [+ 3]=1032
int c;
char *p,*t;

s=1024; p=malloc(s+4);
if(p==0) return 0;
if(printf("%s", testo)<0)

better:
if(testo!=0 && printf("%s", testo)<0)

{la: free(p); return 0;}
if(fflush(stdout)!=0)
goto la;
for(i=0; (c=getchar())!=EOF ; )
{if(i>=s)
{if(s>=vMax)
goto la;
s=s+1024;
t=realloc(p, s+4);
if(t==0)
goto la;
p=t;
}
p=c; ++i;
if(c=='\n')
break;
}
if(ferror(stdin))
goto la;
p=0;
return p;
}

int main(void)
{char *r;
r=GetLineI("Inserisci stringa: ");
if(r==0)
printf("Errore\n");
else {printf("Hai inserito: [%s]\n", r);
free(r);
}
return 0;
}
 
R

Rosario1903

book say that if printf fail it has to return a <0 value

if testo=="" the string that contain only \0
i think printf has to print nothing to stdin, and return 0
^^^^^^^
to stdout...
 
R

Rosario1903

On Mon, 11 Feb 2013 16:37:44 +0100, Rosario1903


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>

// ritorna un puntatore da liberarsi tramite free()
// 0 per errore
char* AskAndGetLine(char* testo)
{unsigned s, i, vMax=UINT_MAX-1032; // 1024+4+1 [+ 3]=1032
int c;
char *p,*t;

s=1024; p=malloc(s+4);
if(p==0) return 0;
if(testo!=0 && printf("%s", testo)<0)
{la: free(p); return 0;}
if(fflush(stdout)!=0)
goto la;
for(i=0; (c=getchar())!=EOF ; )
{if(i>=s)
{if(s>=vMax)
goto la;
s=s+1024;
t=realloc(p, s+4);
if(t==0)
goto la;
p=t;
}
p=c; ++i;
if(c=='\n')
break;
}
if(ferror(stdin))
goto la;
p=0;
return p;
}

int main(void)
{char *r;
r=AskAndGetLine("Inserisci stringa: ");
if(r==0)
printf("Errore\n");
else {printf("Hai inserito: [%s]\n", r);
free(r);
}
return 0;
}
 
B

Ben Bacarisse

Rosario1903 said:
book say that if printf fail it has to return a <0 value

Yes, I think that's right. The standard says it "returns the number of
characters transmitted, or a negative value if an output or encoding
error occurred" so what your book says is true if all failures are
output or encoding errors. That seems likely to what it meant.

I am not 100% sure what happens if an environmental limit is exceeded so
I've never been 100% sure that you can't get a non-negative return when
something has gone wrong. However, given my tendency to "over read"
things, I'll accept that your book is right: when anything goes wrong
the return will be negative.

<snip>
 
J

James Kuyper

Yes, I think that's right. The standard says it "returns the number of
characters transmitted, or a negative value if an output or encoding
error occurred" so what your book says is true if all failures are
output or encoding errors. That seems likely to what it meant.

I am not 100% sure what happens if an environmental limit is exceeded so
I've never been 100% sure that you can't get a non-negative return when
something has gone wrong.

I think it could be argued that the behavior is undefined in that case,
by reason of the absence of a definition, but such arguments tend to be
tricky. However, even if that argument doesn't hold up, there's
certainly other things that can render the behavior of a program
undefined. When any of those things occurs, it's possible that the
result will be that functions which supposedly can't return a given
value might actually return that value, even if they're standard library
functions.

As a result, if there's only one result that's supposed to be produced
by a successful call to a function, I generally prefer to test for
errors by checking whether a function fails to return that result,
rather than by checking whether it produces a result indicating an error.

If the behavior of your program is undefined, in principle, that means
that anything is possible, which would, if relevant, render it pointless
to consider that possibility. In reality the consequences of executing
code with undefined behavior tend to be more limited. It's certainly
possible that your program will fail catastrophically, but it's also
possible that it won't. In the latter case, other parts of your program
will often continue executing with something approaching their normal
behavior, which means that it can be worthwhile trying to achieve a
controlled exit from the program rather than simply letting it crash. At
the very least, a controlled exit can give you more information about
what went wrong than a crash would.
 
T

Tim Rentsch

Ben Bacarisse said:
Rosario1903 said:
book say that if printf fail it has to return a <0 value

Yes, I think that's right. The standard says it "returns the
number of characters transmitted, or a negative value if an
output or encoding error occurred" so what your book says is
true if all failures are output or encoding errors. That seems
likely to what it meant.

I am not 100% sure what happens if an environmental limit is
exceeded so I've never been 100% sure that you can't get a
non-negative return when something has gone wrong. [snip]

Exceeding an environmental or implementation limit is not
undefined behavior unless explicitly called out as such, eg,
6.4.2.1 or 7.13.1.1. The exception proves the rule in cases not
excepted. The environmental limit associated with fprintf
conversions does not mention any circumstances of undefined
behavior; implementations that cannot satisfy a requested
conversion of, say, 10,000 characters in length, must give a
negative return value, indicating an output error.

However, it is still possible to get a misleading result from
fprintf, because of 6.5 p5. If the number of characters sent
exceeds INT_MAX, that is undefined behavior, and all bets are
off. (And not just theoretically possible UB either...)
 
J

Jorgen Grahn

Hello group,

Here's my attempt at writing a "get_line" implementation, which
reads an entire line from a file stream, dynamically allocating
the space needed to store said line.

Since this is for my own personal use, I didn't bother handling
out-of-memory conditions elegantly. I just kick the bucket.
("We all kick the bucket in the end, in the end.")

EOF is signaled by returning NULL.

I'd like to hear suggestions/criticism.

What I notice immediately is that the documentation is missing (apart
from the hint above about how long lines are handled -- you try to
malloc enough space).

It's hard to criticize when you don't know what you /intend/ the
function to do in normal cases and error conditions. See e.g. the
fgets() manual page for how to do this right.

/Jorgen
 
N

Noob

Noob said:
Here's my attempt at writing a "get_line" implementation, which
reads an entire line from a file stream, dynamically allocating
the space needed to store said line.

I went back to the drawing board, with all your comments and suggestions
in mind.

As far as I can tell, there are 5 "situations" to deal with:

1) non-empty line
2) empty line
3) end of stream
4) stream error
5) out of memory

For "typical" text files, getline will deal mostly with 1 and 2, and
one necessary 3 at the end of the stream. 4 and 5 are exceptional
error conditions.

With the aim of keeping the common case simple, and given that I've
stuck with a pointer return value, the simplest strategy seems to be
to return
- a valid pointer for 1 and 2
- NULL for 3, 4, 5

and let the user tell 3, 4, 5 apart using
feof for 3, ferror for 4, otherwise 5

So here's the "formal" description:

char *mygetline(FILE *stream)

mygetline dynamically allocates enough space (using malloc and friends) to
store the next complete line (a valid NUL-terminated string) from 'stream'.
The string must be free'd by the user when it is no longer needed.
mygetline may return NULL
1) when it has reached the end of the stream
2) when there is an error reading from the stream
3) when malloc fails
The user may use feof and ferror to distinguish between these cases

Here's the code (valid C89 according to gcc)

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

static char *wrap_realloc(char *s, size_t len)
{
char *temp = realloc(s, len);
if (temp == NULL) free(s);
return temp;
}

char *mygetline(FILE *stream)
{
char *s = NULL;
size_t len = 500;
while ( 1 )
{
size_t max = len*2;
s = wrap_realloc(s, max);
if (s == NULL) return NULL;
while (len < max)
{
int c = getc(stream);
if (c == EOF || c == '\n')
{
s[len] = '\0';
return wrap_realloc(s, len+1);
}
s[len++] = c;
}
}
}

P.S. Eric, I did note your remark that len*2 may wrap-around, I'm just
not sure what to do in this situation...

Again, suggestions and criticism are welcome.

Regards.
 
B

Ben Bacarisse

Noob said:
I went back to the drawing board, with all your comments and suggestions
in mind.

As far as I can tell, there are 5 "situations" to deal with:

1) non-empty line
2) empty line
3) end of stream
4) stream error
5) out of memory

For "typical" text files, getline will deal mostly with 1 and 2, and
one necessary 3 at the end of the stream. 4 and 5 are exceptional
error conditions.

With the aim of keeping the common case simple, and given that I've
stuck with a pointer return value, the simplest strategy seems to be
to return
- a valid pointer for 1 and 2
- NULL for 3, 4, 5

That's a fine set of choices but the code does not return NULL in case 3!
and let the user tell 3, 4, 5 apart using
feof for 3, ferror for 4, otherwise 5

So here's the "formal" description:

char *mygetline(FILE *stream)

mygetline dynamically allocates enough space (using malloc and friends) to
store the next complete line (a valid NUL-terminated string) from 'stream'.
The string must be free'd by the user when it is no longer needed.
mygetline may return NULL
1) when it has reached the end of the stream
2) when there is an error reading from the stream
3) when malloc fails
The user may use feof and ferror to distinguish between these cases

The wording is a little off. You intend to return NULL when EOF or a
read error occurs only when no characters have been read. When the
function reads the last line, it will have reached the end of the input
(and feof will tell the caller that should they care to find out) but
you won't return NULL. Similarly for a read error.

You *do* return NULL when allocation fails, even if you have read some
data. That seems, in some way, a shame, but doing anything else
complicates the interface to gain only a dubious benefit in rare cases.
I think your choice is the right one here.

You should document the fact that the newline is not stored.
Personally, I prefer a read-line function to store it, because it
enables the caller to tell if the last line was properly terminated (and
if a read error occurred in or after a complete line had been seen) but
I don't think this is a major issue.
Here's the code (valid C89 according to gcc)

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

static char *wrap_realloc(char *s, size_t len)
{
char *temp = realloc(s, len);
if (temp == NULL) free(s);
return temp;
}

char *mygetline(FILE *stream)
{
char *s = NULL;
size_t len = 500;
while ( 1 )
{
size_t max = len*2;
s = wrap_realloc(s, max);
if (s == NULL) return NULL;
while (len < max)
{
int c = getc(stream);
if (c == EOF || c == '\n')
{
s[len] = '\0';
return wrap_realloc(s, len+1);
}
s[len++] = c;
}
}
}

I don't think you tested this! Unless I am way short on coffee today,
the first character is placed at position 500.

<snip>
 
N

Noob

Ben said:
That's a fine set of choices but the code does not return NULL in case 3!

/me smacks forehead...

Thanks for spotting this! Will fix ASAP.
I don't think you tested this! Unless I am way short on coffee today,
the first character is placed at position 500.

Aaarg! You are right again :-(

Sorry for this rushed, untested version, I hit send prematurely.

Time to fix the nasties...

Regards.
 
E

Eric Sosman

I went back to the drawing board, with all your comments and suggestions
in mind.

As far as I can tell, there are 5 "situations" to deal with:

1) non-empty line
2) empty line
3) end of stream
4) stream error
5) out of memory

For "typical" text files, getline will deal mostly with 1 and 2, and
one necessary 3 at the end of the stream. 4 and 5 are exceptional
error conditions.

With the aim of keeping the common case simple, and given that I've
stuck with a pointer return value, the simplest strategy seems to be
to return
- a valid pointer for 1 and 2
- NULL for 3, 4, 5

and let the user tell 3, 4, 5 apart using
feof for 3, ferror for 4, otherwise 5

So here's the "formal" description:

char *mygetline(FILE *stream)

mygetline dynamically allocates enough space (using malloc and friends) to
store the next complete line (a valid NUL-terminated string) from 'stream'.
The string must be free'd by the user when it is no longer needed.
mygetline may return NULL
1) when it has reached the end of the stream
2) when there is an error reading from the stream
3) when malloc fails
The user may use feof and ferror to distinguish between these cases

Here's the code (valid C89 according to gcc)

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

static char *wrap_realloc(char *s, size_t len)
{
char *temp = realloc(s, len);
if (temp == NULL) free(s);
return temp;
}

char *mygetline(FILE *stream)
{
char *s = NULL;
size_t len = 500;
while ( 1 )
{
size_t max = len*2;

If you're worried about wrap-around (a possibility, albeit
a remote one), at this point you could add something like

if (max <= len) {
max = (size_t) -1; // last gasp: try SIZE_MAX
if (max <= len) {
free(s);
return NULL;
}
}
s = wrap_realloc(s, max);
if (s == NULL) return NULL;
while (len < max)
{
int c = getc(stream);
if (c == EOF || c == '\n')
{
s[len] = '\0';
return wrap_realloc(s, len+1);

I'm of two minds about this realloc(). On the one hand, it's
good not to tie up more memory than you must; if the caller is just
stuffing the lines into a linked list or something, the memory
savings is worth while. But it seems more likely that the caller
will read a line, extract bits and pieces of it and store them
(rather than the whole line), and then just call free(). In that
use, the realloc() is just a waste of effort.

My own edition of this thing (everybody writes one eventually)
takes the idea a step further: It re-uses the existing buffer on
the next call, meaning that the caller needn't (in fact, mustn't)
call free(), and that the caller must extract and stash information
before reading the next line. Whether that's a good idea is open
to debate, but it works for me. YMMV.
}
s[len++] = c;
}
}
}

P.S. Eric, I did note your remark that len*2 may wrap-around, I'm just
not sure what to do in this situation...

Again, suggestions and criticism are welcome.

In addition to the comments above, I suggest you test this
code: You may be in for a surprise. (Hint: When the caller
examines the returned buffer, where will it find the very first
input character?)
 
I

ImpalerCore

Noob said:
Here's my attempt at writing a "get_line" implementation, which
reads an entire line from a file stream, dynamically allocating
the space needed to store said line.

I went back to the drawing board, with all your comments and suggestions
in mind.

As far as I can tell, there are 5 "situations" to deal with:

1) non-empty line
2) empty line
3) end of stream
4) stream error
5) out of memory

For "typical" text files, getline will deal mostly with 1 and 2, and
one necessary 3 at the end of the stream. 4 and 5 are exceptional
error conditions.

With the aim of keeping the common case simple, and given that I've
stuck with a pointer return value, the simplest strategy seems to be
to return
- a valid pointer for 1 and 2
- NULL for 3, 4, 5

and let the user tell 3, 4, 5 apart using
feof for 3, ferror for 4, otherwise 5

So here's the "formal" description:

  char *mygetline(FILE *stream)

mygetline dynamically allocates enough space (using malloc and friends) to
store the next complete line (a valid NUL-terminated string) from 'stream'.
The string must be free'd by the user when it is no longer needed.
mygetline may return NULL
1) when it has reached the end of the stream
2) when there is an error reading from the stream
3) when malloc fails
The user may use feof and ferror to distinguish between these cases

Here's the code (valid C89 according to gcc)

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

static char *wrap_realloc(char *s, size_t len)
{
  char *temp = realloc(s, len);
  if (temp == NULL) free(s);
  return temp;

}

char *mygetline(FILE *stream)
{
  char *s = NULL;
  size_t len = 500;
  while ( 1 )
  {
    size_t max = len*2;
    s = wrap_realloc(s, max);
    if (s == NULL) return NULL;
    while (len < max)
    {
      int c = getc(stream);
      if (c == EOF || c == '\n')
      {
        s[len] = '\0';
        return wrap_realloc(s, len+1);
      }
      s[len++] = c;
    }
  }

}

P.S. Eric, I did note your remark that len*2 may wrap-around, I'm just
not sure what to do in this situation...

Again, suggestions and criticism are welcome.

The problem with writing getline functions is that there are a wide
variety of semantics that people desire in given scenarios.

1. Do you read into a fixed buffer (for character arrays in
structured binary files), or attempt to grow a buffer (reading from
stdin or lines of text from an arbitrary file)?
2. Do you strip newline characters out, or leave them in?
3. If reading into a fixed buffer, what do you do when the string
terminator is not found within the expected length?
3a. Do you terminate the buffer or leave the buffer as is?
3b. How do you inform the user that the buffer contains a string
fragment (an unterminated string)? Is it an error or allowed?
3c. Do you flush any remaining characters in the stream until you hit
the delimiter or EOF?
3d. If the stream is seekable, do you reset the file pointer to its
original location if the string read is unterminated? (I've had to do
this to write an algorithm to recover records in files that had
corrupted sections from a hard drive media failure).
4. Do you pass in an allocated buffer and its size to reuse a single
buffer allocation for all line reads, or does every line get its own
allocation?
4a. If reading into a growing buffer, what kind of allocation
strategy to use (double the size, increments)?
4b. Do you resize the buffer down to the length of the string at the
end?
4c. Do you impose an arbitrary maximum limit to guard against
resource exhaustion in errant or dubious input, or to prevent some
type overflow condition?
5. How important is it to identify various errors from resource
exhaustion, running out of disk space, other stream errors, and how to
distinguish error scenarios from the end of file condition?
5a. How are errors communicated? Is it by return type, global state
like errno, another parameter in the function?

As one can see, there's a lot of choices to make when designing a
'getline' function. For your situation, I'm particularly fond of the
semantics of the POSIX version of 'getline'?

ssize_t getline(char **lineptr, size_t *n, FILE *stream);
ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);

Note that getline is implemented as getdelim where [delim = '\n'].

The problem that I have with your version of getline is that a new
line buffer is allocated for each line read. This may be what you
want now for your current situation, but maybe not for something
else. The POSIX semantics allow you to pass in your own allocated
buffer via 'lineptr' and 'n', and internally uses 'realloc' if the
number of character read for the current line exceeds the allocated
size (*n) of your buffer.

The POSIX semantics include the newline character in the output, and
returns the number of characters read including the newline but
excluding the terminating nul character. The 'n' maintains the
allocated buffer size. Here's a slightly modified example from the
man page.

\code
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
FILE *fp;
char *line = NULL;
size_t buf_len = 0;
ssize_t read;

fp = fopen("your_filename_here", "r");
if (fp == NULL)
exit(EXIT_FAILURE);

while ((read = getline(&line, &buf_len, fp)) != -1) {
printf("Retrieved line of length %zu :\n", read);
printf("%s", line);
}

free(line);
exit(EXIT_SUCCESS);
}
\endcode

Note that only one free at the end is required if you don't need to
store all the lines in a container. Empty lines are represented as
lines with length 1 that consist of '\n'.

If you want to strip newline characters

line[read] = line[read] == '\n' ? '\0' : line[read];

If you want each line to have its own allocated buffer...

char* new_line = strdup( line );

If you don't want newlines in your final line output, you do the above
two lines in order and you'll have an allocated line without the
trailing newline for every line in your file that you can store in
your choice of container.

I personally have two classes of 'getline' functions. I use the
naming convention of 'getline' to represent the scenario where one
wants to grow a buffer to read a line, and 'readline' for semantics
that look to read a line (or C string from a file) into a fixed size
buffer, as both are useful in given contexts.

Best regards,
John D.
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top