segmentation fault with gets()

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

    segmentation fault with gets()

    I am generally new to programming under Unix, but know how to code under
    Windows. I have to create a simple program, that takes the following
    information from a file using redirection:

    4 4 4 4 4 4 5 5 5 5 5 5 3 3 3 3 3 3 3 3 2 2 2 10 10 10 1 1
    3 3 3 3 3 3 3 3 3 2 2 2 12 12 12 1 7 7 7 7 4
    12 13 13 5 5 5 3 3 9 7 7 7 5 4 4 4 3 3 3 3

    read each line, and "compress the information" to the following out print to
    be printed on screen:
    6 4
    6 5
    8 3
    3 2
    3 10
    2 1
    9 3
    3 2
    3 12
    4 7
    1 4
    1 12
    2 13
    3 5
    2 3
    1 9
    3 7
    1 5
    3 4
    4 3

    So the first column counts the occurences, and the second column in the
    integer occurence.
    I keep on getting a segmentation fault when I run my program, here is the
    source code:

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

    /* NUMBER, and COUNT are used in numbers array, indicating what is stored
    *where
    */
    #define NUMBER 0
    #define COUNT 1

    /* boolean definitions*/
    #define TRUE 1
    #define FALSE 0

    /*flag to make sure first entry is processes properly*/
    int first_run = TRUE;

    /* next=store the next value;
    * prev= stores the previous value from the stream;
    * count=keep track how many times the same number is in sequence;
    * incr_x = keeps track where to store the numbers in the numbers array;
    * incr = used to display the numbers array, when encoding is complete.
    */
    int next, prev, count, incr_x, incr;

    /* Stream string to store input to be encoded*/
    char stream[900] = "4 4 4 4 4 2 2 6 6 6 6 6 6 6 6 6 4 4 4 4 4 10 10 10 7 7 7
    7 7 4 4";

    /* Special delimiter to differient between values, this array is used with
    * strtok function, the delimiter is set to whitespaces, so when a
    whitespace
    * is found, it indicates that the next element is a number.
    */
    char delimiters[2] = " ";

    /* Token pointer stores the outcome created by strtok*/
    char *token;

    /* The numbers array stores the numbers and count of them
    * A number is stored using numbers[incr][NUMBERS]=n, and the count of that
    * number found in the sequence i stored by numbers[incr][COUNT]=c
    */
    int numbers[100][2];

    int main() {
    /* Standard input, sending data to the steam array for processing.*/

    // This is where i get the fault, the program works, if I take out
    the while, and just use the gets, but it only gets one line from the
    // file.

    while( gets( stream ) != NULL ) {
    /* Get the first element that is delimited by whitespace. */
    token = strtok( stream, delimiters );

    do {
    next = atoi( token );

    /* If it is a first run, their is not previous value, so we
    * assign prev with next.
    */
    if( first_run ) {
    prev = next;
    first_run = FALSE;
    }

    /* If next is equal to the previous value, we increment the
    count.*/
    if( next == prev ) {
    count++;

    /* If the next value does not equal the previous,
    that indicates a new
    * number was found in the stream, so we insert the previous
    value
    * into the numbers array, and store how many times it was found
    * sequentially, and then we reset the count, and increment
    the numbers
    * array for the next value.
    */
    } else {
    numbers[incr_x][NUMBER] = prev;
    numbers[incr_x][COUNT] = count;
    count = 1;
    incr_x++;
    }
    prev = next;
    /* We stop when the stream is finished.*/
    } while( ( token = strtok( NULL,delimiters ) ) != NULL );

    /* Since the strtok ends the do.while loop, before we can
    process the
    * last number found, we do it here.
    */
    numbers[incr_x][NUMBER] = next;
    numbers[incr_x][COUNT] = count;
    incr_x ++;
    }
    /* Print out our results. */
    for( incr=0; incr < incr_x; incr++ ) {
    printf( "%d %d\n", numbers[incr][COUNT],
    numbers[incr][NUMBER] );
    }
    return 0;
    }

    I wrote a comment where, I think the fault is occurring. Essentially, the
    instructions told us we could only use scanf and printf for our I/O, but I
    couldn't see how to use scanf to get what I want, so I decided to side line
    one spec, and use gets(). With that in mind, I am limited to the use of
    functions, and do not want to stray further from using gets or scanf.

    Thanks

    --
    Peter Dragun
    Faculty of Computer Science 2nd year student
    Western University, London, Ontario, Canada


  • Derk Gwen

    #2
    Re: segmentation fault with gets()

    # /* Standard input, sending data to the steam array for processing.*/
    #
    # // This is where i get the fault, the program works, if I take out
    # the while, and just use the gets, but it only gets one line from the
    # // file.
    #
    # while( gets( stream ) != NULL ) {

    Have you verified the input doesn't overflow the buffer? There's a reason
    most people used fgets instead.

    --
    Derk Gwen http://derkgwen.250free.com/html/index.html
    Mention something out of a Charleton Heston movie, and suddenly
    everybody's a theology scholar.

    Comment

    • Peter Dragun

      #3
      Re: segmentation fault with gets()

      I have been reading upon, how dangerous gets() is, could you help me provide
      an alternative using scanf or fgets(without reading a file, but still using
      the stdin)?



      "Derk Gwen" <derkgwen@HotPO P.com> wrote in message
      news:vp5jjknkcs irb1@corp.super news.com...[color=blue]
      > # /* Standard input, sending data to the steam array for[/color]
      processing.*/[color=blue]
      > #
      > # // This is where i get the fault, the program works, if I take[/color]
      out[color=blue]
      > # the while, and just use the gets, but it only gets one line from the
      > # // file.
      > #
      > # while( gets( stream ) != NULL ) {
      >
      > Have you verified the input doesn't overflow the buffer? There's a reason
      > most people used fgets instead.
      >
      > --
      > Derk Gwen http://derkgwen.250free.com/html/index.html
      > Mention something out of a Charleton Heston movie, and suddenly
      > everybody's a theology scholar.[/color]


      Comment

      • Irrwahn Grausewitz

        #4
        Re: segmentation fault with gets()

        "Peter Dragun" <pdragun@cogeco .ca_NOSPAM> wrote:
        [color=blue]
        >I have been reading upon, how dangerous gets() is, could you help me provide
        >an alternative using scanf or fgets(without reading a file, but still using
        >the stdin)?[/color]

        <snip>

        ....
        #define BUFLEN 900
        ....
        char stream[BUFLEN];
        ....
        while( fgets( stream, BUFLEN, stdin ) {
        ....

        HTH

        Regards
        --
        Irrwahn
        (irrwahn33@free net.de)

        Comment

        • Richard Heathfield

          #5
          Re: segmentation fault with gets()

          Peter Dragun wrote:
          [color=blue]
          > I have been reading upon, how dangerous gets() is, could you help me
          > provide an alternative using scanf or fgets(without reading a file, but
          > still using the stdin)?[/color]

          /* untested code - beware! */

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

          int chop(char *s)
          {
          int chopped = 0;
          char *p = strchr(s, '\n');
          if(p != NULL)
          {
          *p = '\0';
          chopped = 1;
          }
          return chopped;
          }

          #define SOME_SIZE_OR_OT HER 32

          int main(void)
          {
          char buf[SOME_SIZE_OR_OT HER] = {0};

          if(fgets(buf, sizeof buf, stdin) != NULL)
          {
          if(chop(buf))
          {
          printf("The string is [%s]\n", buf);
          }
          else
          {
          printf("The string was a tad long. Here's "
          "some of it: [%s]\n", buf);
          if(fgets(buf, sizeof buf, stdin) != NULL)
          {
          printf("Here's some more: %s\n", buf);
          }
          }
          }
          else
          {
          printf("EOF or error encountered.\n" );
          if(ferror(stdin ))
          {
          printf("Error.\ n");
          }
          else
          {
          printf("EOF.\n" );
          }
          }
          return 0;
          }

          --
          Richard Heathfield : binary@eton.pow ernet.co.uk
          "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
          C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
          K&R answers, C books, etc: http://users.powernet.co.uk/eton

          Comment

          • Richard Heathfield

            #6
            Re: segmentation fault with gets()

            Irrwahn Grausewitz wrote:
            [color=blue]
            > ...
            > #define BUFLEN 900
            > ...
            > char stream[BUFLEN];
            > ...
            > while( fgets( stream, BUFLEN, stdin ) {[/color]

            Better than BUFLEN: sizeof stream

            --
            Richard Heathfield : binary@eton.pow ernet.co.uk
            "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
            C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
            K&R answers, C books, etc: http://users.powernet.co.uk/eton

            Comment

            • Irrwahn Grausewitz

              #7
              Re: segmentation fault with gets()

              Richard Heathfield <dontmail@addre ss.co.uk.invali d> wrote:
              [color=blue]
              >Irrwahn Grausewitz wrote:
              >[color=green]
              >> ...
              >> #define BUFLEN 900
              >> ...
              >> char stream[BUFLEN];
              >> ...
              >> while( fgets( stream, BUFLEN, stdin ) {[/color]
              >
              >Better than BUFLEN: sizeof stream[/color]

              Indeed.
              --
              Irrwahn
              (irrwahn33@free net.de)

              Comment

              • Irrwahn Grausewitz

                #8
                Re: segmentation fault with gets()

                "Peter Dragun" <pdragun@cogeco .ca_NOSPAM> wrote:
                [color=blue]
                >I am generally new to programming under Unix, but know how to code under
                >Windows. I have to create a simple program, that takes the following
                >information from a file using redirection:
                >[/color]
                <snip>[color=blue]
                >read each line, and "compress the information" to the following out print to
                >be printed on screen:[/color]
                <snip>

                /* If this is homework, don't read any further!!!!
                *
                *
                *
                *
                *
                *
                *
                *
                *
                *
                *
                *
                *
                */

                #include <stdio.h>

                int main( void )
                {
                int n = 0,
                nn = 0,
                cnt = 0,
                run = 1;

                while( run )
                {
                if ( scanf( "%d", &n ) != 1 )
                run = 0;

                if ( n != nn || !run )
                {
                if ( cnt )
                printf( "%d %d\n", cnt, nn );
                nn = n;
                cnt = 1;
                }
                else
                ++cnt;
                }
                return 0;
                }

                Regards
                --
                Irrwahn
                (irrwahn33@free net.de)

                Comment

                • Joe Wright

                  #9
                  Re: segmentation fault with gets()

                  Irrwahn Grausewitz wrote:[color=blue]
                  >
                  > Richard Heathfield <dontmail@addre ss.co.uk.invali d> wrote:
                  >[color=green]
                  > >Irrwahn Grausewitz wrote:
                  > >[color=darkred]
                  > >> ...
                  > >> #define BUFLEN 900
                  > >> ...
                  > >> char stream[BUFLEN];
                  > >> ...
                  > >> while( fgets( stream, BUFLEN, stdin ) {[/color]
                  > >
                  > >Better than BUFLEN: sizeof stream[/color]
                  >[/color]
                  Also better would be ...
                  while( fgets( stream, sizeof stream, stdin )) {}
                  so that the right paren doesn't get lonely. :-)
                  --
                  Joe Wright http://www.jw-wright.com
                  "Everything should be made as simple as possible, but not simpler."
                  --- Albert Einstein ---

                  Comment

                  • CBFalconer

                    #10
                    Re: segmentation fault with gets()

                    Peter Dragun wrote:[color=blue]
                    >
                    > I am generally new to programming under Unix, but know how to
                    > code under Windows. I have to create a simple program, that takes
                    > the following information from a file using redirection:
                    >
                    > 4 4 4 4 4 4 5 5 5 5 5 5 3 3 3 3 3 3 3 3 2 2 2 10 10 10 1 1
                    > 3 3 3 3 3 3 3 3 3 2 2 2 12 12 12 1 7 7 7 7 4
                    > 12 13 13 5 5 5 3 3 9 7 7 7 5 4 4 4 3 3 3 3
                    >
                    > read each line, and "compress the information" to the following
                    > out print to be printed on screen:
                    > 6 4
                    > 6 5
                    > 8 3
                    > 3 2
                    > 3 10
                    > 2 1
                    > 8 3
                    > .... snip ...
                    >
                    > So the first column counts the occurences, and the second column
                    > in the integer occurence.
                    > I keep on getting a segmentation fault when I run my program,
                    > here is the source code:
                    >[/color]
                    .... snip code using gets ...[color=blue]
                    >
                    > I wrote a comment where, I think the fault is occurring.
                    > Essentially, the instructions told us we could only use scanf
                    > and printf for our I/O, but I couldn't see how to use scanf to
                    > get what I want, so I decided to side line one spec, and use
                    > gets(). With that in mind, I am limited to the use of functions,
                    > and do not want to stray further from using gets or scanf.[/color]

                    Bad decision. Your instructor was leading you in the right
                    direction. Think about what scanf does ... it extracts a number
                    (or other things) from an incoming stream. It requires no extra
                    buffering of the incoming stream, and will skip all white space
                    while extracting numbers. It also tells you if it succeeded. So,
                    the phrase:

                    int anint;
                    ....
                    if (1 == scanf(stdin, "%d", &anint)) {
                    /* whatever */
                    }

                    will extract a number and tell you if it succeeded. You can also
                    modify that into a while statement. Now think about how you can
                    tell if this is the same number as the previous one, and what to
                    do if it is, or if it isn't. Then think about how to get the
                    process started. You may well find you need a few extra variables
                    and initialization.

                    When you are finished you will be astounded at how simple it is.

                    --
                    Chuck F (cbfalconer@yah oo.com) (cbfalconer@wor ldnet.att.net)
                    Available for consulting/temporary embedded and systems.
                    <http://cbfalconer.home .att.net> USE worldnet address!


                    Comment

                    • Chris Torek

                      #11
                      Re: segmentation fault with gets()

                      In article <J%ykb.198649$k o%.99848@news04 .bloor.is.net.c able.rogers.com >
                      Peter Dragun <pdragun@cogeco .ca_NOSPAM> writes:[color=blue]
                      >... I have to create a simple program, that takes the following
                      >information from a file using redirection:
                      >
                      >4 4 4 4 4 4 5 5 5 5 5 5 3 3 3 3 3 3 3 3 2 2 2 10 10 10 1 1
                      >3 3 3 3 3 3 3 3 3 2 2 2 12 12 12 1 7 7 7 7 4
                      >12 13 13 5 5 5 3 3 9 7 7 7 5 4 4 4 3 3 3 3
                      >
                      >read each line, and "compress the information" ...[/color]

                      [in short, using a form of Run-Length Encoding; the output is
                      (N,value) pairs representing N instances of the given value].

                      Without answering questions about gets() (others have done that
                      already), I will note that the first thing I thought about when
                      I read the above is:

                      What if the input has the same integer value split across
                      several lines?

                      For instance, if the input is:

                      4
                      4
                      4 5
                      5 101 7

                      should the output be:

                      1 4
                      1 4
                      1 4
                      1 5
                      1 101
                      1 7

                      or should it be:

                      3 4
                      2 5
                      1 101
                      1 7

                      ?

                      Later, you note:
                      [color=blue]
                      >the instructions told us we could only use scanf ...[/color]

                      which suggests (but does not say for certain) that the answer is
                      the latter. In particular, if you use scanf's "%d" format, the
                      scanf engine -- the code shared by scanf, fscanf, sscanf, and in
                      C99 the various vscanf routines -- will skip "white space", and
                      newlines are considered white space. Hence a loop of the form:

                      while (scanf("%d", &var) == 1)

                      will eat right through those newlines, producing the second kind
                      of output. (Note that scanf() will "jam" if it hits a non-numeric,
                      non-white-space character, so this kind of loop is certainly not
                      "robust" against malformed input. As a result you might actually
                      do better, in the end, using fgets(), unless of course you are Dan
                      Pop. :-) )

                      (The reason I say "does not say for certain" is that if you use
                      scanf with "%c" formats, and "manual" conversion of integer values
                      one digit at a time, you will be able to "see" the newlines in the
                      input stream. This again gives you the choice of whether to consider
                      newlines significant. Note, however, that the first form of output
                      does *not* allow you to reconstruct the original set of newlines.
                      If the RLE-output says "N1 X" followed by "N2 X" -- i.e., if the
                      value being run-length encoded repeats -- then you know for certain
                      there was a newline between these, but if the value after N2 is
                      not X, you do not know whether there was a newline there. That
                      makes it hard for me to imagine why anyone would *want* the first
                      form of output.)
                      --
                      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://67.40.109.61/torek/index.html (for the moment)
                      Reading email is like searching for food in the garbage, thanks to spammers.

                      Comment

                      Working...