473,769 Members | 5,757 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

itoa in pure C

I wrote a version of itoa yesterday.

Features:
1 No implementation defined arithmetic. All of the division
and modulus division is done on positive values only.
2 No object is assumed capable of representing the
magnitude of INT_MIN.
3 The string is constructed in place without reversal.
4 No features from standard library are used.

sput_i writes the decimal representation of a nonnegative int value
argument to an array of char.
sput_ip1 writes the representation of one greater than the
argument value, for any nonnegative int value argument, to an
array of char.

/* BEGIN itoa.c */

void itoa(int, char *);
char *sput_i(int, char *);
char *sput_ip1(int, char *);

void itoa(int integer, char *string)
{
if (0 > integer) {
++integer;
*string++ = '-';
*sput_ip1(-integer, string) = '\0';
} else {
*sput_i(integer , string) = '\0';
}
}

char *sput_i(int integer, char *string)
{
if (integer / 10 != 0) {
string = sput_i(integer / 10, string);
}
*string++ = (char)('0' + integer % 10);
return string;
}

char *sput_ip1(int integer, char *string)
{
int digit;

digit = (integer % 10 + 1) % 10;
if (integer / 10 != 0) {
string = (digit == 0 ? sput_ip1 : sput_i)(integer / 10, string);
*string++ = (char)('0' + digit);
} else {
if (digit == 0) {
*string++ = '1';
}
*string++ = (char)('0' + digit);
}
return string;
}

/* END itoa.c */

--
pete
Nov 14 '05
29 20909
pete wrote:
Dan Pop wrote:
.... snip ...
just treat INT_MIN as a special case: set a flag
and handle it as INT_MIN + 1. If the flag is set, increment the least
significant digit of the result.
No need to worry about carry propagation
because no power of two has 0 as its least significant digit.
void ito_a(int i, char *s)
{
char c, *p;
int int_min = 0;

p = s;
if (0 > i) {
*p++ = '-';
++s;
if (i == INT_MIN) {
int_min = 1;
i = INT_MAX;
} else {
i = -i;
}
}


Try a simpler method (untested in C).

if (0 > i) sign = '-';
else {
i = -i;
sign = '\0';
}
p = s;
/* Now sign has been recorded, and i is negative */
/* Only the first digit is critical, after that the range */
/* of i will easily be within that of a positive int */
do {
c = i % 10; /* this step requires careful std reading */
/* about modulus of -ve numbers. Check it */
*p++ = c + '0'; /* which may require adding 10 here */
i /= 10;
} while (i);
if (*p++ = sign) *p++ = '\0';
--p;
/* Now reverse the string s through p in place */
while (s < --p) {
c = *s;
*s++ = *p;
*p = c;
}

There may be an evil gotcha in the above, because something about
modulo changed between C89 and C99.

do {
*p++ = (char)('0' + i % 10);
i /= 10;
} while (i);
if (int_min) {
++*s;
}
for (*p = '\0'; --p > s; ++s) {
c = *s;
*s = *p;
*p = c;
}
}

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

Nov 14 '05 #21
pete wrote:

Peter Nilsson wrote:

What are your thoughts on...?

char *itoa(int i, char *s)
{
char *p = s;
char *q = s;

if (i >= 0)
{
do
{
*q++ = '0' + (i % 10);
}
while (i /= 10);
}
else if (-1 % 2 < 0)
{
This is the part of the code that runs on my machine.
I believe that here, (-1 % 10 == -1) and (-1 / 10 == 0) are true.
*q++ = '-';
p++;

do
{
*q++ = '0' - i % 10;
}
while (i /= 10);
I'm thinking about converting -1.
'0' - i % 10 is '1', so that looks good.
}
else
{
This code is unreachable on my machine,
so all I can do is to think about it.
*q++ = '-';
p++;

do
{
int d = i % 10;
i = i / 10;
if (d) { i++; d = 10 - d; }
*q++ = '0' + d;
}
I'm thinking about converting -1 again.
I think that in the above loop,
(-1 % 10 == 1) and (-1 / 10 == -2) are true.
I see why i++ is there, but I think that the value of
int d = i % 10;
is correct and should not be altered as in d = 10 - d;
while (i);
}

for (*q = 0; p < --q; p++)
{
char c = *p;
*p = *q;
*q = c;
}

return s;
}


