Link to home
Start Free TrialLog in
Avatar of znbg
znbg

asked on

itoa function

I wrote a program in Visual C++ that uses this function to convert an int to a string.  When I moved the code to a UNIX box and compiled there, it failed.  I get the messge: The function "itoa" must have a prototype.

Can anyone tell me why this is happening and how I can get the function to run correctly.

Note, I also use atoi and it didn't say anything about that.
Avatar of jkr
jkr
Flag of Germany image

'itoa()' should be available from 'stdlib.h'. If you cannot find it there, you can easily 'emulate' that behaviour by writing your own:

/* helper routine that does the main job. */

static void __cdecl xtoa (
        unsigned long val,
        char *buf,
        unsigned radix,
        int is_neg
        )
{
        char *p;                /* pointer to traverse string */
        char *firstdig;         /* pointer to first digit */
        char temp;              /* temp char */
        unsigned digval;        /* value of digit */

        p = buf;

        if (is_neg) {
            /* negative, so output '-' and negate */
            *p++ = '-';
            val = (unsigned long)(-(long)val);
        }

        firstdig = p;           /* save pointer to first digit */

        do {
            digval = (unsigned) (val % radix);
            val /= radix;       /* get next digit */

            /* convert to ascii and store */
            if (digval > 9)
                *p++ = (char) (digval - 10 + 'a');  /* a letter */
            else
                *p++ = (char) (digval + '0');       /* a digit */
        } while (val > 0);

        /* We now have the digit of the number in the buffer, but in reverse
           order.  Thus we reverse them now. */

        *p-- = '\0';            /* terminate string; p points to last digit */

        do {
            temp = *p;
            *p = *firstdig;
            *firstdig = temp;   /* swap *p and *firstdig */
            --p;
            ++firstdig;         /* advance to next two digits */
        } while (firstdig < p); /* repeat until halfway */
}

/* Actual functions just call conversion helper with neg flag set correctly,
   and return pointer to buffer. */

char * __cdecl _itoa (
        int val,
        char *buf,
        int radix
        )
{
        if (radix == 10 && val < 0)
            xtoa((unsigned long)val, buf, radix, 1);
        else
            xtoa((unsigned long)(unsigned int)val, buf, radix, 0);
        return buf;
}
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
itoa is not part of the ANSI C++ standards.
Some compilers have itoa or _itoa as part of the stdlib.h, but not all compilers support this non-standard function.

I suggest you use one of jkr's above functions to emulate the function.
You can also try the following itoa emulated function:

char* itoa(int nValue)
{
 static char buffer[64];
 sprintf(buffer, "%i", nValue);
 return buffer;
}
Avatar of nietod
nietod

A simpler substitute for itoa() or _itoa() or what ever is

string IntToASCI(int i)
{
   stringstream S;

   S << i;
  return S.str();
}

(This assumes you want base 10.  other bases can be obtained, if necessary).  Tthis is a lot more convenient than itoa() since you do not have to provide a storage space for the resulting string.  it returns a strign object that is automatically sized to the size needed to store the converted value.

>>A simpler substitute for itoa() or _itoa() or what ever
>>is

FYI,
This would be a better method if your main concern is the small storage space required by previous posted method.

However, if you're more concern about having a function that works more like the char* itoa() function, nietod's method would not work.

string IntToASCI(int i)
This method would return a string type that would fail in code that requires a pointer to a string.
Example:

int x = 10;
printf("%s",IntToASCI(x));

You can still get nietod's method to work, buy modifying the code to the following:

int x = 10;
printf("%s",IntToASCI(x).c_str());

This would make your code less portable, and it would mean you would have to modify the code where ever this problem presents itself.
If you make the above modifications, the code would not compile when porting it back to it's original platform/compiler.

I recomend using using the function I posted because it will work like the original itoa function.
The small 64-bytes of storage space required for this function is really small and insignificant in MOST target applications.
"A simpler substitute for itoa() or _itoa() or what ever is
string IntToASCI(int i)"

Or even:

template<class T>
T StringToType(const string& source)
{
    istringstream iss(source);
    T ret;
    iss >> ret;
    return ret;
};

or

template<class T>
T& StringToType(const string& source, T& target)
{
    istringstream iss(source);
    iss >> target;
    return target;
};

and

template<class T>
string ToString(const T& source)
{
    ostringstream oss;
    oss << source;
    return oss.str();
};

===============================================
use them like so:

