Proper fgets

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • uidzer0

    #1

    Proper fgets

    Hey everyone,

    Taken the following code; is there a "proper" or dynamic way to
    allocate the length of line[]?

    #include <stdio.h>
    #include <errno.h>

    int main(int argc, char **argv) {
    FILE *fp;
    char line[4096];

    if(argc < 2) {
    printf("usage: %s <file>\n", argv[0]);
    return(1);
    }

    if((fp = fopen(argv[1], "r")) == NULL) {
    perror("fopen") ;
    return(1);
    }

    while(fgets(lin e, sizeof(line), fp)) {
    printf("%s", line);
    }

    return(0);
    }

  • user923005

    #2
    Re: Proper fgets

    On Mar 12, 10:22 am, "uidzer0" <ben.lemasur... @gmail.comwrote :
    Hey everyone,
    >
    Taken the following code; is there a "proper" or dynamic way to
    allocate the length of line[]?
    >
    #include <stdio.h>
    #include <errno.h>
    >
    int main(int argc, char **argv) {
    FILE *fp;
    char line[4096];
    >
    if(argc < 2) {
    printf("usage: %s <file>\n", argv[0]);
    return(1);
    }
    >
    if((fp = fopen(argv[1], "r")) == NULL) {
    perror("fopen") ;
    return(1);
    }
    >
    while(fgets(lin e, sizeof(line), fp)) {
    printf("%s", line);
    }
    >
    return(0);
    >
    >
    >
    }- Hide quoted text -
    >
    - Show quoted text -
    Do a web search for getline

    Comment

    • uidzer0

      #3
      Re: Proper fgets

      That's perfect, however, it appears to be a GNU extension. Is there a
      ANSI C way to do this?

      Thanks again,

      Ben

      On Mar 12, 12:44 pm, "user923005 " <dcor...@connx. comwrote:
      On Mar 12, 10:22 am, "uidzer0" <ben.lemasur... @gmail.comwrote :
      >
      >
      >
      Hey everyone,
      >
      Taken the following code; is there a "proper" or dynamic way to
      allocate the length of line[]?
      >
      #include <stdio.h>
      #include <errno.h>
      >
      int main(int argc, char **argv) {
      FILE *fp;
      char line[4096];
      >
      if(argc < 2) {
      printf("usage: %s <file>\n", argv[0]);
      return(1);
      }
      >
      if((fp = fopen(argv[1], "r")) == NULL) {
      perror("fopen") ;
      return(1);
      }
      >
      while(fgets(lin e, sizeof(line), fp)) {
      printf("%s", line);
      }
      >
      return(0);
      >
      }- Hide quoted text -
      >
      - Show quoted text -
      >
      Do a web search for getline

      Comment

      • santosh

        #4
        Re: Proper fgets

        uidzer0 wrote:
        Hey everyone,
        >
        Taken the following code; is there a "proper" or dynamic way to
        allocate the length of line[]?
        >
        #include <stdio.h>
        #include <errno.h>
        >
        int main(int argc, char **argv) {
        FILE *fp;
        char line[4096];
        >
        if(argc < 2) {
        printf("usage: %s <file>\n", argv[0]);
        argv[0] need not point to the program's invocation name. Some
        environments do not provide this information.
        return(1);
        This is a non-portable return values. The portable ones are 0 and
        EXIT_SUCCESS to indicate success and EXIT_FAILURE to indicate abnormal
        termination. For both the macros, stdlib.h must be included.
        }
        >
        if((fp = fopen(argv[1], "r")) == NULL) {
        perror("fopen") ;
        fopen is not guaranteed to set errno. It's a quality-of-implementation
        issue.
        return(1);
        }
        >
        while(fgets(lin e, sizeof(line), fp)) {
        printf("%s", line);
        You should include a newline to immediately flush the output to the
        connected device.
        }
        >
        return(0);
        Parenthesis not necessary.
        }
        Now coming to your main question, yes, the most portable method to do
        what you want is to use malloc to allocate an array which you can
        resize, with realloc, on the fly, as you read in more input.
        CBFalconer often posts the sources for his 'ggets' function to do
        exactly what you want.

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

        Note: C99 has also introduced Variable Length Arrays, (VLA), which can
        do what you want in a syntactically clean form, but this is poorly
        implemented by most compilers and has a serious problem in that an
        allocation failure leads to undefined behaviour, with no way of
        detection.

        Comment

        • uidzer0

          #5
          Re: Proper fgets

          On Mar 12, 12:52 pm, "santosh" <santosh....@gm ail.comwrote:
          uidzer0 wrote:
          Hey everyone,
          >
          Taken the following code; is there a "proper" or dynamic way to
          allocate the length of line[]?
          >
          #include <stdio.h>
          #include <errno.h>
          >
          int main(int argc, char **argv) {
          FILE *fp;
          char line[4096];
          >
          if(argc < 2) {
          printf("usage: %s <file>\n", argv[0]);
          >
          argv[0] need not point to the program's invocation name. Some
          environments do not provide this information.
          >
          return(1);
          >
          This is a non-portable return values. The portable ones are 0 and
          EXIT_SUCCESS to indicate success and EXIT_FAILURE to indicate abnormal
          termination. For both the macros, stdlib.h must be included.
          >
          }
          >
          if((fp = fopen(argv[1], "r")) == NULL) {
          perror("fopen") ;
          >
          fopen is not guaranteed to set errno. It's a quality-of-implementation
          issue.
          >
          return(1);
          }
          >
          while(fgets(lin e, sizeof(line), fp)) {
          printf("%s", line);
          >
          You should include a newline to immediately flush the output to the
          connected device.
          >
          }
          >
          return(0);
          >
          Parenthesis not necessary.
          >
          }
          >
          Now coming to your main question, yes, the most portable method to do
          what you want is to use malloc to allocate an array which you can
          resize, with realloc, on the fly, as you read in more input.
          CBFalconer often posts the sources for his 'ggets' function to do
          exactly what you want.
          >
          <http://cbfalconer.home .att.net/download/ggets.zip>
          >
          Note: C99 has also introduced Variable Length Arrays, (VLA), which can
          do what you want in a syntactically clean form, but this is poorly
          implemented by most compilers and has a serious problem in that an
          allocation failure leads to undefined behaviour, with no way of
          detection.
          Perfect, thanks.

          Comment

          • Eric Sosman

            #6
            Re: Proper fgets

            uidzer0 wrote:
            Hey everyone,
            >
            Taken the following code; is there a "proper" or dynamic way to
            allocate the length of line[]?
            >
            #include <stdio.h>
            #include <errno.h>
            >
            int main(int argc, char **argv) {
            FILE *fp;
            char line[4096];
            >
            if(argc < 2) {
            printf("usage: %s <file>\n", argv[0]);
            return(1);
            }
            >
            if((fp = fopen(argv[1], "r")) == NULL) {
            perror("fopen") ;
            return(1);
            }
            >
            while(fgets(lin e, sizeof(line), fp)) {
            printf("%s", line);
            }
            >
            return(0);
            }
            The allocation looks fine as it stands, since the program
            works even if line[] holds just a fragment of a line instead
            of an entire line. The code could be improved in a number of
            small ways, but there's nothing irretrievably wrong with it.

            --
            Eric Sosman
            esosman@acm-dot-org.invalid

            Comment

            • Mark McIntyre

              #7
              Re: Proper fgets

              On 12 Mar 2007 10:51:14 -0700, in comp.lang.c , "uidzer0"
              <ben.lemasurier @gmail.comwrote :
              >That's perfect, however, it appears to be a GNU extension. Is there a
              >ANSI C way to do this?
              Look at the source for getline() ?
              --
              Mark McIntyre

              "Debugging is twice as hard as writing the code in the first place.
              Therefore, if you write the code as cleverly as possible, you are,
              by definition, not smart enough to debug it."
              --Brian Kernighan

              Comment

              • CBFalconer

                #8
                Re: Proper fgets

                uidzer0 wrote:
                >
                Taken the following code; is there a "proper" or dynamic way to
                allocate the length of line[]?
                .... snip code ...

                Yes. One example can be found in the ggets package, found at:

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

                --
                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

                Comment

                • Old Wolf

                  #9
                  Re: Proper fgets

                  On Mar 13, 6:52 am, "santosh" <santosh....@gm ail.comwrote:
                  uidzer0 wrote:
                  >
                  Taken the following code; is there a "proper" or dynamic way to
                  allocate the length of line[]?

                  while(fgets(lin e, sizeof(line), fp)) {
                  printf("%s", line);
                  >
                  Now coming to your main question, yes, the most portable method to do
                  what you want is to use malloc to allocate an array which you can
                  resize, with realloc, on the fly, as you read in more input.
                  >
                  Note: C99 has also introduced Variable Length Arrays, (VLA), which can
                  do what you want in a syntactically clean form
                  I don't see how VLA can be used to solve this problem. The VLA
                  must be declared with a size, which cannot be altered subsequently.

                  Comment

                  • Chris Torek

                    #10
                    Re: Proper fgets

                    >uidzer0 wrote:
                    [edited slightly, and trimmed heavily]
                    > while(fgets(lin e, sizeof(line), fp))
                    > printf("%s", line);
                    In article <1173721956.677 613.29330@n33g2 000cwc.googlegr oups.com>,
                    santosh <santosh.k83@gm ail.comwrote:
                    >You should include a newline to immediately flush the output to the
                    >connected device.
                    Actually, in this case, there *is* an included newline (usually):
                    it is in the string stored in "line". Remember that fgets()
                    keeps the newline at the end of the input line. There are only
                    two cases in which the newline is omitted:

                    1) The input line was so long that it had to be split. The
                    fgets() function writes the initial part of the input
                    line into the array ("line", in this case), and leaves
                    the remaining part of the input line in the input stream.[%]
                    Subsequent fgets() calls will read and consume more of
                    that line, up to and including the newline that terminates
                    it. Those partial-and-eventually-complete lines (including
                    the single terminating newline) will be passed to the
                    printf() call, so the output will re-construct the original
                    input.

                    2) The input file ended without a terminating newline, and the
                    underlying implementation chooses to handle such files by
                    reporting the final line without a terminating newline. In
                    this case, the next fgets() call will return NULL, with the
                    reason for failure being "reached end of file" (i.e., this
                    will set feof(fp)). In this case, it is usually probably best
                    to output an unterminated text line, so as to mimic the input.
                    There is no guarantee that the implementation will be able
                    to produce that output line (perhaps the input file is
                    coming from a file system that supports partial final lines,
                    while the output file is being written on one that does
                    not), but unless you have something specific in mind, adding
                    a newline terminator (to make the output "valid") is, at the
                    least, changing the input. :-)

                    So in this *particular* case -- reading an input file and copying
                    it to the standard output -- using printf with "%s" and no newline
                    is probably right. (Or, equivalently, one can use fputs(line,stdo ut)
                    in the loop body. The fputs() and puts() functions have the same
                    newline relationship, in this case, as the fgets() and gets()
                    functions: the old, less-thought-out, less-usable[$] gets() and
                    puts() fiddle with the data, while the newer, more-thought-out
                    fgets() and fputs() functions leave it unchanged, as much as
                    possible. In less precise, but more memorable, words, "gets and
                    puts delete and add a newline respectively; fgets and fputs do
                    not.")

                    -----
                    [%] This assumes the implementation is actually capable of handling
                    very long lines. Text files, on some systems, have line length
                    restrictions. If the line[] array has size 4096, but the
                    underlying system never has lines longer than 1023 characters,
                    there can never be a line long enough to split. In some
                    particularly old and klunky systems, it is even possible that
                    the input file might have lines longer than the input methods
                    can handle, in which case overlong input lines might be truncated
                    before the C system ever really "sees" them. In both cases, the
                    C compiler is effectively hobbled by the system. There is no
                    portable way around this problem, though, so one might as well
                    ignore it, in general. (In specific cases, one might be able
                    to open the text file as a "binary" file and decode the "true
                    intent" from the raw record-data. If the raw data is encoded
                    -- e.g., some form of ISAM or VSAM -- doing this can be rather
                    complex.)

                    [$] In the case of gets(), "nearly unusable". While its newline
                    removal is sometimes handy, you can only use it safely if you
                    can somehow verify the input data before reading it. On some
                    systems you could do a pre-scan of the entire file, with the
                    file somehow locked against changes, but this is nonportable
                    and, if not a bad idea for other reasons, at the least, I would
                    call it "icky". :-) One might as well just use fgets(), or
                    code similar to Chuck Falconer's ggets(), or some such.
                    --
                    In-Real-Life: Chris Torek, Wind River Systems
                    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
                    email: forget about it http://web.torek.net/torek/index.html
                    Reading email is like searching for food in the garbage, thanks to spammers.

                    Comment

                    Working...