Re: K&R2, exercise 6.4

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

    Re: K&R2, exercise 6.4

    On Mon, 05 May 2008 18:55:44 -0700, Barry Schwarz wrote:
    >On Tue, 06 May 2008 10:18:12 +0500, arnuld <sunrise@see.si gs.invalid>
    >>char *strdup( char * );
    This function name belongs to the implementation but that's also just
    another nit for the time being.
    ok, I changed the name to string_copy

    > psnode = arr_psnodes;
    > psnode_last = psnode + (ARRSIZE - 1);
    This works but you could accomplish the same thing by simply keeping a
    count of the number of elements of arr_psnodes that are in use.
    yes, I could have used array-indexing too but I am quite weak at
    understanding pointers, so I used them to get an idea about them.


    > while( getword( word, WORDSIZE ) && (psnode != psnode_last) )
    Nowhere do you prompt the user for input.
    getword() will prompt the user and return a useful value.


    > if( isalpha(word[0]) )
    >> {
    >> root_node = add_to_snode( root_node, word ); *(psnode++) = root_node;
    This does not do what you want. add_to_snode always adds new nodes at
    the end but returns the address of the first node.
    I am from C++ background and I never ever used Arrays in C++, neither
    any linked list. At present I don't understand much how these linked lists
    work. I am just confused about them but I try to learn them. I have read
    the section 6.5 8 times but still don't get the basic idea of why used
    a linked list and how they work.



    > if( p == NULL )
    For the first node (N1), this is true immediately.
    >
    On initial entry for the second node (N2a), this is false.
    >
    On the recursive entry for the second node (N2b), this is true.

    yes, right, anything NULL needs a new node as the word ha snot seen
    before.

    > if( !p )
    >> {
    >> fprintf( stderr, "out of memory\n" ); exit( EXIT_FAILURE );
    >> }
    >> }
    > p->word = strdup( w );
    > p->count = 1;
    > p->next = NULL;
    (N1) You build struct_1 with "a", 1, and NULL.
    >
    (N2b) You build struct_2 with "b", 1, and NULL.

    I though that code will make this:

    N1 -- N2 --N3 ---....


    what is the meaning of N2a and N2b, it is not a doubly-linked list. I
    thought you mean this:

    N2
    / \
    / \
    N2a N2b


    I simply have a single linked list:


    N1 -- N2 --N3 --N4 --....



    Is there any possibility the if could evaluate to false? If it is
    always true, a simple else would work just as well.

    I don't know. SInce mt program is quite raw and my understanding of linked
    lists and pointers is quite weak, so I was just avoiding any garbage value
    by using "else if".


    > p->next = add_to_snode( p->next, w );
    (N2a) So you call this function recursively with NULL and "b".
    >
    When N2b returns here, you change struct_1 to point to struct_2 (instead
    of NULL) but p still points to struct_1.

    so, should I return p->next ?

    (N1) And you return the address of struct_1 which main will store in
    root_node.
    >
    (N2b) And you return the address of struct_2 to N2a.
    >
    (N2a) And you return the address of struct_1 which main will store again
    in root_node.

    that is not what I want. I want to return the address of latest node
    created or address of the last node, if the word is already in the list.




    The routine that calls strdup does not check if it succeeded. You
    either need to check here or everywhere

    I use strcpy from library . Library does not do any check for me?


    Actually, the extra letters are not discarded. They are left in the
    input buffer and will be processed on the next call to getword as if
    they were the start of a new word.
    oh.. I am getting frustrated now.. :(


    But bullet-proofing can come later and this is not an unreasonable
    assumption to start with. By isolating getword in a separate function
    you have made it easier to fix this problem when you get around to it.

    okay, at least one thing in my program is good but getword() is just
    a modification of K&R2's getword, it is not my creation :(



    can you provide some hints on coding this program ?

    or

    you think a doubly-linked list is a good idea ?




    --

    my email ID is @ the above blog.
    just check the "About Myself" page :)

  • Richard Heathfield

    #2
    Re: K&amp;R2, exercise 6.4

    arnuld said:
    >On Mon, 05 May 2008 18:55:44 -0700, Barry Schwarz wrote:
    >
    >>On Tue, 06 May 2008 10:18:12 +0500, arnuld <sunrise@see.si gs.invalid>
    >>>char *strdup( char * );
    >
    >This function name belongs to the implementation but that's also just
    >another nit for the time being.
    >
    ok, I changed the name to string_copy
    That name also belongs to the implementation, as do all identifiers
    beginning str and continuing with a lower case letter.

    <snip>
    I am from C++ background and I never ever used Arrays in C++, neither
    any linked list. At present I don't understand much how these linked
    lists work.
    Railway train. Lots of carriages. Each carriage joined to carriage in front
    and carriage behind. End carriages have null links.

    railway ---railway ---railway ---NULL
    carriage carriage carriage
    NULL <--- A <--- B <--- C

    Voila, double-linked list. Easy.

    <snip>

    --
    Richard Heathfield <http://www.cpax.org.uk >
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999

    Comment

    • Barry Schwarz

      #3
      Re: K&amp;R2, exercise 6.4

      On Wed, 07 May 2008 08:38:50 +0500, arnuld <sunrise@see.si gs.invalid>
      wrote:
      >On Mon, 05 May 2008 18:55:44 -0700, Barry Schwarz wrote:
      >
      >>On Tue, 06 May 2008 10:18:12 +0500, arnuld <sunrise@see.si gs.invalid>
      >>>char *strdup( char * );
      >
      >This function name belongs to the implementation but that's also just
      >another nit for the time being.
      >
      >ok, I changed the name to string_copy
      Avoid creating function names beginning with str.

      snip
      >> while( getword( word, WORDSIZE ) && (psnode != psnode_last) )
      >
      >Nowhere do you prompt the user for input.
      >
      >getword() will prompt the user and return a useful value.
      The getword you provided contained no prompt.

      snip
      >> if( p == NULL )
      >
      >For the first node (N1), this is true immediately.
      >>
      >On initial entry for the second node (N2a), this is false.
      >>
      >On the recursive entry for the second node (N2b), this is true.
      >
      >
      >yes, right, anything NULL needs a new node as the word ha snot seen
      >before.
      >
      >
      >> if( !p )
      >>> {
      >>> fprintf( stderr, "out of memory\n" ); exit( EXIT_FAILURE );
      >>> }
      >>> }
      >> p->word = strdup( w );
      >> p->count = 1;
      >> p->next = NULL;
      >
      >(N1) You build struct_1 with "a", 1, and NULL.
      >>
      >(N2b) You build struct_2 with "b", 1, and NULL.
      >
      >
      >I though that code will make this:
      >
      N1 -- N2 --N3 ---....
      It does build a linked list like that. But it always returns the
      address of N1 which is what you store in arr_psnodes. At the end each
      element of arr_psnodes will contain the address of the first struct
      which is not what you want.
      >
      >
      >what is the meaning of N2a and N2b, it is not a doubly-linked list. I
      >thought you mean this:
      Since you call the same function individually for each new node and
      recursively to determine if word already exists, I used this notation
      to indicate which invocation of the function the comment applied to.
      N1 means the comment applies to the initial call for the first node.
      N2a means the comment applies to the initial call for the second node.
      N2b means the recursive call for the second node. You should read the
      N1 comments first, then the N2a ones, etc.
      >
      N2
      / \
      / \
      N2a N2b
      >
      >
      >I simply have a single linked list:
      >
      >
      N1 -- N2 --N3 --N4 --....
      >
      >
      >
      >
      >Is there any possibility the if could evaluate to false? If it is
      >always true, a simple else would work just as well.
      >
      >
      >I don't know. SInce mt program is quite raw and my understanding of linked
      >lists and pointers is quite weak, so I was just avoiding any garbage value
      >by using "else if".
      This has nothing to do with linked lists and pointers. Your previous
      if checked !match. This else if checked match. If the first if was
      true, the else prevents the second if from being evaluated. If the
      first if is false, then match must be true and you don't need to test
      it.
      >
      >
      >
      >> p->next = add_to_snode( p->next, w );
      >
      >(N2a) So you call this function recursively with NULL and "b".
      >>
      >When N2b returns here, you change struct_1 to point to struct_2 (instead
      >of NULL) but p still points to struct_1.
      >
      >
      >so, should I return p->next ?
      That only solves the problem for the second struct. The problem will
      reappear for the third.

      One way to solve the problem is to not fill in arr_psnodes until you
      are done. Then simply walk through the list saving addresses in
      arr_psnodes until p->next is NULL>
      >
      >
      >(N1) And you return the address of struct_1 which main will store in
      >root_node.
      >>
      >(N2b) And you return the address of struct_2 to N2a.
      >>
      >(N2a) And you return the address of struct_1 which main will store again
      >in root_node.
      >
      >
      >that is not what I want. I want to return the address of latest node
      >created or address of the last node, if the word is already in the list.
      >
      >
      >
      >
      >
      >The routine that calls strdup does not check if it succeeded. You
      >either need to check here or everywhere
      >
      >
      >I use strcpy from library . Library does not do any check for me?
      strdup calls malloc. malloc can fail and strdup checks before calling
      strcpy. However, strdup returns the malloc value whether it is valid
      or NULL. You will then use this value in both your sort and print
      routines which will lead to undefined behavior if they don't check.
      Rather than check in multiple places, it is better if the routine that
      calls strdup checks immediately and takes appropriate action when
      strdup fails.
      >
      >
      >
      >Actually, the extra letters are not discarded. They are left in the
      >input buffer and will be processed on the next call to getword as if
      >they were the start of a new word.
      >
      >oh.. I am getting frustrated now.. :(
      >
      >
      >
      >But bullet-proofing can come later and this is not an unreasonable
      >assumption to start with. By isolating getword in a separate function
      >you have made it easier to fix this problem when you get around to it.
      >
      >
      >okay, at least one thing in my program is good but getword() is just
      >a modification of K&R2's getword, it is not my creation :(
      >
      >
      >
      >can you provide some hints on coding this program ?
      >
      or
      >
      >you think a doubly-linked list is a good idea ?
      No one mentioned doubly linked lists which seems like overkill for
      this problem to me.


      Remove del for email

      Comment

      • arnuld

        #4
        Re: K&amp;R2, exercise 6.4

        On Tue, 06 May 2008 18:35:31 -0700, Barry Schwarz wrote:
        strdup calls malloc. malloc can fail and strdup checks before calling
        strcpy. However, strdup returns the malloc value whether it is valid
        or NULL. You will then use this value in both your sort and print
        routines which will lead to undefined behavior if they don't check.
        Rather than check in multiple places, it is better if the routine that
        calls strdup checks immediately and takes appropriate action when
        strdup fails.

        how about this ( I have changed the function name :):


        char *copy_str( char *pc )
        {
        char *dup;

        dup = malloc( strlen(pc) + 1 );

        if( !dup )
        {
        fprintf(stderr, "can not copy word. out of memory\n");
        exit( EXIT_FAILURE );
        }


        strcpy( dup, pc );

        return dup;
        }



        --

        my email ID is @ the above blog.
        just check the "About Myself" page :)

        Comment

        • Barry Schwarz

          #5
          Re: K&amp;R2, exercise 6.4

          On Wed, 07 May 2008 16:06:01 +0500, arnuld <sunrise@see.si gs.invalid>
          wrote:
          >On Tue, 06 May 2008 18:35:31 -0700, Barry Schwarz wrote:
          >
          >strdup calls malloc. malloc can fail and strdup checks before calling
          >strcpy. However, strdup returns the malloc value whether it is valid
          >or NULL. You will then use this value in both your sort and print
          >routines which will lead to undefined behavior if they don't check.
          >Rather than check in multiple places, it is better if the routine that
          >calls strdup checks immediately and takes appropriate action when
          >strdup fails.
          >
          >
          >how about this ( I have changed the function name :):
          >
          >
          >char *copy_str( char *pc )
          >{
          char *dup;
          >
          dup = malloc( strlen(pc) + 1 );
          >
          if( !dup )
          {
          fprintf(stderr, "can not copy word. out of memory\n");
          My only additional suggestion would be to include the string pc points
          to in this error message so the user has some idea of where the
          program failed.
          exit( EXIT_FAILURE );
          }
          >
          >
          strcpy( dup, pc );
          >
          return dup;
          >}
          >
          >

          Remove del for email

          Comment

          • arnuld

            #6
            Re: K&amp;R2, exercise 6.4

            On Wed, 07 May 2008 22:40:39 -0700, Barry Schwarz wrote:
            My only additional suggestion would be to include the string pc points
            to in this error message so the user has some idea of where the
            program failed.
            okay, nice idea :)


            --

            my email ID is @ the above blog.
            just check the "About Myself" page :)

            Comment

            Working...