[comp.lang.c] integer to string function

brad@SSD.CSD.HARRIS.COM (Brad Appleton) (06/29/90)

In article <22888@boulder.Colorado.EDU> baileyc@tramp.Colorado.EDU (BAILEY CHRISTOPHER R) writes:

>Help, I need an itoa() function for use with my Sun compiler.

Perhaps I missed something but ...  Is there some reason why:

  int i = 10; char a[3];
  sprintf( a, "%d", i );

is unnacceptable for your purposes?

______________________ "And miles to go before I sleep." ______________________
 Brad Appleton         brad@hcx1.ssd.csd.harris.com    Harris Computer Systems
                           ...!uunet!hcx1!brad         Fort Lauderdale, FL USA
~~~~~~~~~~~~~~~~~~~~ Disclaimer: I said it, not my company! ~~~~~~~~~~~~~~~~~~~

carroll@m.cs.uiuc.edu (06/29/90)

/* Written  3:06 pm  Jun 28, 1990 by baileyc@boulder.Colorado.EDU in m.cs.uiuc.edu:comp.lang.c */
/* ---------- "integer to string function (itoa())" ---------- */
>Help, I need an itoa() function for use with my Sun compiler. 
Sent. Email if anyone else wants it. Handles base 2..36.

dankg@monsoon.Berkeley.EDU (Dan KoGai) (06/30/90)

In article <153@travis.csd.harris.com> brad@SSD.CSD.HARRIS.COM (Brad Appleton) writes:
>In article <22888@boulder.Colorado.EDU> baileyc@tramp.Colorado.EDU (BAILEY CHRISTOPHER R) writes:
>
>>Help, I need an itoa() function for use with my Sun compiler.
>
>Perhaps I missed something but ...  Is there some reason why:
>
>  int i = 10; char a[3];
>  sprintf( a, "%d", i );
>
>is unnacceptable for your purposes?

	Maybe.  But I was wondering why there's no itoa() in most C libraries:
atoi() exists and often used in scanf().  Why do we let [sf]printf() do
all conversion instead of calling itoa...

	itoa() would be not that hard to program.  Let me make it up:

/*
 * itoa.c
 * converts integer to ascii string
 */

char *itoa(int i)
/* or
 * char
 * itoa(i)
 * int i;
 */
{
  static char buf[16]; /* twelve will suffice including sign but hell */
  char *bufptr = &buf[15]; /* bufptr pts at the end of buf */
  char sign = 0;/* true if negative */
  *bufptr-- = 0;/* terminate string for sure */
  if (i < 0) {
    sign = 1;	/* set negative */
    i = -i;	/* i must be positve for do-while loop */
  } 
  do{	/* while fails if i = 0 */
    *bufptr-- = i % 10 + '0'; /* sets digit from low to high */
    i /= 10;/* shift one digit */
  }while(i != 0);
  if (sign) {
    *bufptr = '-';	/* if negative put '-' */
    return bufptr;
  }
  else return ++bufptr;	/* rewind overrun bufptr */
}

/* main() for test */
main(int argc, char **argv){
  int i = atoi(argv[1]);
  printf("via printf:%d via itoa:%s\n", i, itoa(i));
}

	This should work unless your character table is so wierd that it
doesn't have [0-9] consecutively

cpcahil@virtech.uucp (Conor P. Cahill) (06/30/90)

In article <1990Jun30.071229.23965@agate.berkeley.edu> dankg@monsoon.Berkeley.EDU (Dan KoGai) writes:
>In article <153@travis.csd.harris.com> brad@SSD.CSD.HARRIS.COM (Brad Appleton) writes:
>>In article <22888@boulder.Colorado.EDU> baileyc@tramp.Colorado.EDU (BAILEY CHRISTOPHER R) writes:
>>
>>>Help, I need an itoa() function for use with my Sun compiler.
>>
>>Perhaps I missed something but ...  Is there some reason why:
>>
>	Maybe.  But I was wondering why there's no itoa() in most C libraries:
>atoi() exists and often used in scanf().  Why do we let [sf]printf() do
>all conversion instead of calling itoa...