At first glance, it seems to be efficient and thorough.
I'll take a closer look at it.


--
pete
Nov 14 '05 #22
pete wrote:

pete wrote:

Peter Nilsson wrote:
What are your thoughts on...?

char *itoa(int i, char *s)
{
char *p = s;
char *q = s;

if (i >= 0)
{
do
{
*q++ = '0' + (i % 10);
}
while (i /= 10);
}
else if (-1 % 2 < 0)
{
This is the part of the code that runs on my machine.
I believe that here, (-1 % 10 == -1) and (-1 / 10 == 0) are true.


/* (a/b)*b + a%b shall equal a */

(-1 / 10 == 0, 0) * 10 + (-1 % 10 == -1, -1) == -1

*q++ = '-';
p++;

do
{
*q++ = '0' - i % 10;
}
while (i /= 10);
I'm thinking about converting -1.
'0' - i % 10 is '1', so that looks good.
}
else
{
This code is unreachable on my machine,
so all I can do is to think about it.
*q++ = '-';
p++;

do
{
int d = i % 10;
i = i / 10;
if (d) { i++; d = 10 - d; }
*q++ = '0' + d;
}
I'm thinking about converting -1 again.
I think that in the above loop,
(-1 % 10 == 1) and (-1 / 10 == -2) are true.


I can't make , "(a/b)*b + a%b shall equal a "
hold for those numbers, so I think I'm wrong.
I see why i++ is there, but I think that the value of
int d = i % 10;
is correct and should not be altered as in d = 10 - d;


Is this what you're using ?
(-1 / 10 == -1) (-1 % 10 == 9)
That would explain
d = 10 - d;
but not
i++;

while (i);
}

for (*q = 0; p < --q; p++)
{
char c = *p;
*p = *q;
*q = c;
}

return s;
}


At first glance, it seems to be efficient and thorough.
I'll take a closer look at it.


--
pete
Nov 14 '05 #23
pete wrote:

pete wrote:

pete wrote:

Peter Nilsson wrote:

