removing newline character from the buffer read by fgets

Discussion in 'C Programming' started by junky_fellow@yahoo.co.in, Nov 28, 2006.

  1. Guest

    Is there any efficcient way of removing the newline character from the
    buffer read by
    fgets() ?

    Is there any library function that is similar to fgets() but also tells
    how many
    bytes it read into the buffer ?
     
    , Nov 28, 2006
    #1
    1. Advertising

  2. In article <>,
    <> wrote:
    >Is there any efficcient way of removing the newline character from the
    >buffer read by
    >fgets() ?


    >Is there any library function that is similar to fgets() but also tells
    >how many
    >bytes it read into the buffer ?


    fgets() terminates the string with the null character, so you can
    simply use something along the lines of

    /* code fragment follows, not intended as standalone routine */

    fgetsresult = fgets( outbuffer, sizeof(outbuffer)-1, stream);
    if (fgetsresult == NULL) {
    /* handling for no string available */
    } else {
    size_t newbuflen = strlen(outbuffer);
    if (outbuffer[newbuflen - 1] == '\n') outbuffer[newbuflen - 1] = '\0';
    }
    --
    "law -- it's a commodity"
    -- Andrew Ryan (The Globe and Mail, 2005/11/26)
     
    Walter Roberson, Nov 28, 2006
    #2
    1. Advertising

  3. Jack Klein Guest

    On 27 Nov 2006 19:03:10 -0800, ""
    <> wrote in comp.lang.c:

    > Is there any efficcient way of removing the newline character from the
    > buffer read by
    > fgets() ?


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

    /* inside a function */
    if (NULL != fgets(my_buffer, sizeof my_buffer, stdin)
    {
    char *nlptr = strchr(my_buffer, '\n');
    if (nlptr) *nlptr = '\0';
    }

    > Is there any library function that is similar to fgets() but also tells
    > how many
    > bytes it read into the buffer ?


    You can certainly write one, a simple wrapper for fgets():

    size_t my_fgets(char *buffer, size_t size, FILE *fp)
    {
    size_t result = 0;
    if (NULL != fgets(my_buffer, sizeof my_buffer, fp)
    {
    /* optional, remove newline */
    char *nlptr = strchr(my_buffer, '\n');
    if (nlptr) *nlptr = '\0';
    result = strlen(my_buffer);
    }
    return result;
    }

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://c-faq.com/
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Nov 28, 2006
    #3
  4. wrote:
    > Is there any efficcient way of removing the newline character from the
    > buffer read by
    > fgets() ?


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

    int use_fgets(void)
    {
    char buffer[BIGENOUGH]; /* #define BIGENOUGH elsewhere */
    char *nl;
    if (!fgets(buffer, BIGENOUGH, stdin)) return EXIT_FAILURE;
    if ((nl = strchr(buffer, '\n'))) *nl = 0;
    /* use buffer here */
    return EXIT_SUCCESS;
    }

    > Is there any library function that is similar to fgets() but also tells
    > how many
    > bytes it read into the buffer ?


    #include <stdio.h>
    #include <string.h>
    int fgets_with_chars_read(char *buffer, int maxchars, FILE *f)
    {
    if (!fgets(buffer, maxchars, f)) return 0;
    return strlen(buffer); /* or 1+strlen(buffer) if you want the '\0'
    counted */
    }
     
    Martin Ambuhl, Nov 28, 2006
    #4
  5. Walter Roberson wrote:
    > In article <>,
    > <> wrote:
    >> Is there any efficcient way of removing the newline character from the
    >> buffer read by
    >> fgets() ?

    >
    >> Is there any library function that is similar to fgets() but also tells
    >> how many
    >> bytes it read into the buffer ?

    >
    > fgets() terminates the string with the null character, so you can
    > simply use something along the lines of
    >
    > /* code fragment follows, not intended as standalone routine */
    >
    > fgetsresult = fgets( outbuffer, sizeof(outbuffer)-1, stream);

    ^^
    if outbuffer is an array, the -1 is useless and silly
    if outbuffer is a char *, sizeof is wrong

    > if (fgetsresult == NULL) {
    > /* handling for no string available */
    > } else {
    > size_t newbuflen = strlen(outbuffer);
    > if (outbuffer[newbuflen - 1] == '\n') outbuffer[newbuflen - 1] = '\0';
    > }
     
    Martin Ambuhl, Nov 28, 2006
    #5
  6. said:

    > Is there any efficcient way of removing the newline character from the
    > buffer read by
    > fgets() ?


    Others here have posted sensible suggestions on the best way to remove the
    newline character from the buffer after an fgets call. But if you're really
    after efficiency, don't use fgets!

    > Is there any library function that is similar to fgets() but also tells
    > how many
    > bytes it read into the buffer ?


    No such standard library function exists, but you could write a routine
    yourself to do it. It could also have the following characteristics:

    1) always reads a complete line (subject to available memory), by expanding
    the buffer as and when necessary
    2) allows you to re-use the same buffer over and over (like fgets)
    3) records and reports the number of bytes read into the buffer per call
    4) records and reports the current size of the buffer (*not* the same thing
    as the length of the string contained therein)
    5) doesn't bother putting a newline on the end, because there's no need,
    because of Property 1, and therefore the caller need not remove it

    Such a routine is far, far, far simpler to write than you might imagine.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
     
    Richard Heathfield, Nov 28, 2006
    #6
  7. Guest

    On Nov 28, 11:07 am, Richard Heathfield <> wrote:
    > said:
    >
    > > Is there any efficcient way of removing the newline character from the
    > > buffer read by
    > > fgets() ?Others here have posted sensible suggestions on the best way to remove the

    > newline character from the buffer after an fgets call. But if you're really
    > after efficiency, don't use fgets!
    >
    > > Is there any library function that is similar to fgets() but also tells
    > > how many
    > > bytes it read into the buffer ?No such standard library function exists, but you could write a routine

    > yourself to do it. It could also have the following characteristics:
    >
    > 1) always reads a complete line (subject to available memory), by expanding
    > the buffer as and when necessary
    > 2) allows you to re-use the same buffer over and over (like fgets)
    > 3) records and reports the number of bytes read into the buffer per call
    > 4) records and reports the current size of the buffer (*not* the same thing
    > as the length of the string contained therein)
    > 5) doesn't bother putting a newline on the end, because there's no need,
    > because of Property 1, and therefore the caller need not remove it
    >
    > Such a routine is far, far, far simpler to write than you might imagine.
    >


    thanks everyone for your help. In fact, I don't want to use strlen() or
    strchr()
    (for efficiency reasons) to remove the newline character.
    Based of Richard's suggestion, I tried to write my own version of
    fgets()
    that will not put newline character to the input buffer passed.
    I am sure, the people here will find lots of problems in my code. All
    comments
    are welcome.

    following is my code:
    /* it returns NULL , if EOF or error encountered else returns the
    string pointer */

    #include <stdio.h>
    char *
    my_fgets(char *string, int n, FILE *fp)
    {
    int ch;
    int count = 0;

    while(count < (n - 1)) {
    ch = fgetc(fp);
    if( ch == EOF ) {
    break;
    }
    else if( ch == '\n' ) {
    break;
    }
    else {
    string[count] = ch;
    }
    count++;
    }
    string[count] = '\0';
    if( ch == EOF )
    return(NULL);
    else
    return(string);
    }
     
    , Nov 28, 2006
    #7
  8. said:

    <snip>
    >
    > thanks everyone for your help. In fact, I don't want to use strlen() or
    > strchr()
    > (for efficiency reasons) to remove the newline character.
    > Based of Richard's suggestion, I tried to write my own version of
    > fgets()
    > that will not put newline character to the input buffer passed.
    > I am sure, the people here will find lots of problems in my code. All
    > comments
    > are welcome.


    The principal objection I have to your code is that it fails to provide a
    way to distinguish between a line that has been read completely and a line
    that has been read only partially because of insufficient space in the
    buffer.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
     
    Richard Heathfield, Nov 28, 2006
    #8
  9. Guest

    On Nov 28, 1:59 pm, Richard Heathfield <> wrote:
    > said:
    >
    > <snip>
    >
    >
    >
    > > thanks everyone for your help. In fact, I don't want to use strlen() or
    > > strchr()
    > > (for efficiency reasons) to remove the newline character.
    > > Based of Richard's suggestion, I tried to write my own version of
    > > fgets()
    > > that will not put newline character to the input buffer passed.
    > > I am sure, the people here will find lots of problems in my code. All
    > > comments
    > > are welcome.The principal objection I have to your code is that it fails to provide a

    > way to distinguish between a line that has been read completely and a line
    > that has been read only partially because of insufficient space in the
    > buffer.
    >


    For that I would change the function to return the number of bytes
    read.
    If user requested n bytes and bytes read is equal to (n-1), it means
    insufficient
    space. Is this ok ? Or am I missing something ?

    char *
    my_fgets(char *string, int n, int *bytes_read, FILE *fp)
    {
    int ch;
    int count = 0;

    while(count < (n - 1)) {
    ch = fgetc(fp);
    if( ch == EOF ) {
    break;
    }
    else if( ch == '\n' ) {
    break;
    }
    else {
    string[count] = ch;
    }
    count++;
    }
    string[count] = '\0';
    *bytes_read = count;
    if( ch == EOF )
    return(NULL);
    else
    return(string);
    }
     
    , Nov 28, 2006
    #9
  10. santosh Guest

    wrote:
    > On Nov 28, 11:07 am, Richard Heathfield <> wrote:
    > > said:
    > >
    > > > Is there any efficcient way of removing the newline character from the
    > > > buffer read by
    > > > fgets() ?Others here have posted sensible suggestions on the best way to remove the

    > > newline character from the buffer after an fgets call. But if you're really
    > > after efficiency, don't use fgets!
    > >
    > > > Is there any library function that is similar to fgets() but also tells
    > > > how many
    > > > bytes it read into the buffer ?No such standard library function exists, but you could write a routine

    > > yourself to do it. It could also have the following characteristics:
    > >
    > > 1) always reads a complete line (subject to available memory), by expanding
    > > the buffer as and when necessary
    > > 2) allows you to re-use the same buffer over and over (like fgets)
    > > 3) records and reports the number of bytes read into the buffer per call
    > > 4) records and reports the current size of the buffer (*not* the same thing
    > > as the length of the string contained therein)
    > > 5) doesn't bother putting a newline on the end, because there's no need,
    > > because of Property 1, and therefore the caller need not remove it
    > >
    > > Such a routine is far, far, far simpler to write than you might imagine.
    > >

    >
    > thanks everyone for your help. In fact, I don't want to use strlen() or
    > strchr()
    > (for efficiency reasons) to remove the newline character.
    > Based of Richard's suggestion, I tried to write my own version of
    > fgets()
    > that will not put newline character to the input buffer passed.
    > I am sure, the people here will find lots of problems in my code. All
    > comments
    > are welcome.
    >
    > following is my code:
    > /* it returns NULL , if EOF or error encountered else returns the
    > string pointer */
    >
    > #include <stdio.h>
    > char *
    > my_fgets(char *string, int n, FILE *fp)
    > {
    > int ch;
    > int count = 0;
    >
    > while(count < (n - 1)) {


    Why (n - 1)?

    <snip>
     
    santosh, Nov 28, 2006
    #10
  11. said:
    > On Nov 28, 1:59 pm, Richard Heathfield wrote:
    >> The principal objection I have to your code is that it fails to provide a
    >> way to distinguish between a line that has been read completely and a
    >> line that has been read only partially because of insufficient space in
    >> the buffer.

    >
    > For that I would change the function to return the number of bytes
    > read.


    That is a reasonable approach. I would suggest a size_t type for this. You
    might reasonably reserve 0 for an exceptional condition, leaving the user
    to enquire of ferror() to find out whether Something Really Bad happened or
    whether the routine simply couldn't find any data to stuff into the buffer
    (i.e. encountered EOF on the first getc call).

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
     
    Richard Heathfield, Nov 28, 2006
    #11
  12. Guest

    On Nov 28, 3:27 pm, Richard Heathfield <> wrote:
    > said:
    >
    > > On Nov 28, 1:59 pm, Richard Heathfield wrote:
    > >> The principal objection I have to your code is that it fails to provide a
    > >> way to distinguish between a line that has been read completely and a
    > >> line that has been read only partially because of insufficient space in
    > >> the buffer.

    >
    > > For that I would change the function to return the number of bytes
    > > read.That is a reasonable approach. I would suggest a size_t type for this. You

    > might reasonably reserve 0 for an exceptional condition, leaving the user
    > to enquire of ferror() to find out whether Something Really Bad happened or
    > whether the routine simply couldn't find any data to stuff into the buffer
    > (i.e. encountered EOF on the first getc call).
    >


    Using 0 or some other value (negative value) for an exceptional
    condition
    is a good idea. thanks for that.
    Regarding "size_t", I used the type "int" for "bytes_read" as its value
    will
    never be greater than "n". The type of "n" is "int", so I thought
    "bytes_read"
    should also be "int".

    Is there any special reason for using size_t for "bytes_read" ?
     
    , Nov 28, 2006
    #12
  13. said:

    >
    >
    > On Nov 28, 3:27 pm, Richard Heathfield <> wrote:
    >> said:
    >>
    >> > On Nov 28, 1:59 pm, Richard Heathfield wrote:
    >> >> The principal objection I have to your code is that it fails to
    >> >> provide a way to distinguish between a line that has been read
    >> >> completely and a line that has been read only partially because of
    >> >> insufficient space in the buffer.

    >>
    >> > For that I would change the function to return the number of bytes
    >> > read.That is a reasonable approach. I would suggest a size_t type for
    >> > this. You

    >> might reasonably reserve 0 for an exceptional condition, leaving the user
    >> to enquire of ferror() to find out whether Something Really Bad happened
    >> or whether the routine simply couldn't find any data to stuff into the
    >> buffer (i.e. encountered EOF on the first getc call).
    >>

    >
    > Using 0 or some other value (negative value) for an exceptional
    > condition
    > is a good idea. thanks for that.


    0, if you're using an unsigned type such as size_t.

    > Regarding "size_t", I used the type "int" for "bytes_read" as its value
    > will
    > never be greater than "n". The type of "n" is "int", so I thought
    > "bytes_read"
    > should also be "int".


    Why not change n's type to size_t? After all, it represents the size of an
    object, does it not?

    >
    > Is there any special reason for using size_t for "bytes_read" ?


    It's an unsigned integer type that is guaranteed to be able to store the
    largest possible object size, whereas int is not.

    See also the following standard library functions, which use size_t for much
    the same reason:

    bsearch, calloc, fread, fwrite, malloc, memchr, memcmp, memcpy, memmove,
    memset, qsort, realloc, setvbuf, strftime, strlen, strncat, strncmp,
    strncpy, and no doubt I missed one or two.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
     
    Richard Heathfield, Nov 28, 2006
    #13
  14. Jack Klein Guest

    On Tue, 28 Nov 2006 04:04:06 +0000 (UTC), -cnrc.gc.ca
    (Walter Roberson) wrote in comp.lang.c:

    > In article <>,
    > <> wrote:
    > >Is there any efficcient way of removing the newline character from the
    > >buffer read by
    > >fgets() ?

    >
    > >Is there any library function that is similar to fgets() but also tells
    > >how many
    > >bytes it read into the buffer ?

    >
    > fgets() terminates the string with the null character, so you can
    > simply use something along the lines of
    >
    > /* code fragment follows, not intended as standalone routine */
    >
    > fgetsresult = fgets( outbuffer, sizeof(outbuffer)-1, stream);
    > if (fgetsresult == NULL) {
    > /* handling for no string available */
    > } else {
    > size_t newbuflen = strlen(outbuffer);
    > if (outbuffer[newbuflen - 1] == '\n') outbuffer[newbuflen - 1] = '\0';
    > }


    In addition to Martin's comments, which I agree with, this is overly
    complicated. See my simpler method in my reply to the original.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://c-faq.com/
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Nov 28, 2006
    #14
  15. Jack Klein Guest

    On 28 Nov 2006 00:30:45 -0800, ""
    <> wrote in comp.lang.c:

    >
    >
    > On Nov 28, 11:07 am, Richard Heathfield <> wrote:
    > > said:
    > >
    > > > Is there any efficcient way of removing the newline character from the
    > > > buffer read by
    > > > fgets() ?Others here have posted sensible suggestions on the best way to remove the

    > > newline character from the buffer after an fgets call. But if you're really
    > > after efficiency, don't use fgets!
    > >
    > > > Is there any library function that is similar to fgets() but also tells
    > > > how many
    > > > bytes it read into the buffer ?No such standard library function exists, but you could write a routine

    > > yourself to do it. It could also have the following characteristics:
    > >
    > > 1) always reads a complete line (subject to available memory), by expanding
    > > the buffer as and when necessary
    > > 2) allows you to re-use the same buffer over and over (like fgets)
    > > 3) records and reports the number of bytes read into the buffer per call
    > > 4) records and reports the current size of the buffer (*not* the same thing
    > > as the length of the string contained therein)
    > > 5) doesn't bother putting a newline on the end, because there's no need,
    > > because of Property 1, and therefore the caller need not remove it
    > >
    > > Such a routine is far, far, far simpler to write than you might imagine.
    > >

    >
    > thanks everyone for your help. In fact, I don't want to use strlen() or
    > strchr()
    > (for efficiency reasons) to remove the newline character.


    "efficiency reasons" is your first mistake. If you're writing your
    own implementation as a learning exercise, well and good. If you're
    writing your own implementation because you think it will be "more
    efficient" than fgets()+strlen(), you are wrong on two counts:

    1. It probably won't be more efficient.

    2. You probably don't need more efficiency anyway.

    After you get your program working properly with the simplest, easiest
    to understand implementation, and it runs too slowly, and you use a
    profiler or other test method to prove that this implementation is a
    serious bottleneck, then and only then consider writing your own
    routine for efficiency.

    And even then, test again afterwards to see if you have actually
    improved efficiency.

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://c-faq.com/
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
     
    Jack Klein, Nov 28, 2006
    #15
  16. santosh Guest

    wrote:
    > On Nov 28, 3:27 pm, Richard Heathfield <> wrote:
    > > said:
    > >
    > > > On Nov 28, 1:59 pm, Richard Heathfield wrote:
    > > >> The principal objection I have to your code is that it fails to provide a
    > > >> way to distinguish between a line that has been read completely and a
    > > >> line that has been read only partially because of insufficient space in
    > > >> the buffer.

    > >
    > > > For that I would change the function to return the number of bytes
    > > > read.That is a reasonable approach. I would suggest a size_t type for this. You

    > > might reasonably reserve 0 for an exceptional condition, leaving the user
    > > to enquire of ferror() to find out whether Something Really Bad happened or
    > > whether the routine simply couldn't find any data to stuff into the buffer
    > > (i.e. encountered EOF on the first getc call).
    > >

    >
    > Regarding "size_t", I used the type "int" for "bytes_read" as its value
    > will never be greater than "n". The type of "n" is "int", so I thought
    > "bytes_read" should also be "int".


    Well consider pure DOS which is a 16 bit system. An int would have a
    range of -32768 to 32767. On the other hand you might be able to
    allocate an object of 65536 bytes. You might want to read in the
    contents of a file into this buffer. If your function used int as the
    type to specify bytes to read, the caller will have to call your
    function twice. Had you used size_t instead, you could be assured that
    you can fully address the largest single object you could possibly
    allocate.

    size_t is expressly meant for the purpose of holding the size of
    objects in your program, so it might be more suited for this purpose
    than an int, (atleast a signed int).
     
    santosh, Nov 28, 2006
    #16
  17. "" <> writes:
    [...]
    > thanks everyone for your help. In fact, I don't want to use strlen()
    > or strchr() (for efficiency reasons) to remove the newline
    > character.


    Why not? Is the call to strlen() or strchr() a performance bottleneck
    in your program, justifying the extra work of writing an input
    function from scratch?

    It may be, but if you haven't measured it, you may be applying your
    efforts unwisely. Typically reading the input from some external
    device will be much slower than scanning a string in memory.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Nov 28, 2006
    #17
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mike Mimic

    fgets and newline

    Mike Mimic, May 15, 2004, in forum: C++
    Replies:
    4
    Views:
    8,072
    John Harrison
    May 15, 2004
  2. Charles Erwin
    Replies:
    4
    Views:
    594
    Joe Wright
    Oct 6, 2003
  3. Daniel Mark
    Replies:
    6
    Views:
    70,933
    Tim Chase
    Sep 28, 2006
  4. Replies:
    6
    Views:
    1,166
    James Dow Allen
    Feb 17, 2010
  5. John Reye
    Replies:
    43
    Views:
    1,402
    Malcolm McLean
    Nov 14, 2013
Loading...

Share This Page