When this was first posted, I was a bit skeptical about it.  A posting from
a university asking for a simple C routine that is presented in it's entirety
in K&R1 (pg 60).  I was inclined to believe this was for a class project.

Anyway, since people have already posted several solutions, here is mine (this
function will do binary, octal, decimal, and hexidecimal conversions, although
I have not modified it to handle negative numbers).  Have fun.


#!/bin/sh
# This is a shell archive (shar 3.21)
# made 06/30/1990 13:50 UTC by cpcahil@virtech
# Source directory /usr/local/src/lib/malloclib
#
# existing files WILL be overwritten
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#    491 -r--r--r-- tostring.h
#   2716 -r--r--r-- tostring.c
#
if touch 2>&1 | fgrep '[-amc]' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= tostring.h ==============
echo "x - extracting tostring.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > tostring.h &&
X/*
X * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).  
X * You may copy, distribute, and use this software as long as this
X * copyright statement is not removed.
X */
X/*
X * $Id: tostring.h,v 1.2 90/05/11 00:13:11 cpcahil Exp $
X */
X#define B_BIN	 2
X#define B_DEC	10
X#define B_HEX	16
X#define B_OCTAL	 8
X
X/* 
X * $Log:	tostring.h,v $
X * Revision 1.2  90/05/11  00:13:11  cpcahil
X * added copyright statment
X * 
X * Revision 1.1  90/02/23  07:09:05  cpcahil
X * Initial revision
X * 
X */
SHAR_EOF
$TOUCH -am 0511001490 tostring.h &&
chmod 0444 tostring.h ||
echo "restore of tostring.h failed"
set `wc -c tostring.h`;Wc_c=$1
if test "$Wc_c" != "491"; then
	echo original size 491, current size $Wc_c
fi
# ============= tostring.c ==============
echo "x - extracting tostring.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > tostring.c &&
X/*
X * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).  
X * You may copy, distribute, and use this software as long as this
X * copyright statement is not removed.
X */
X#include "tostring.h"
X
X/*
X * Function:	tostring()
X *
X * Purpose:	to convert an integer to an ascii display string
X *
X * Arguments:	buf	- place to put the 
X *		val	- integer to convert
X *		len	- length of output field (0 if just enough to hold data)
X *		base	- base for number conversion (only works for base <= 16)
X *		fill	- fill char when len > # digits
X *
X * Returns:	length of string
X *
X * Narrative:	IF fill character is non-blank
X *		    Determine base
X *		        If base is HEX
X *		            add "0x" to begining of string
X *		        IF base is OCTAL
X *		            add "0" to begining of string
X *
X *		While value is greater than zero
X *		    use val % base as index into xlation str to get cur char
X *		    divide val by base
X *
X *		Determine fill-in length
X *
X *		Fill in fill chars
X *
X *		Copy in number
X *		
X *
X * Mod History:	
X *   90/01/24	cpcahil		Initial revision.
X */
X
X#ifndef lint
Xstatic
Xchar rcs_hdr[] = "$Id: tostring.c,v 1.4 90/05/11 00:13:11 cpcahil Exp $";
X#endif
X
X#define T_LEN 10
X
Xint
Xtostring(buf,val,len,base,fill)
X	int	  base;
X	char	* buf;
X	char	  fill;
X	int	  len;
X	int	  val;
X	
X{
X	char	* bufstart = buf;
X	int	  i = T_LEN;
X	char	* xbuf = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
X	char	  tbuf[T_LEN];
X
X	/*
X	 * if we are filling with non-blanks, make sure the
X	 * proper start string is added
X	 */
X	if( fill != ' ' )
X	{
X		switch(base)
X		{
X			case B_HEX:
X				*(buf++) = '0';
X				*(buf++) = 'x';
X				if( len )
X				{
X					len -= 2;
X				}
X				break;
X			case B_OCTAL:
X				*(buf++) = fill;
X				if( len )
X				{
X					len--;
X				}
X				break;
X			default:
X				break;
X		}
X	}
X
X	while( val > 0 )
X	{
X		tbuf[--i] = xbuf[val % base];
X		val = val / base;
X	}
X
X	if( len )
X	{
X		len -= (T_LEN - i);
X
X		if( len > 0 )
X		{
X			while(len-- > 0)
X			{
X				*(buf++) = fill;
X			}
X		}
X		else
X		{
X			/* 
X			 * string is too long so we must truncate
X			 * off some characters.  We do this the easiest
X			 * way by just incrementing i.  This means the
X			 * most significant digits are lost.
X			 */
X			while( len++ < 0 )
X			{
X				i++;
X			}
X		}
X	}
X
X	while( i < T_LEN )
X	{
X		*(buf++) = tbuf[i++];
X	}
X
X	return( (int) (buf - bufstart) );
X
X} /* tostring(... */
X
X/*
X * $Log:	tostring.c,v $
X * Revision 1.4  90/05/11  00:13:11  cpcahil
X * added copyright statment
X * 
X * Revision 1.3  90/02/24  21:50:33  cpcahil
X * lots of lint fixes
X * 
X * Revision 1.2  90/02/24  17:29:42  cpcahil
X * changed $Header to $Id so full path wouldnt be included as part of rcs 
X * id string
X * 
X * Revision 1.1  90/02/22  23:17:44  cpcahil
X * Initial revision
X * 
X */
SHAR_EOF
$TOUCH -am 0511001490 tostring.c &&
chmod 0444 tostring.c ||
echo "restore of tostring.c failed"
set `wc -c tostring.c`;Wc_c=$1
if test "$Wc_c" != "2716"; then
	echo original size 2716, current size $Wc_c
