K&R2 Exercise 4-12

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

    K&R2 Exercise 4-12

    Here is my 1st attempt at the solution for K&R2 Exercise 4-12:

    void itoa(int n, char *s)
    {

    if (n < 0)
    {
    *s++ = '-';
    n = -n;
    }

    if( n/10 0 )
    itoa( n/10, s );

    *s++ = n%10 + '0';
    *s = 0;
    }


    I realize why my code is not working, it's because the increments
    don't carry forward when the recursive calls "unwind."

    I can solve this this way:


    void itoa2(int n, char *s)
    {
    static char *p = 0;

    if(p == 0)
    p = s;

    if (n < 0)
    {
    *p++ = '-';
    n = -n;
    }

    if( n/10 0 )
    itoa2( n/10, p );

    *p++ = n%10 + '0';
    *p = 0;
    }


    This keeps the p pointer up-to-date while the recursive calls unwind.

    My quesiton is, does anyone know of a solution that doesn't require
    the introduction of a static duration variable? Something like a small
    modifcation to my first attempt?
  • Richard Heathfield

    #2
    Re: K&amp;R2 Exercise 4-12

    Lax said:
    Here is my 1st attempt at the solution for K&R2 Exercise 4-12:
    >
    void itoa(int n, char *s)
    {
    >
    if (n < 0)
    {
    *s++ = '-';
    n = -n;
    }
    >
    if( n/10 0 )
    itoa( n/10, s );
    >
    *s++ = n%10 + '0';
    *s = 0;
    }
    >
    >
    I realize why my code is not working, it's because the increments
    don't carry forward when the recursive calls "unwind."
    In a real itoa, you'd want to take a maximum length, to reduce the risk of
    buffer overruns. The following fixes your problem, I think (although I
    haven't actually tested it).

    void itoasub(int n, char **s)
    {
    if(n / 10 0)
    {
    itoasub(n / 10, s);
    }
    **s = n % 10 + '0';
    ++*s;
    }
    void itoa(int n, char *s)
    {
    if(n < 0)
    {
    *s++ = '-';
    n = -n; /* beware INT_MIN! */
    }
    itoasub(n, &s);
    *s = 0;
    }

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

    • Bartc

      #3
      Re: K&amp;R2 Exercise 4-12


      "Lax" <Lax.Clarke@gma il.comwrote in message
      news:1737a679-a647-40be-a053-47a96987c45b@k3 7g2000hsf.googl egroups.com...
      Here is my 1st attempt at the solution for K&R2 Exercise 4-12:
      >
      void itoa(int n, char *s)
      {
      >
      if (n < 0)
      {
      *s++ = '-';
      n = -n;
      }
      >
      if( n/10 0 )
      itoa( n/10, s );
      >
      *s++ = n%10 + '0';
      *s = 0;
      }
      Try this; it uses a local variable, and calls strlen a lot, so is a bit
      slower:

      void itoa(int n, char *s)
      {int len;

      *s=0;

      if (n < 0)
      {
      *s++ = '-';
      n = -n;
      }

      if( n>=10 )
      itoa( n/10, s );
      len=strlen(s);
      s[len]= n%10 + '0';
      s[len+1]=0;
      }

      --
      Bart


      Comment

      • Ben Bacarisse

        #4
        Re: K&amp;R2 Exercise 4-12

        Lax <Lax.Clarke@gma il.comwrites:
        Here is my 1st attempt at the solution for K&R2 Exercise 4-12:
        <snip not quite solution>
        I can solve this this way:
        >
        void itoa2(int n, char *s)
        {
        static char *p = 0;
        >
        if(p == 0)
        p = s;
        >
        if (n < 0)
        {
        *p++ = '-';
        n = -n;
        Small point: in C -n can overflow. I am sure that K&R don't intend
        that you deal with this here, but a real itoa would have to.
        }
        >
        if( n/10 0 )
        itoa2( n/10, p );
        >
        *p++ = n%10 + '0';
        *p = 0;
        }
        >
        >
        This keeps the p pointer up-to-date while the recursive calls unwind.
        >
        My quesiton is, does anyone know of a solution that doesn't require
        the introduction of a static duration variable? Something like a small
        modifcation to my first attempt?
        Well, not a tweak but a general idea: recursion works particularly
        well with functions that have simple value parameters and return useful
        results. In fact, that pattern can be grown into a whole methodology
        of programming.

        Since the interface of itoa is fixed, you need a helper function. The
        trick is thinking up the most helpful function you can imagine. Often
        that function can then be written in terms of itself and the desired
        function becomes a simple call of it with a little extra
        house-keeping. For example:

        Given 'char *aux_itoa(int n, char *s);' that takes a positive 'n',
        puts the character representation of 'n' into 's' and returns a pointer
        to the end of that representation, could you write both itoa and also
        aux_itoa?

        --
        Ben.

        Comment

        • Martin

          #5
          Re: K&amp;R2 Exercise 4-12

          On Sun, 13 Apr 2008 08:14:18 +0100, Lax <Lax.Clarke@gma il.comwrote:
          Here is my 1st attempt at the solution for K&R2 Exercise 4-12:
          >
          void itoa(int n, char *s)
          {
          >
          if (n < 0)
          {
          *s++ = '-';
          n = -n;
          }
          >
          if( n/10 0 )
          itoa( n/10, s );
          >
          *s++ = n%10 + '0';
          *s = 0;
          }
          Any comments on Tondo & Gimpel's solution, in THE C ANSWER BOOK?

          #include <math.h>

          /* itoa: convert n to characters in s; recursive */
          void itoa(int n, char s[])
          {
          static int i;

          if ( n / 10 )
          itoa(n / 10, s);
          else {
          i = 0;
          if (n < 0)
          s[i++] = '-';
          }
          s[i++] = abs(n) % 10 + '0';
          s[i] = '0';
          }

          --
          Martin

          Comment

          • Flash Gordon

            #6
            Re: K&amp;R2 Exercise 4-12

            Martin wrote, On 15/04/08 13:44:

            <snip>
            Any comments on Tondo & Gimpel's solution, in THE C ANSWER BOOK?
            If you have correctly presented it, then it is not very good.
            #include <math.h>
            This header is not needed.
            /* itoa: convert n to characters in s; recursive */
            void itoa(int n, char s[])
            {
            static int i;
            >
            if ( n / 10 )
            itoa(n / 10, s);
            else {
            i = 0;
            if (n < 0)
            s[i++] = '-';
            }
            s[i++] = abs(n) % 10 + '0';
            For abs you should include stdlib.h
            s[i] = '0';
            }
            Now try running it with the following main function calling it...

            int main(void)
            {
            char s1[]="abcdef",s2[]="ghijk";
            itoa(1,s1);
            itoa(2,s2);
            printf("1='%s' 2='%s'\n",s1,s2 );
            return 0;
            }

            Then try reading the code and see if you can find the error.
            --
            Flash Gordon

            Comment

            • Dann Corbit

              #7
              Re: K&amp;R2 Exercise 4-12

              "Flash Gordon" <spam@flash-gordon.me.ukwro te in message
              news:oe7fd5xqel .ln2@news.flash-gordon.me.uk...
              Martin wrote, On 15/04/08 13:44:
              >
              <snip>
              >
              >Any comments on Tondo & Gimpel's solution, in THE C ANSWER BOOK?
              >
              If you have correctly presented it, then it is not very good.
              >
              >#include <math.h>
              >
              This header is not needed.
              >
              >/* itoa: convert n to characters in s; recursive */
              >void itoa(int n, char s[])
              >{
              > static int i;
              >>
              > if ( n / 10 )
              > itoa(n / 10, s);
              > else {
              > i = 0;
              > if (n < 0)
              > s[i++] = '-';
              > }
              > s[i++] = abs(n) % 10 + '0';
              >
              For abs you should include stdlib.h
              >
              > s[i] = '0';
              >}
              >
              Now try running it with the following main function calling it...
              >
              int main(void)
              {
              char s1[]="abcdef",s2[]="ghijk";
              itoa(1,s1);
              itoa(2,s2);
              printf("1='%s' 2='%s'\n",s1,s2 );
              return 0;
              }
              >
              Then try reading the code and see if you can find the error.
              It has to be a typo (obviously). But even after the obvious fix, there is
              still a problem with INT_MIN:

              #include <stdlib.h>
              /* my_itoa: convert n to characters in s; recursive */
              void my_itoa(int n, char s[])
              {
              static int i;

              if (n / 10)
              my_itoa(n / 10, s);
              else {
              i = 0;
              if (n < 0)
              s[i++] = '-';
              }
              s[i++] = abs(n) % 10 + '0';
              s[i] = 0;
              }

              #include <stdio.h>
              #include <string.h>
              #include <limits.h>
              int main(void)
              {
              char s1[80] = "abcdef";
              char s2[80] = "abcdef";
              my_itoa(INT_MAX , s1);
              my_itoa(INT_MIN , s2);
              printf("INT_MAX ='%s' INT_MIN='%s'\n" , s1, s2);
              return 0;
              }



              ** Posted from http://www.teranews.com **

              Comment

              • Peter Nilsson

                #8
                Re: K&amp;R2 Exercise 4-12

                Lax wrote:
                Here is my 1st attempt at the solution for K&R2 Exercise 4-12:
                >
                void itoa(int n, char *s)
                <snip>
                My quesiton is, does anyone know of a solution that doesn't require
                the introduction of a static duration variable? Something like a small
                modifcation to my first attempt?
                Google comp.lang.c for itoa. This is not the first time the function
                has been discussed.

                --
                Peter

                Comment

                • Bartc

                  #9
                  Re: K&amp;R2 Exercise 4-12

                  Martin wrote:
                  On Sun, 13 Apr 2008 08:14:18 +0100, Lax <Lax.Clarke@gma il.comwrote:
                  >Here is my 1st attempt at the solution for K&R2 Exercise 4-12:
                  >>
                  >void itoa(int n, char *s)
                  >{
                  >>
                  > if (n < 0)
                  > {
                  > *s++ = '-';
                  > n = -n;
                  > }
                  >>
                  > if( n/10 0 )
                  > itoa( n/10, s );
                  >>
                  > *s++ = n%10 + '0';
                  > *s = 0;
                  >}
                  >
                  Any comments on Tondo & Gimpel's solution, in THE C ANSWER BOOK?
                  >
                  #include <math.h>
                  >
                  /* itoa: convert n to characters in s; recursive */
                  void itoa(int n, char s[])
                  {
                  static int i;
                  The OP wanted something without a 'static duration variable'.


                  -- Bartc


                  Comment

                  • user923005

                    #10
                    Re: K&amp;R2 Exercise 4-12

                    On Apr 16, 3:14 am, "Bartc" <b...@freeuk.co mwrote:
                    Martin wrote:
                    On Sun, 13 Apr 2008 08:14:18 +0100, Lax <Lax.Cla...@gma il.comwrote:
                    Here is my 1st attempt at the solution for K&R2 Exercise 4-12:
                    >
                    void itoa(int n, char *s)
                    {
                    >
                        if (n < 0)
                        {
                            *s++ = '-';
                            n = -n;
                        }
                    >
                        if( n/10 0 )
                            itoa( n/10, s );
                    >
                        *s++ = n%10 + '0';
                        *s = 0;
                    }
                    >
                    Any comments on Tondo & Gimpel's solution, in THE C ANSWER BOOK?
                    >
                    #include <math.h>
                    >
                    /* itoa: convert n to characters in s; recursive */
                    void itoa(int n, char s[])
                    {
                         static int i;
                    >
                    The OP wanted something without a 'static duration variable'.
                    As a sensible solution, snprintf() springs to mind. A simpler way to
                    remove the static and remain recursive is to have one top level
                    function that calls the recursive function and passes in an
                    initialized counter.

                    Comment

                    • Willem

                      #11
                      Re: K&amp;R2 Exercise 4-12

                      Lax wrote:
                      ) Here is my 1st attempt at the solution for K&R2 Exercise 4-12:
                      )
                      ) void itoa(int n, char *s)
                      ) {
                      )
                      ) if (n < 0)
                      ) {
                      ) *s++ = '-';
                      ) n = -n;
                      ) }
                      )
                      ) if( n/10 0 )
                      ) itoa( n/10, s );
                      )
                      ) *s++ = n%10 + '0';
                      ) *s = 0;
                      ) }
                      )
                      )
                      ) I realize why my code is not working, it's because the increments
                      ) don't carry forward when the recursive calls "unwind."
                      )
                      ) I can solve this this way:
                      )
                      )
                      ) void itoa2(int n, char *s)
                      ) {
                      ) static char *p = 0;
                      )
                      ) if(p == 0)
                      ) p = s;
                      )
                      ) if (n < 0)
                      ) {
                      ) *p++ = '-';
                      ) n = -n;
                      ) }
                      )
                      ) if( n/10 0 )
                      ) itoa2( n/10, p );
                      )
                      ) *p++ = n%10 + '0';
                      ) *p = 0;
                      ) }
                      )
                      )
                      ) This keeps the p pointer up-to-date while the recursive calls unwind.
                      )
                      ) My quesiton is, does anyone know of a solution that doesn't require
                      ) the introduction of a static duration variable? Something like a small
                      ) modifcation to my first attempt?

                      A simple way would be to have two functions and pass a pointer to pointer:

                      void itoa_r(int n, char **s)
                      {
                      if( n/10 0 )
                      itoa2( n/10, s );
                      (*s)++ = n%10 + '0';
                      }

                      void itoa(int n, char *s)
                      {
                      if (n < 0) {
                      *s++ = '-';
                      n = -n;
                      }
                      itoa_r(n, &s);
                      *s = 0;
                      }


                      SaSW, Willem
                      --
                      Disclaimer: I am in no way responsible for any of the statements
                      made in the above text. For all I know I might be
                      drugged or something..
                      No I'm not paranoid. You all think I'm paranoid, don't you !
                      #EOT

                      Comment

                      • Martin

                        #12
                        Re: K&amp;R2 Exercise 4-12

                        On Tue, 15 Apr 2008 23:04:49 +0100, Dann Corbit <dcorbit@connx. comwrote:
                        It has to be a typo (obviously).
                        Indeed. I missed out the backslash, so the incorrect line:

                        s[i] = '0';

                        should be:

                        s[i] = '\0';

                        But Dann's

                        s[i] = 0;

                        will do!

                        That was the only typing mistake I made. T&G's response does include
                        <math.hin its solution.

                        But even after the obvious fix, there is still a problem with INT_MIN:
                        >
                        ... itoa ...
                        >
                        #include <stdio.h>
                        #include <string.h>
                        #include <limits.h>
                        int main(void)
                        {
                        char s1[80] = "abcdef";
                        char s2[80] = "abcdef";
                        my_itoa(INT_MAX , s1);
                        my_itoa(INT_MIN , s2);
                        printf("INT_MAX ='%s' INT_MIN='%s'\n" , s1, s2);
                        return 0;
                        }
                        I get:

                        INT_MAX='214748 3647' INT_MIN='-214748364('

                        which is puzzling.

                        --
                        Martin

                        Comment

                        • Martin

                          #13
                          Re: K&amp;R2 Exercise 4-12

                          On Wed, 16 Apr 2008 11:14:06 +0100, Bartc <bc@freeuk.comw rote:
                          The OP wanted something without a 'static duration variable'.
                          Yes. T&G's solution is answering K&R2's question (or trying to anyway).

                          --
                          Martin

                          Comment

                          • Ben Bacarisse

                            #14
                            Re: K&amp;R2 Exercise 4-12

                            Martin <m@b.cwrites:
                            I get:
                            >
                            INT_MAX='214748 3647' INT_MIN='-214748364('
                            >
                            which is puzzling.
                            There is a bug (two, really). The solution should include <stdlib.h>
                            not <math.hand abs(n) is undefined when n == INT_MIN on some
                            systems. I think this version is correct (but I prefer my other
                            posted solution!):

                            #include <stdlib.h>

                            void itoa(int n, char s[])
                            {
                            static int i;

                            if ( n / 10 )
                            itoa(n / 10, s);
                            else {
                            i = 0;
                            if (n < 0)
                            s[i++] = '-';
                            }
                            s[i++] = abs(n % 10) + '0'; /* Note: not abs(n) % 10. */
                            s[i] = '\0';
                            }

                            --
                            Ben.

                            Comment

                            • CBFalconer

                              #15
                              Re: K&amp;R2 Exercise 4-12

                              Martin wrote:
                              >
                              .... snip ...
                              >
                              I get:
                              >
                              INT_MAX='214748 3647' INT_MIN='-214748364('
                              >
                              which is puzzling.
                              Sounds like a bug in limits.h. The entry for INT_MIN should be:

                              #define INT_MIN = (-2137482647 - 1)

                              and probably is:

                              #define INT_MIN = (-2137482648)

                              because the expression "-number" loads number and then negates it.

                              --
                              [mail]: Chuck F (cbfalconer at maineline dot net)
                              [page]: <http://cbfalconer.home .att.net>
                              Try the download section.


                              ** Posted from http://www.teranews.com **

                              Comment

                              Working...