Integer to string conversion

P

pradeep

Hello friends:

I know some people here don't like to answer C++ questions, but I
believe this is really about the underlying C code. Anyway I have posted
as well to the other group someone suggested ("comp.lang.c++") just in
case.

I think the problem is that in my C++ class, we were taught to use cin,
cout etc. but now I need to use the primitive C operations printf etc.
and I don't understand exactly how they work.

I'm trying to convert an integer into a string. Here's what I'm trying,
but when I try to output the string returned from the function, I just
get garbage. How should I be using sprintf?

Thanks.



char *App::IntToString(int i) //doesn't really rely on classes
{
char buf[2];
char *out = buf;
sprintf(out, "%d", i);
return out;
}
 
I

Ian Collins

pradeep said:
Hello friends:

I know some people here don't like to answer C++ questions, but I
believe this is really about the underlying C code. Anyway I have posted
as well to the other group someone suggested ("comp.lang.c++") just in
case.

I think the problem is that in my C++ class, we were taught to use cin,
cout etc. but now I need to use the primitive C operations printf etc.
and I don't understand exactly how they work.
Why? If you are writing C++, use C++ idioms.

f'ups set.
 
D

Default User

pradeep said:
I'm trying to convert an integer into a string. Here's what I'm
trying, but when I try to output the string returned from the
function, I just get garbage. How should I be using sprintf?
char *App::IntToString(int i) //doesn't really rely on classes
{
char buf[2];
char *out = buf;
sprintf(out, "%d", i);
return out;
}

Your problem is that you are returning a pointer to local storage. That
is invalid as soon as the function returns. In C, you would either pass
in a pointer to storage, or dynamically allocate some for return.

In C++, you shouldn't do this at all. Ask in comp.lang.c++ for ways to
do it.




Brian
 
P

peter koch

Hello friends:

I know some people here don't like to answer C++ questions, but I
believe this is really about the underlying C code. Anyway I have posted
  as well to the other group someone suggested ("comp.lang.c++") just in
case.
We do like answering C++ questions, so it is more the other way
around: C functions are better asked in comp.lang.c - even if they
also (as in your case) happen to be C++ functions.
I think the problem is that in my C++ class, we were taught to use cin,
cout etc. but now I need to use the primitive C operations printf etc. Why?

and I don't understand exactly how they work. You need to study first!

I'm trying to convert an integer into a string. Here's what I'm trying,
but when I try to output the string returned from the function, I just
get garbage. How should I be using sprintf?

Thanks.