fi
exit 0
-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

carroll@m.cs.uiuc.edu (07/01/90)

I got a number of requests for this, so here it is:
(This code is taken out of Epoch, where it works just fine).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
char *
UnsignedLongToString(n,base)
     unsigned long n;
     unsigned int base;
{
  char *digit = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  static char LongToStringBuffer[34];	/* 32+nul+negative sign */
  char *s = LongToStringBuffer + 33; /* at most 33 characters in binary */

  *s = 0;			/* terminate */
  while (n)			/* something there */
    {
    *--s = digit[n % base];		/* store bottom digit */
    n /= base;			/* shift right */
    }
  if (*s == 0) *--s = '0';		/* in case nothing was put in string */
  return s;
}

char *
LongToString(n,base)
     long n;
     int base;
{
  char *s;

  if (n < 0)
    {
      s = UnsignedLongToString((unsigned long) -n, base);
      *--s = '-';
    }
  else s = UnsignedLongToString((unsigned long) n, base);
  return s;
}
/* ------------------------------------------------------------------------ */
main()
{
  printf("%s\n",LongToString(-1234567,10));
  printf("%s\n",UnsignedLongToString(7654321,10));
  printf("%s\n",LongToString(0x12345,16));
}

Alan M. Carroll                Barbara/Marilyn in '92 :
carroll@cs.uiuc.edu            + This time, why not choose the better halves?
Epoch Development Team         
CS Grad / U of Ill @ Urbana    ...{ucbvax,pur-ee,convex}!cs.uiuc.edu!carroll

carroll@m.cs.uiuc.edu (07/01/90)

/* Written 11:15 am  Jun 29, 1990 by brad@SSD.CSD.HARRIS.COM in m.cs.uiuc.edu:comp.lang.c */
>In article <22888@boulder.Colorado.EDU> baileyc@tramp.Colorado.EDU (BAILEY CHRISTOPHER R) writes:
>
>>Help, I need an itoa() function for use with my Sun compiler.
>
>Perhaps I missed something but ...  Is there some reason why:
>
>  int i = 10; char a[3];
>  sprintf( a, "%d", i );
>
>is unnacceptable for your purposes?
I can't speak for Mr. Bailey, but I have such code because sprintf() was
inadequate. In Epoch there is a need to convert longs to several different
bases (i.e., 2,8,10,16) in a general way. Rolling your own itoa() is (IMHO)
actually easier than kludging with special cases and sprintf(), not to
mention being more efficient (sprintf() does so ugly things in many cases
to work). I don't understand why this _isn't_ in the standard library, since
the inverse is available. One thing that's pissed me off in the past is that
I can read binary easily (using atol()), but I can't write it with equal
facility.