> What are your thoughts on...?
>
> char *itoa(int i, char *s)
> {
> char *p = s;
> char *q = s;
>
> if (i >= 0)
> {
> do
> {
> *q++ = '0' + (i % 10);
> }
> while (i /= 10);
> }
> else if (-1 % 2 < 0)
> {


This is the part of the code that runs on my machine.
I believe that here, (-1 % 10 == -1) and (-1 / 10 == 0) are true.


/* (a/b)*b + a%b shall equal a */

(-1 / 10 == 0, 0) * 10 + (-1 % 10 == -1, -1) == -1
> *q++ = '-';
> p++;
>
> do
> {
> *q++ = '0' - i % 10;
> }
> while (i /= 10);


I'm thinking about converting -1.
'0' - i % 10 is '1', so that looks good.
> }
> else
> {


This code is unreachable on my machine,
so all I can do is to think about it.
> *q++ = '-';
> p++;
>
> do
> {
> int d = i % 10;
> i = i / 10;
> if (d) { i++; d = 10 - d; }
> *q++ = '0' + d;
> }


I'm thinking about converting -1 again.
I think that in the above loop,
(-1 % 10 == 1) and (-1 / 10 == -2) are true.


I can't make , "(a/b)*b + a%b shall equal a "
hold for those numbers, so I think I'm wrong.
I see why i++ is there, but I think that the value of
int d = i % 10;
is correct and should not be altered as in d = 10 - d;


Is this what you're using ?
(-1 / 10 == -1) (-1 % 10 == 9)
That would explain
d = 10 - d;
but not
i++;


Actually it does explain i++;

--
pete
Nov 14 '05 #24
"pete" <pf*****@mindsp ring.com> wrote in message
news:40******** ***@mindspring. com...
pete wrote:
pete wrote: ....
I'm thinking about converting -1 again.
I think that in the above loop,
(-1 % 10 == 1) and (-1 / 10 == -2) are true.


I can't make , "(a/b)*b + a%b shall equal a "
hold for those numbers, so I think I'm wrong.
-1/10 => -0.1, so the integer division can be 0 or -1.
I see why i++ is there, but I think that the value of
int d = i % 10;
is correct and should not be altered as in d = 10 - d;


Is this what you're using ?
(-1 / 10 == -1) (-1 % 10 == 9)
Yes.
That would explain
d = 10 - d;
but not
i++;


Actually it does explain i++;


C89 supports no less than 8 different forms of integer division[*]. But I've
only ever seen two: rounding towards zero, and the mathematical non-negative
remainder version.

You can actually test all of the different versions, simply by adjusting the
results of the existing division. [That's how I tested my code; I replaced
the % and / calculations with some function macros.]
[*] there are three possible ways for at least one of two operands to be
negative, and there are two possible division results for each case.

--
Peter
Nov 14 '05 #25
Peter Nilsson wrote:

"pete" <pf*****@mindsp ring.com> wrote in message
news:40******** ***@mindspring. com...
pete wrote:
pete wrote: ... > I'm thinking about converting -1 again.
> I think that in the above loop,
> (-1 % 10 == 1) and (-1 / 10 == -2) are true.

I can't make , "(a/b)*b + a%b shall equal a "
hold for those numbers, so I think I'm wrong.
-1/10 => -0.1, so the integer division can be 0 or -1.
I see why i++ is there, but I think that the value of
> int d = i % 10;
> is correct and should not be altered as in d = 10 - d;

Is this what you're using ?
(-1 / 10 == -1) (-1 % 10 == 9)
Yes.
That would explain
d = 10 - d;
but not
i++;


Actually it does explain i++;


C89 supports no less than 8 different forms of integer division[*].
But I've only ever seen two: rounding towards zero, and the
mathematical non-negative remainder version.

You can actually test all of the different versions,
simply by adjusting the
results of the existing division.
[That's how I tested my code; I replaced
the % and / calculations with some function macros.]

[*] there are three possible ways for at least one of two operands
to be negative,
and there are two possible division results for each case.


You get my vote for
"most efficient library independant itoa alogorithm".

--
pete
Nov 14 '05 #26
On Thu, 29 Jan 2004 19:13:19 -0500 (EST), "Arthur J. O'Dwyer"
<aj*@nospam.and rew.cmu.edu> wrote:

On Thu, 29 Jan 2004, Larry Doolittle wrote:

[pete wrote:]
Can't do it if UINT_MAX == 65535, and INT_MIN == -65536.
<snip> #if -(INT_MIN)>UINT_ MAX


Huh? On a "normal" two's-complement machine, this would produce
undefined behavior when you tried to negate INT_MIN. "Fixing" the
code to read

#if (0u - INT_MIN) > UINT_MAX

just makes it sillier: the left-hand side evaluates to some unsigned
int, which by definition cannot be greater than UINT_MAX. <snip>


Not by definition; preprocessor arithmetic is done in u/long in C89,
and u/intmax_t in C99. But it is still *possible* that the largest
unsigned type cannot handle the full range of signed INT etc., so on
an absolute-maximum-portability quest you still have the problem.

- David.Thompson1 at worldnet.att.ne t
Nov 14 '05 #27
In <vc************ *************** *****@4ax.com> Dave Thompson <da************ *@worldnet.att. net> writes:
Not by definition; preprocessor arithmetic is done in u/long in C89,
and u/intmax_t in C99. But it is still *possible* that the largest
unsigned type cannot handle the full range of signed INT etc.,

^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
It's not only possible, it's a *certitude*.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #28
On 6 Feb 2004 19:29:42 GMT, Da*****@cern.ch (Dan Pop) wrote:
In <vc************ *************** *****@4ax.com> Dave Thompson <da************ *@worldnet.att. net> writes:
Not by definition; preprocessor arithmetic is done in u/long in C89,
and u/intmax_t in C99. But it is still *possible* that the largest
unsigned type cannot handle the full range of signed INT etc.,

^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
It's not only possible, it's a *certitude*.

Sorry, sloppy wording. I meant can't handle the magnitudes of the full
negative range, and in particular of the 2sC most negative value,
which was the issue upthread.

Nit: a thing that is necessarily or always so, like what you marked,
is a "certainty" . "Certitude" is (and "certainty" is *also*) the
property of a person being confident of something.

- David.Thompson1 at worldnet.att.ne t
Nov 14 '05 #29
In <b7************ *************** *****@4ax.com> Dave Thompson <da************ *@worldnet.att. net> writes:
On 6 Feb 2004 19:29:42 GMT, Da*****@cern.ch (Dan Pop) wrote:
In <vc************ *************** *****@4ax.com> Dave Thompson <da************ *@worldnet.att. net> writes:
>Not by definition; preprocessor arithmetic is done in u/long in C89,
>and u/intmax_t in C99. But it is still *possible* that the largest
>unsigned type cannot handle the full range of signed INT etc., ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
It's not only possible, it's a *certitude*.

Sorry, sloppy wording. I meant can't handle the magnitudes of the full
negative range, and in particular of the 2sC most negative value,
which was the issue upthread.


Unsigned types cannot handle any single bit of the negative range, by
definition.
Nit: a thing that is necessarily or always so, like what you marked,
is a "certainty" . "Certitude" is (and "certainty" is *also*) the
property of a person being confident of something.


Thanks,
Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #30

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
3707
by: John Lenton | last post by:
Is there any reason python's printf-style formatting is missing the (C99) '%a' specifier? I'm sorry if this has been asked and answered before; I can't find it on google ('%a' is a very awkward thing to look for): -- John Lenton (john@grulic.org.ar) -- Random fortune: Los cementerios están llenos de valientes.
7
12856
by: news.hku.hk | last post by:
Excuse me, i write the following function to add comma for integers but the unix server said: In function `class string comma(int)': implicit declaration of function `int itoa(...)' ________________________________ string comma(int a){ char to_string; string s_a = itoa(a, to_string, 10);
4
14339
by: Moritz Beller | last post by:
Hello! Is there an equivalent to Visual C++'s itoa function in gcc? best regards Moritz Beller -- web http://www.4momo.de mail momo dot beller at t-online dot de gpgkey http://gpg.notlong.com
2
5030
by: Raskolnikow | last post by:
Hi! I have a very simple problem with itoa() or the localtime(...). Sorry, if it is too simple, I don't have a proper example. Please have a look at the comments. struct tm *systime; time_t currentTime; char day; char month;
2
6678
by: Sona | last post by:
Hi, I have a char* that holds an ascii character in its first element (at least I think that's what it holds because when I print it, it prints weird characters). I need to convert this into an integer and so I thought the following might work: char *somevar ... // somevar holds a value in somevar and is null terminated i.e. somevar = '\0'
11
3604
by: rayw | last post by:
I'm pretty new to C, although I did do some years ago now. I've been told that itoa is no longer a standard function, and that the ato... functions - although in the std - are not recommended. So, I was wondering what was wrong with both itoa and atoi etc (and what's replaced them). Many thanks
24
8206
by: Mark | last post by:
hi, all i want is a simple function that takes an int, and returns a char* so i tried char * itoa(int i) { char buff; return _itoa(i,buff,10); }
7
39554
by: silverburgh.meryl | last post by:
Hi, Can you please tell me where I can find itoa()? I try to compile the following example, but I get the following error: .../t.cpp:20:2: warning: no newline at end of file .../t.cpp: In function 'int main()': .../t.cpp:13: error: 'itoa' was not declared in this scope /* itoa example */
0
9583
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9423
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10039
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8869
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7406
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6668
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5297
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3955
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3560
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.