char *App::IntToString(int i) //doesn't really rely on classes
Why a pointer to a character? I'd presume a std::string would be more
appropriate.
{
     char buf[2];
Why only two characters? This definitely is wrong.
     char *out = buf;
     sprintf(out, "%d", i);
Why %d? So far as I remember (I haven't used printf-type formatting
for a very long time), the correct format is %i.
Also I believe there is a snprintf available that gives safer code.
     return out;
Here you return a pointer to a temporary variable. This is never a
good idea.

Finding the answer to the questions above hopefully will help your
progress!

/Peter
 
B

Bartc

pradeep said:
Hello friends:

I know some people here don't like to answer C++ questions, but I believe
this is really about the underlying C code. Anyway I have posted as well
to the other group someone suggested ("comp.lang.c++") just in case.

I think the problem is that in my C++ class, we were taught to use cin,
cout etc. but now I need to use the primitive C operations printf etc. and
I don't understand exactly how they work.

I'm trying to convert an integer into a string. Here's what I'm trying,
but when I try to output the string returned from the function, I just get
garbage. How should I be using sprintf?

Thanks.



char *App::IntToString(int i) //doesn't really rely on classes
{
char buf[2];
char *out = buf;
sprintf(out, "%d", i);
return out;
}

If this was C (you'd have to get rid of that :: for a start):

The buffer of 2 characters is far too small; what if i is <0 or >9? Make it
a much more reasonable width, remembering it needs a zero terminator too.

Also the buf[2] being in automatic storage, will disappear when you return
from the function.

You can try making buf static. And bigger.
 
J

Jim Langston

pradeep said:
Hello friends:

I know some people here don't like to answer C++ questions, but I
believe this is really about the underlying C code. Anyway I have
posted as well to the other group someone suggested
("comp.lang.c++") just in case.

I think the problem is that in my C++ class, we were taught to use
cin, cout etc. but now I need to use the primitive C operations
printf etc. and I don't understand exactly how they work.

I'm trying to convert an integer into a string. Here's what I'm
trying, but when I try to output the string returned from the
function, I just get garbage. How should I be using sprintf?

Thanks.



char *App::IntToString(int i) //doesn't really rely on classes
{
char buf[2];

Not big enough by far and disappears once IntToString finishes.
char *out = buf;

No reason to have to do this.
sprintf(out, "%d", i);

sprintf( buf, "%d", i );
would also work, although there are hte other problems.
return out;

you are returning a pointer to a buffer that goes out of scope when the
function returns.

So, how to fix this? Simplest is to make the buffer static so it doesn't
disappear when the function returns and make it big enough. char buf[2];
is only large enough to hold "0" through "9". An integer can hold quite a
larger value, however. 10 or 11 digits I think.

char *App::IntToString(int i) //doesn't really rely on classes
{
static char buf[12];
sprintf(buf, "%d", i);
return buf;
}

Shoudl fix the immediate errors, but does not fix any design issues. Such
as the fact if you called this twice in a row, both returned char*'s would
point to the same value. I.E.

char* Value1;
char* Value2;

Value1 = IntToString( 10 );
Value2 = IntToString( 11 );

std::cout << Value1 << " " << Value2;

would output 11 11 since the pointers returned by IntToString are identical,
and the static buffer was changed.

It is better to return a std::string. You can do the conversion either as is
and convert to a std::string, or use use std::stringstream. (Untested
code).

std::string App::IntToString( int i )
{
std::stringstream Convert;
Convert << i;
std::string Answer;
Convert >> Answer;

return Convert.string();
}

Personally, I use a template for this.

template<typename T, typename F > T StrmConvert( const F from )
{
std::stringstream temp;
temp << from;
T to = T();
temp >> to;
return to;
}

template<typename F> std::string StrmConvert( const F from )
{
return StrmConvert<std::string>( from );
}

So I can do:

std::string Value = StrmConvert( 10 );

or even:

int Value = StrmConvert<int>( "10" );

Note that my StrmConvert does not have any error checking, any errors would
simply return a default constructed value. I.E. If you tried to convert
"xyz" to an int the result would be 0.
 
P

ppi

char *App::IntToString(int i) //doesn't really rely on classes
{
char buf[2];
char *out = buf;
sprintf(out, "%d", i);
return out;

}

you are using a local char array. When returning from the function, it
has been recycled (memory released) - hence the garbage.
provide the array to store the conversion in the parameters list or
return a c++ string.

-- paulo
 
J

Juha Nieminen

pradeep said:
I think the problem is that in my C++ class, we were taught to use cin,
cout etc. but now I need to use the primitive C operations printf etc.
and I don't understand exactly how they work.

I'm trying to convert an integer into a string.

You don't need printf for that. You can do it like this:

std::eek:stringstream os;
os << i;
std::string theString = os.str();
 
K

Keith Thompson

pradeep said:
I know some people here don't like to answer C++ questions, but I
believe this is really about the underlying C code. Anyway I have
posted as well to the other group someone suggested ("comp.lang.c++")
just in case.

I think the problem is that in my C++ class, we were taught to use
cin, cout etc. but now I need to use the primitive C operations printf
etc. and I don't understand exactly how they work.

I'm trying to convert an integer into a string. Here's what I'm
trying, but when I try to output the string returned from the
function, I just get garbage. How should I be using sprintf? [...]

char *App::IntToString(int i) //doesn't really rely on classes
{
char buf[2];
char *out = buf;
sprintf(out, "%d", i);
return out;
}

You could (and should) have avoided any possible controversy by (a)
dropping the "::" from your function's name, (b) dropping any mention
of C++ and classes, and (c) not cross-posting to comp.lang.c++. You
would then have been asking an appropriate C question in a C newsgroup
(to which I've redirected followups).

As far as C is concerned, the FAQ is at <http://www.c-faq.com/>, and
you've asked question 7.5a. Read the answer there, and follow the
references to other questions. If that doesn't tell you what you need
to know, post a followup to comp.lang.c only.

Or, if you just wanted to use sprintf in C++ code for some reason, you
could have just posted to comp.lang.c++. They'd undoubtedly ask you
why you don't just use the usual C++ idioms -- which is a very good
question, and one you might consider answering in a followup to
comp.lang.c++ only.
 
K

Keith Thompson

peter koch said:
Why %d? So far as I remember (I haven't used printf-type formatting
for a very long time), the correct format is %i.

You misremember. For printf, "%d" and "%i" are equivalent. (It's 'd'
for decimal, 'i' for integer).
Also I believe there is a snprintf available that gives safer code.

Yes, but it's a new feature in C99. It's likely to be available as an
extension in pre-C99 C implementations, or in C++ implementations, but
it's not guaranteed to be there. (But if you're programming in C++
I'm not sure why you'd use either sprintf or snprintf.)
 
P

pradeep

Thanks for all the answers.

I think Jim probably has the best solution but we haven't covered
templates yet and they seem very confusing, the code just blurs in front
of my eyes!

What I'd like is a simpler version of this. Here's an idea I had which I
think is very similar to what Jim tries to do but easier: make a pipe
and then cout>> the integer to the pipe, but then cin<< it back as a
string. Would that work?

There is a pipe command on my computer but it isn't mentioned in the
text book. I don't understand the argument, it's an array of 2 int. I
tried passing NULL but it didn't work.

Thanks.


Jim said:
pradeep said:
Hello friends:

I know some people here don't like to answer C++ questions, but I
believe this is really about the underlying C code. Anyway I have
posted as well to the other group someone suggested
("comp.lang.c++") just in case.

I think the problem is that in my C++ class, we were taught to use
cin, cout etc. but now I need to use the primitive C operations
printf etc. and I don't understand exactly how they work.

I'm trying to convert an integer into a string. Here's what I'm
trying, but when I try to output the string returned from the
function, I just get garbage. How should I be using sprintf?

Thanks.



char *App::IntToString(int i) //doesn't really rely on classes
{
char buf[2];


Not big enough by far and disappears once IntToString finishes.

char *out = buf;


No reason to have to do this.

sprintf(out, "%d", i);


sprintf( buf, "%d", i );
would also work, although there are hte other problems.

return out;


you are returning a pointer to a buffer that goes out of scope when the
function returns.



So, how to fix this? Simplest is to make the buffer static so it doesn't
disappear when the function returns and make it big enough. char buf[2];
is only large enough to hold "0" through "9". An integer can hold quite a
larger value, however. 10 or 11 digits I think.

char *App::IntToString(int i) //doesn't really rely on classes
{
static char buf[12];
sprintf(buf, "%d", i);
return buf;
}

Shoudl fix the immediate errors, but does not fix any design issues. Such
as the fact if you called this twice in a row, both returned char*'s would
point to the same value. I.E.

char* Value1;
char* Value2;

Value1 = IntToString( 10 );
Value2 = IntToString( 11 );

std::cout << Value1 << " " << Value2;

would output 11 11 since the pointers returned by IntToString are identical,
and the static buffer was changed.

It is better to return a std::string. You can do the conversion either as is
and convert to a std::string, or use use std::stringstream. (Untested
code).

std::string App::IntToString( int i )
{
std::stringstream Convert;
Convert << i;
std::string Answer;
Convert >> Answer;

return Convert.string();
}

Personally, I use a template for this.

template<typename T, typename F > T StrmConvert( const F from )
{
std::stringstream temp;
temp << from;
T to = T();
temp >> to;
return to;
}

template<typename F> std::string StrmConvert( const F from )
{
return StrmConvert<std::string>( from );
}

So I can do:

std::string Value = StrmConvert( 10 );

or even:

int Value = StrmConvert<int>( "10" );

Note that my StrmConvert does not have any error checking, any errors would
simply return a default constructed value. I.E. If you tried to convert
"xyz" to an int the result would be 0.
 
J

Jim Langston

pradeep said:
Thanks for all the answers.

I think Jim probably has the best solution but we haven't covered
templates yet and they seem very confusing, the code just blurs in
front of my eyes!

What I'd like is a simpler version of this. Here's an idea I had
which I think is very similar to what Jim tries to do but easier:
make a pipe and then cout>> the integer to the pipe, but then cin<<
it back as a string. Would that work?

There is a pipe command on my computer but it isn't mentioned in the
text book. I don't understand the argument, it's an array of 2 int. I
tried passing NULL but it didn't work.

Yes. That is what the stringstream example I also gave did.

std::string App::IntToString( int i )
{
std::stringstream Convert;
Convert << i;
std::string Answer;
Convert >> Answer;

return Convert.string();
}

std::stringstream is in this case the "pipe". Just instead of "cin" and
"cout" you use the name of the instantized stringstream. Just make sure you
#include <sstream>
#include said:
Jim said:
pradeep said:
Hello friends:

I know some people here don't like to answer C++ questions, but I
believe this is really about the underlying C code. Anyway I have
posted as well to the other group someone suggested
("comp.lang.c++") just in case.

I think the problem is that in my C++ class, we were taught to use
cin, cout etc. but now I need to use the primitive C operations
printf etc. and I don't understand exactly how they work.

I'm trying to convert an integer into a string. Here's what I'm
trying, but when I try to output the string returned from the
function, I just get garbage. How should I be using sprintf?

Thanks.



char *App::IntToString(int i) //doesn't really rely on classes
{
char buf[2];


Not big enough by far and disappears once IntToString finishes.

char *out = buf;


No reason to have to do this.

sprintf(out, "%d", i);


sprintf( buf, "%d", i );
would also work, although there are hte other problems.

return out;


you are returning a pointer to a buffer that goes out of scope when
the function returns.



So, how to fix this? Simplest is to make the buffer static so it
doesn't disappear when the function returns and make it big enough. char
buf[2]; is only large enough to hold "0" through "9". An
integer can hold quite a larger value, however. 10 or 11 digits I
think. char *App::IntToString(int i) //doesn't really rely on classes
{
static char buf[12];
sprintf(buf, "%d", i);
return buf;
}

Shoudl fix the immediate errors, but does not fix any design issues.
Such as the fact if you called this twice in a row, both returned
char*'s would point to the same value. I.E.

char* Value1;
char* Value2;

Value1 = IntToString( 10 );
Value2 = IntToString( 11 );

std::cout << Value1 << " " << Value2;

would output 11 11 since the pointers returned by IntToString are
identical, and the static buffer was changed.

It is better to return a std::string. You can do the conversion
either as is and convert to a std::string, or use use
std::stringstream. (Untested code).

std::string App::IntToString( int i )
{
std::stringstream Convert;
Convert << i;
std::string Answer;
Convert >> Answer;

return Convert.string();
}

Personally, I use a template for this.

template<typename T, typename F > T StrmConvert( const F from )
{
std::stringstream temp;
temp << from;
T to = T();
temp >> to;
return to;
}

template<typename F> std::string StrmConvert( const F from )
{
return StrmConvert<std::string>( from );
}

So I can do:

std::string Value = StrmConvert( 10 );

or even:

int Value = StrmConvert<int>( "10" );

Note that my StrmConvert does not have any error checking, any
errors would simply return a default constructed value. I.E. If
you tried to convert "xyz" to an int the result would be 0.
 
T

Thomas J. Gritzan

Jim said:
Yes. That is what the stringstream example I also gave did.

std::string App::IntToString( int i )
{
std::stringstream Convert;
Convert << i;
std::string Answer;
Convert >> Answer;

return Convert.string();
}

Doesn't compile. This will:

#include <sstream>
#include <string>

std::string IntToString( int i )
{
std::eek:stringstream Convert;
Convert << i;
return Convert.str();
}
std::stringstream is in this case the "pipe". Just instead of "cin" and
"cout" you use the name of the instantized stringstream. Just make sure you
#include <sstream>
#include <string>

You are aware that this is the comp.lang.c?
f'ups set to c.l.c++
 
K

Keith Thompson

pradeep said:
Thanks for all the answers.

I think Jim probably has the best solution but we haven't covered
templates yet and they seem very confusing, the code just blurs in
front of my eyes!

Templates are specific to C++. Why did you redirect followups to
comp.lang.c?
What I'd like is a simpler version of this. Here's an idea I had which
I think is very similar to what Jim tries to do but easier: make a
pipe and then cout>> the integer to the pipe, but then cin<< it back
as a string. Would that work?

cout>> and cin<< are specific to C++. Don't expect us to answer questions
about them here in comp.lang.c.
There is a pipe command on my computer but it isn't mentioned in the
text book. I don't understand the argument, it's an array of 2 int. I
tried passing NULL but it didn't work.

If your system has a pipe function (not command), then it should have
documentation for it. "man pipe" or some variation of it is likely to
show you that documentation. Or you can read
<http://www.opengroup.org/onlinepubs/009695399/functions/pipe.html>.
Since the pipe() function is defined by POSIX, not by either C or C++,
any more questions about it should be directed to
comp.unix.programmer.

Please don't top-post. Read the following:
http://www.caliburn.nl/topposting.html
http://www.cpax.org.uk/prg/writings/topposting.php

And please learn that we have different newsgroups, that discuss
different topics, for very good reasons. Posting to comp.lang.c about
C++ wastes everyone's time.
 
K

Keith Thompson

Jim Langston said:
Yes. That is what the stringstream example I also gave did.

std::string App::IntToString( int i )
{
std::stringstream Convert;
Convert << i;
std::string Answer;
Convert >> Answer;

return Convert.string();
}

std::stringstream is in this case the "pipe". Just instead of "cin" and
"cout" you use the name of the instantized stringstream. Just make sure you
#include <sstream>
#include <string>

Jim, I assume you posted from comp.lang.c++. Unfortunately, pradeep
cross-posted to comp.lang.c and comp.lang.c++ *and* redirected
followups to comp.lang.c, so your article appeared only in
comp.lang.c.

I've cross-posted this to comp.lang.c and comp.lang.c++ and redirected
followups to comp.lang.c++, since this branch of the conversation
seems to be C++-specific.
 
P

pradeep

Thanks alot to Jim Langton - it's a great solution.

I set to followup here because I'm subscribing to comp.lang.c so I'd
like to read people's replies here. I don't want to subscribe to
comp.lang.c++ because it's full of spam.

You seem to spend a lot of time telling people not to post here when it
would be better to answer questions if you know, or otherwise don't stop
other people getting answers.

Thanks.
 
I

Ian Collins

pradeep said:
Thanks alot to Jim Langton - it's a great solution.

I set to followup here because I'm subscribing to comp.lang.c so I'd
like to read people's replies here. I don't want to subscribe to
comp.lang.c++ because it's full of spam.
So you spam this group instead?

Get an decent news server and post where your posts belong.
 
S

Sean G. McLaughlin

pradeep said:
I set to followup here because I'm subscribing to comp.lang.c so I'd
like to read people's replies here. I don't want to subscribe to
comp.lang.c++ because it's full of spam.

So subscribe to comp.lang.c++.moderated. Problem solved.
 
S

santosh

pradeep wrote:

[Try not to top-post. It usually irks most Usenetters. I fixed it here.]
Thanks alot to Jim Langton - it's a great solution.

I set to followup here because I'm subscribing to comp.lang.c so I'd
like to read people's replies here. I don't want to subscribe to
comp.lang.c++ because it's full of spam.

That's unfortunate but that still does not make C++ questions or
discussions topical here. If your problem is with the subset of C++
that is valid C, and you are sure that the rest of the C++ code is not
in any way influencing this portion, then you could try posting here,
but in general it's strongly recommended to post C++ code or questions
in comp.lang.c++. Repeatedly posting C++ here will only get you
blacklisted by many posters who might otherwise have helped you out
with C.
You seem to spend a lot of time telling people not to post here when
it would be better to answer questions if you know, or otherwise don't
stop other people getting answers.

I guess he was just trying to preserve topicality. Usenet groups exist
for a reason. As you can see, most groups are already suffering from
spam from Google Groups users. No need to further drown the signal
under off-topic stuff.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top