henry@zoo.toronto.edu (Henry Spencer) (07/01/90)

In article <1990Jun30.071229.23965@agate.berkeley.edu> dankg@monsoon.Berkeley.EDU (Dan KoGai) writes:
>	Maybe.  But I was wondering why there's no itoa() in most C libraries:
>atoi() exists and often used in scanf().  Why do we let [sf]printf() do
>all conversion instead of calling itoa...

Such things existed once.  They fell pretty much out of use once sprintf
and friends became available, since there wasn't a spectacular difference
in efficiency and the more general tool was easier to remember (because it
got so much more use).
-- 
"Either NFS must be scrapped or NFS    | Henry Spencer at U of Toronto Zoology
must be changed."  -John K. Ousterhout |  henry@zoo.toronto.edu   utzoo!henry

bakke@plains.UUCP (Jeffrey P. Bakke) (07/01/90)

In article <4700055@m.cs.uiuc.edu> carroll@m.cs.uiuc.edu writes:
> 
> I got a number of requests for this, so here it is:
> (This code is taken out of Epoch, where it works just fine).
> .... CODE
> 
> Alan M. Carroll                Barbara/Marilyn in '92 :
> carroll@cs.uiuc.edu            + This time, why not choose the better halves?
> Epoch Development Team         
> CS Grad / U of Ill @ Urbana    ...{ucbvax,pur-ee,convex}!cs.uiuc.edu!carroll


I'm not sure if I'm jumping in on the middle of a discussion but I happened
to catch this post as I went by.   An alternate to this code is the
code implemented directly in K&R.  If the above code is part of a discussion
of alternate methods of the itoa function than K&Rs, ignore the following
code.


/* --------------------------------------
   Name:      IntString
   Function:  Converts a Long integer value to a string
   Call:      IntString(n,str);
   Returns:   void
   -------------------------------------- */
void IntString(n,str)
long n;
char *str;
{
  int i=0;
  long int sign;

  if ((sign = n) < 0) n =- n;
  do
    str[i++] = (n % 10) + '0';
  while (( n /= 10) > 0);
  if (sign < 0)
    str[i++] = '-';
  str[i] = '\0';
  Reverse(str);
}


/* --------------------------------------
   Name:      Reverse
   Function:  Reverse string
   Call:      Reverse(str);
   Returns:   void
   -------------------------------------- */
void Reverse(str)
char *str;
{
  int i,j;
  char c;

  for (i=0,j=(strlen(str)-1);i<j;i++,j--){
    c = str[i];
    str[i] = str[j];
    str[j] = c;
  }
}


Jeffrey P. Bakke     | Internet: bakke@plains.NoDak.edu | "Life... don't talk
2550 15th Str S #23B | UUCP    : ...!uunet!plains!bakke |  to me about life..."
Fargo, ND  58105     | BITNET  : bakke@plains.bitnet    |    - Marvin the PA

toma@ozdaltx.UUCP (Tom Armistead) (07/03/90)

In article <22888@boulder.Colorado.EDU>, baileyc@boulder.Colorado.EDU (BAILEY CHRISTOPHER R) writes:
> 
> Help, I need an itoa() function for use with my Sun compiler.  It seems
> as if only PC versions of C have itoa functions.  So, source code for
> an integer to string function would be very helpful.  Thanks!

I can't wait to here the flames about this one...

If you are in a hurry or not real concerned about performance, you can
use sprinf() to replace the itoa() function.

    i.e.

    char buf[10];
    int number=100;

    sprintf( buf, "%d", number );

Now buf will contain the ASCII representation of number.