string s = ToString(123);
int i = StringToType<int>(s);
or
StringToType(s, i);
>> This would make your code less portable, and it would
>> mean you would have to modify the code where ever
>> this problem presents itself.
In what way is my suggestion non portable???  It will port to ANY conforming C++ implimentaion.  itoa() and _itoa() certainly won't.

And clearly its not exactlyt he same as itoa((),  it takes different parmeters and returns a different data type.  I pointed it out.

AssafLavie, some very slick templates.  simeple and very effective.
>>In what way is my suggestion non portable???  It will
>>port to ANY conforming C++ implimentaion.  itoa()
>>and _itoa() certainly won't.
The code modifications need to use your function is not portable to compilers that include itoa() function with a return type of char*

>>I pointed it out.
Yes, but you did not point out what kind of problems this can cause.
>> The code modifications need to use your function
>> is not portable to compilers that include itoa()
>> function with a return type of char*
Yes it is!   it is portable to ALL compilrs.  there's nothing that is non-portable about it.

>> you did not point out what kind of
>> problems this can cause.
its hardly a problem.  The change is trivial and missed changes will always be caught by the compiler.  The lack of support for other bases is a bigger problem.  That can be handled too however.
Avatar of znbg

ASKER

That's all I needed!  Thanks!!!!
>>The change is trivial and missed changes will always be
>>caught by the compiler.
That's wrong.  
Example:
int x = 10;
printf("%s",IntToASCI(x));

The above code does compile, but on run-time, it does not produce the desired results.
The compiler does not always detect bad coding nor bad functions.

It's poor practice to depend on a compiler to catch a poorly written substitute function.
>> The above code does compile, but on run-time,
>> it does not produce the desired results.
No kidding!  what does that have to do with portability?

Aren't file stream objects portable?  Well

>> printf("%s",fstream());

compiles and works wrong too!

This has nothing to do with portability.  

Obviously if you are going to use a new function in your program, the code is goignt ob e changed.  Its is impossible to keep things exactly the same durign a change.  That is inherient int he definiton of change.   In additioon you can make a change--a change of any type and make it wrong.  That doesn't maen something is non-portable.  non-portable has a very precise meaining.  It means that a non-illformed program cannot be made to compile or to work correctly on all platforms.  

>> It's poor practice to depend on a
>> compiler to catch a poorly written
>> substitute function.
There is no gautrantee against people being moronic.  If someone is stupid enough to write code like that they are going to have problems.  At the very least they shouldn't be using pritnf() for reasons I've tried to convince you of, and you never accepted, yet here you showing how bad it is

By the same token you could argue that your code is "non-portable" because

code like

char s1[10];
char s2[10];
_itoa(s1,123);
_itoa(s2,456);

when converted produces

char *s1 = itoa(123);
char *s2 = itoa(345);

because now s1 and s2 both store "345".   That is a problem, it no longer produces the right results  Is that a sign that the code is not portable?  No!  its a sign that someone changed the code to use a new function and didn't do it correctly.  (Its also a sign of a pretty major weakness in the function, one that is nearly impossible to get around under soem circumstances, like multi-threading.)  
>>No kidding!  what does that have to do with portability?
No kidding!  It's not suppose to have anything to do with portability.
I'm addressing the statement you made that said "missed changes will always be caught by the compiler"

So I don't know why you're trying to bring portability issue into the picture.

The fact is that you're suggesting to depend on a compiler to catch a poorly written substitute function.

You're above comment has nothing to do with your previous bad advise.

>>If someone is stupid enough to write code like
>>that they are going to have problems.  
You're the one who's always posting some of the wall poorly written code as an example on how a method can fail to work.
It's seems alright when you right these moronic examples, but not alright when someone else does.
>> No kidding!  It's not suppose to have
>> anything to do with portability.

So when you said "This would make your code less portable."  That is your way of saying that it has nothig to do with portability?

>> I don't know why you're trying to bring
>> portability issue into the picture.
Because you said my code was not portable.  I know it is portable. Its obviously portable.  Why are you bring it up?

IS THE CODE PORTABLE?

>> You're the one who's always posting
>> some of the wall poorly written code
>> as an example on how a method
>> can fail to work.
but with reason.  There has to be some expecaction of reasonable resposibility on the programmers part.  Otherwise no techniqyue is safe.  The return value of ANY function can cause printf() to fail.  Does that mean that any technique that would call a fucntion is therefore unsafe?  No, it means that printf() is unsafe.  

>>So when you said "This would make your code less
>>portable."  That is your way of saying that it has
>>nothig to do with portability?

Is this your way of trying to avoid the subject?
In my last two comments, I made no attempt to address portability.
My last two comments are only addressing your following statement:
"missed changes will always be caught by the compiler"

If you want to talk about something else, that's find with me, but don't make my last two comments about portability, when it has nothing to do with it.

If you're not going to address the fact that you gave bad advise with "missed changes will always be caught by the compiler", then you need to stop referrencing my last comments because that's the only thing I'm addressing there.
>> Is this your way of trying to avoid the subject?
What subject?  you claimed my code is not protable.  Why is it not protable?  Or are you now stating that it is portable?  WHICH IS IT?

>> "missed changes will always be
>> caught by the compiler"
Tht is not a missed change.  The programmer had to go an make the change there.  They changed the code to work in an unsafe manner.  

Virtually all ocde can be made unsafe.  You can't criticize something for being unsafe if you have to work hard to make it so!   Your code can be made unsafe.  The original atof() can be made unsafe  (pass a NULL pointer).  You do everything within reason to make code safe, but there are limitations to what can be done.  

In addition you are presenting this as if it is somehow related to my code.  its not.  The problem is with printf(0, not my code.  Any code that uses printf is inheriently risky.  

>> If you want to talk about something
>> else, that's find with me
You started of talking about portability?  Are you now admiting the code is portable?   Come on!

>> "missed changes will always be
>> caught by the compiler",
Who do you think changed the code so it no longer uses atof()?   Someone had to do that.  Adn at that time they had to examine the code and make changes to make the code work correctly.  That is part of making a change.  

>> stop referrencing my last comments
>> because that's the nly

AXTER'S CODE IS FULL OF BUGS AND WILL CRASH IF YOU ATTEMPT TO USE IT.

Your code will require changes whenever it is called, just like mone.

Please confine your responses only to the last thing I said.  (Yeah right!)
              thing I'm addressing there.
>>Virtually all ocde can be made unsafe.  You can't
>>criticize something for being unsafe if you have to
>>work hard to make it so!  
Wow, that sounds very familiar.  Isn't that the same thing I said when you said crosscasting is unsafe?

Since you don't want to talk about your screw-up, I see no reason why I should have to talk to you about what you want to talk about.
Are you just trying to cause trouble.  Or do you really nut understand?  I can't believe anyone couldn't understand?  

You do everythign reasonable to avoid problems.  You don't do things that are unreasonable.  You don't do nothing.  You do everythign that is reasonable.  

Here you essentially suggestiong that ALL procedure calls be avoided because printf() is unsafe.   That is not reasonable.  But this is what you are suggestiong.  (Avoidning printf() is reasoanble however, why you don't see that is beyond me.)  Actually i know that you are only suggesting that my function call be avoided, but that is stupid, the logic applies to all function calls, and also all expresions too.  You need to avoid those too.  That is not reasonable.  It causes far mroe problems than it avoids.  But what is reasonable?  Not using printf() is reasonable.  It avoids this problem and others.  That is a resonable solution.  On the other question  what is resonable?  Not using dynamic_cast is not resonable.  its a powerful tool and of great help when used correctly.   using dynamic cast indescrimiantely is not reasoanble.  its ganderios when used inappropriately.  it can lead to cude that is unsefe under modications. (modificatiosn that occur in other parts of the code.)  So that is not reasoanble   But usign it in the three methods I discribed that is reasoanble.  You have all the power fo the dymaic_)cast that way.  Yet you have no risk of unexpected behavior.


And what about the portability of my code?  Why is it not portable?  Its not protable because you said it is not portable and just don't want to change your mind about that/  Or do you have some facts you would like to offer?
nietod,
Again, since you don't want to talk about your screw-up, I see no reason why I should have to talk to you about
what you want to talk about.
What screw up?

You said my code is not portable?  Is my code not portable?
(God.. someone shoot this thread already!)
>>(God.. someone shoot this thread already!)
Unfortunately, we can't remove email notification after answer has been accepted.
What screw up?  You are making accusations again.  Support them or retract them.

Why is the code not portable?  support that or retract that.
nietod,
>>What screw up?  You are making accusations again.  
I've repeated myself three times.  If you don't understand by know, then you will never understand.
I'm not repeating myself again.  It's a waste of time with you.
What are you babbeling about?  Where is this screw up?

Is the reason you won't "repeat yourself" the fact that you are obviously wrong?