Tom
-- 
-------------------------------
{uunet,smu}!sulaco!ozdaltx!toma         (Tom Armistead @ Garland, Texas)
{uunet,smu}!sulaco!ozdaltx!swsrv1!toma 

loren@tristan.llnl.gov (Loren Petrich) (07/14/90)

In article <22888@boulder.Colorado.EDU> baileyc@tramp.Colorado.EDU (BAILEY CHRISTOPHER R) writes:
>
>Help, I need an itoa() function for use with my Sun compiler.  It seems
>as if only PC versions of C have itoa functions.  So, source code for
>an integer to string function would be very helpful.  Thanks!

	Use the "sprintf" function -- it is like "printf" or
"fprintf", but it takes the output string as an argument. Check your
system's manual pages for more details.

						        ^    
Loren Petrich, the Master Blaster		     \  ^  /
	loren@sunlight.llnl.gov			      \ ^ /
One may need to route through any of:		       \^/
						<<<<<<<<+>>>>>>>>
	lll-lcc.llnl.gov			       /v\
	lll-crg.llnl.gov			      / v \
	star.stanford.edu			     /  v  \
						        v    
For example, use:
loren%sunlight.llnl.gov@star.stanford.edu

My sister is a Communist for Reagan

dankg@headcrash.Berkeley.EDU (Dan KoGai) (07/14/90)

In article <64736@lll-winken.LLNL.GOV>,
loren@tristan.UUCP (Loren Petrich) said:
>In article <22888@boulder.Colorado.EDU> baileyc@tramp.Colorado.EDU (BAILEY CHRISTOPHER R) writes:
>>
>>Help, I need an itoa() function for use with my Sun compiler.  It seems
>>as if only PC versions of C have itoa functions.  So, source code for
>>an integer to string function would be very helpful.  Thanks!
>
>	Use the "sprintf" function -- it is like "printf" or
>"fprintf", but it takes the output string as an argument. Check your
>system's manual pages for more details.

	Well, I could speculate several reasons that itoa() is worth
coded...

1.	It's mucsimpler and faster:  itoa(buffer, 123) is niftier
	than sprintf(buffer, "%d", 123)
2.	Return value.  sprintf() returns number of chars written according
	to ANSI specs.  And itoa() returns ptr to the string written
	for most of the implementations posted here, including my own
	version (or itoa() might need only one argument if it has
	static buffer inside of it).

	It would be definitely useful if you want to code (fs)printf()
by yourself.  Wierd thing is that atoi() exists for scanf but itoa()
doesn't seem to exist in C standard library.  Does anyone know why?

----------------
____  __  __    + Dan The "I want official version of itoa(), too!" Man
    ||__||__|   + E-mail:       dankg@ocf.berkeley.edu
____| ______    + Voice:        +1 415-549-6111
|     |__|__|   + USnail:       1730 Laloma Berkeley, CA 94709 U.S.A
|___  |__|__|   + Oxymora:    Usable MS-DOS, Multitasking Mac, Secure Unix,
    |____|____  + 		rec.humor posters without sense of humor,
  \_|    |      +		Christian Science, and English grammer

henry@zoo.toronto.edu (Henry Spencer) (07/15/90)

In article <1990Jul14.084734.29071@agate.berkeley.edu> dankg@headcrash.Berkeley.EDU (Dan KoGai) writes:
>... Wierd thing is that atoi() exists for scanf but itoa()
>doesn't seem to exist in C standard library.  Does anyone know why?

The scanf family is a bit of a botch that doesn't really give you enough
control to cope with real-life input.  The printf family does not have
this weakness, so there is much less need to bypass it.

There used to be an itoa() function, long ago, if my memory isn't failing
me.  Once sprintf arrived, nobody ever bothered to use itoa().  It was
seldom performance-critical, and everyone already knew how to use the
printf family.
-- 
NFS:  all the nice semantics of MSDOS, | Henry Spencer at U of Toronto Zoology
and its performance and security too.  |  henry@zoo.toronto.edu   utzoo!henry