intToStr

A

Andrej Viktorovich

Hello,

Moving from delphi to C :)

Got garbage on output while converting integer to C string. Have feeling that something wrong with char* on intToStr return. What is the right way of doing that?

char* intToStr(int value)
{
char buffer[33];
char* c;
c= itoa(value,buffer,10);
return buffer;
}

int _tmain(int argc, _TCHAR* argv[])
{

cout<<intToStr(55)<<"\n";

getc(stdin);

return 0;
}

Thank you
 
M

Mark Bluemel

Hello,

Moving from delphi to C :)

I don't think so. What you have below looks like C++...
Got garbage on output while converting integer to C string. Have
feeling that something wrong with char* on intToStr return. What
is the right way of doing that?

Assuming that C++ differs little from C in this respect, you're
returning the address of a buffer which is local to the invocation of
intToStr. It's not a good idea.
char* intToStr(int value)
{
char buffer[33];
char* c;
c= itoa(value,buffer,10);
return buffer;
}

int _tmain(int argc, _TCHAR* argv[])
{

cout<<intToStr(55)<<"\n";

getc(stdin);

return 0;
}

Thank you
 
A

Andrej Viktorovich

Assuming that C++ differs little from C in this respect, you're
returning the address of a buffer which is local to the invocation of
intToStr. It's not a good idea.


I have feeling that in C i must create memory area and pass it like parameter to function that converts int to string.

But I would like to have simple function with one param of integer and I would like to ask intToString to do all that job of creating memory area and I need just char[] on utput. Is it possible to think that way in C?

Thank you
 
K

Kenny McCormack

Assuming that C++ differs little from C in this respect, you're
returning the address of a buffer which is local to the invocation of
intToStr. It's not a good idea.


I have feeling that in C i must create memory area and pass it like
parameter to function that converts int to string.

But I would like to have simple function with one param of integer and I
would like to ask intToString to do all that job of creating memory area
and I need just char[] on utput. Is it possible to think that way in C?

Thank you

You can usually work around this by making the local buffer static.

But the problem with that is that your function then becomes not
"thread-safe" (and also, can't be called recursively).

--
"The anti-regulation business ethos is based on the charmingly naive notion
that people will not do unspeakable things for money." - Dana Carpender

Quoted by Paul Ciszek (pciszek at panix dot com). But what I want to know
is why is this diet/low-carb food author doing making pithy political/economic
statements?

Nevertheless, the above quote is dead-on, because, the thing is - business
in one breath tells us they don't need to be regulated (which is to say:
that they can morally self-regulate), then in the next breath tells us that
corporations are amoral entities which have no obligations to anyone except
their officers and shareholders, then in the next breath they tell us they
don't need to be regulated (that they can morally self-regulate) ...
 
H

Heinrich Wolf

....
char* intToStr(int value)
{
char buffer[33];
char* c;
c= itoa(value,buffer,10);
return buffer;
}
....
buffer is only valid inside intToStr. After "return buffer;", buffer is
destroyed. You need "static char buffer[33];" But that is not reentrant!
When doing similar things, I call intToStr with a buffer supplied by the
caller.

char* intToStr(int value, char *buffer)
{
itoa(value,buffer,10);
return buffer;
}

int _tmain(int argc, _TCHAR* argv[])
{
char buffer[33];
cout<<intToStr(55, buffer)<<"\n";
getc(stdin);
return 0;
}
 
S

Stefan Ram

Andrej Viktorovich said:
But I would like to have simple function with one param of
integer

Do you mean int?
and I would like to ask intToString to do all that job of
creating memory area and I need just char[] on utput.

It is better to pass in a buffer of the right size, which
is some value near LOG10(INT_MAX), say LOG10(INT_MAX)+2
or so. You get INT_MAX from <limits.h> and still need to
define LOG10 yourself.

The called function could allocate a buffer using malloc,
but management of memory with allocated storage duration
is more difficult in C.
 
J

James Kuyper

Hello,

Moving from delphi to C :)

Got garbage on output while converting integer to C string. Have feeling that something wrong with char* on intToStr return. What is the right way of doing that?

char* intToStr(int value)
{
char buffer[33];
char* c;
c= itoa(value,buffer,10);

itoa() is not a C standard library function. I'll assume, given the
context, that it fills buffer with a string corresponding to the
specified value, using base 10?
return buffer;
}

The object named buffer has a lifetime that ends when your function
returns. Dereferencing a pointer that points at an object whose life
time has ended has undefined behavior. In practical terms, by the time
your program has a chance to look at the memory pointed at by the
string, it may already have been reassigned for some other use.

You have two main options.

The first is to give buffer static storage duration, which means that
it's life time extends from the beginning of the program all the way to
the end of the program; the pointer will remain valid forever. But this
means that if you call intToStr() twice, the pointer returned by the
first call will, after the second call, point to the string containing
the result the second call.

A second option is to allocate memory for the string using malloc(). The
lifetime of such memory continues until the memory has been free()d.
Problem: if you don't free() it, you've got a memory leak. You can't
free() it unless you stored the pointer somewhere so it can be passed to
free(), which is not the case in the code below:
int _tmain(int argc, _TCHAR* argv[])
{

cout<<intToStr(55)<<"\n";

I thought you said you were using C? This looks like C++, a different,
though closely related language. You'll get better answers about such
things by going to comp.lang.c++. Among other things, you could use new
and delete instead of malloc() and free(), and there are smart pointer
types you can use to avoid the necessity of explicitly using delete,
though I'm not well qualified to explain those. Also, do you realize
that you'd get a similar result by writing

cout << 55 << "\n";

It would also be more idiomatic to use endl rather than "\n".

You only need to do complicated things like this when cout() doesn't
already have the needed overloaded operator<<, for instance when you're
trying to print out a user defined type (UDT). The idiomatic C++ way to
handle that problem is to define your own operator<< overload. It should
take std::eek:stream& as it's first argument, your UDT as the second, and
it should return its first argument as a reference, so << overloads can
be chained together.
 
A

Andrej Viktorovich

Thank you, I got many answers to a lot of hypothetical questions.

But how do you deal in case for example when you need just log some variables like debug info. How you construct string that will be saved to file? Doyou really make such long and boring conversion to string routine (creating char[] variable, calling itoa ) for each variable of a,b,c and then concatenate them into one string before passing to function SaveToDebugInfoFile..

void SaveToDebugInfoFile(char[] info)
{
....
}

int main
{
int a =1;
int b =2;
int c =3;
....

SaveToDebugInfoFile(*/ need to pass a,b,c variables with some text /*);
}

I hope to have in output something like this:
"variable a=1 , variable b=2, variable c=3"


int main
{
int a =1;
int b =2;
int c =3;
....

SaveToDebugInfoFile(*/ need to pass a,b,c variables with some text /*);
}

I hope to have in output something like this:
"variable a=1 , variable b=2, variable c=3"
 
S

Stefan Ram

Andrej Viktorovich said:
SaveToDebugInfoFile(*/ need to pass a,b,c variables with some text /*);

Possibly, pass a format string and a va_list and then use vsnprintf.
 
H

Heinrich Wolf

Stefan pointed you the C way with vsnprintf. Since you seem to use C++ you
should maybe ask also in a C++ newsgroup. There is a stringstream class. But
I am not expirienced with that.
 
M

Mark Bluemel

Thank you, I got many answers to a lot of hypothetical questions.

No - you got the answer to the question you asked. You were told why
your example code failed and you were shown a number of ways in which,
using C, your code could be made to work.
But how do you deal in case for example when you need just log some
variables like debug info.

That is not the question you asked. The answer to it is probably
language-specific. If you are actually planning to work in C, you'ld use
a member of the printf family - your example below suggests that
fprintf() may be appropriate.

In C++ it is likely that there are other mechanisms which would be
appropriate.

If you are planning to use C++, you should post your questions to the
appropriate newsgroup - comp.lang.c++
void SaveToDebugInfoFile(char[] info)
{
...
}

int main
{
int a =1;
int b =2;
int c =3;
...

SaveToDebugInfoFile(*/ need to pass a,b,c variables with some text /*);
}

I hope to have in output something like this:
"variable a=1 , variable b=2, variable c=3"


int main
{
int a =1;
int b =2;
int c =3;
...

SaveToDebugInfoFile(*/ need to pass a,b,c variables with some text /*);
}

I hope to have in output something like this:
"variable a=1 , variable b=2, variable c=3"
 
M

Malcolm McLean

בת×ריך ×™×•× ×©×™×©×™, 29 ביוני 2012 15:05:39 UTC+1, מ×ת Andrej Viktorovich:
Thank you, I got many answers to a lot of hypothetical questions.

But how do you deal in case for example when you need just log some variables like debug info. How you construct string that will be saved to file? Do you really make such long and boring conversion to string routine (creating char[] variable, calling itoa ) for each variable of a,b,c and then concatenate them into one string before passing to function SaveToDebugInfoFile.
No, you use vsprintf to construct

SaveToDebugInfoFilef(char *format, ...)

Then you just pass strings to this function, exactly as you would to printf().

If you want to dump an array there's no way of doing it other than in a loop. You could write your own vsprintf() equivalent that takes arrays, but that would probably be more trouble than its worth.
 
K

Keith Thompson

Andrej Viktorovich said:
Assuming that C++ differs little from C in this respect, you're
returning the address of a buffer which is local to the invocation of
intToStr. It's not a good idea.

I have feeling that in C i must create memory area and pass it like
parameter to function that converts int to string.

But I would like to have simple function with one param of integer and
I would like to ask intToString to do all that job of creating memory
area and I need just char[] on utput. Is it possible to think that way
in C?

Yes, but you have to think *really hard*. :cool:}

You can't just return a string or array from a C function. It has to be
allocated somewhere, and you pretty much have to manage that allocation
yourself.

There are (at least) three approaches:

1. Declare the local buffer as "static", so its lifetime extends over
the entire execution of the program. This has some drawbacks. There's
only one buffer in memory, so successive calls will clobber the value
from previous calls. And you have to decide how big the buffer needs to
be.

2. Have the caller pass in a pointer to (the first element of) its own
buffer.

3. Have the function allocate a new buffer using malloc(). This makes
the caller responsible for free()ing the buffer when it's done with it.

(Since you're using "cout << ...", you might consider using C++
mechanisms for this, like std::string. But if you have any questions
about C++, you'll need to ask in comp.lang.c++.)
 
F

Fred K

Thank you, I got many answers to a lot of hypothetical questions.

But how do you deal in case for example when you need just log some variables like debug info. How you construct string that will be saved to file? Do you really make such long and boring conversion to string routine (creating char[] variable, calling itoa ) for each variable of a,b,c and then concatenate them into one string before passing to function SaveToDebugInfoFile.

void SaveToDebugInfoFile(char[] info)
{
...
}

int main
{
int a =1;
int b =2;
int c =3;
...

SaveToDebugInfoFile(*/ need to pass a,b,c variables with some text /*);
}

I hope to have in output something like this:
"variable a=1 , variable b=2, variable c=3"


int main
{
int a =1;
int b =2;
int c =3;
...

SaveToDebugInfoFile(*/ need to pass a,b,c variables with some text /*);
}

I hope to have in output something like this:
"variable a=1 , variable b=2, variable c=3"

If all you want is to write it to a log file, what's wrong
with just using fprintf() ? Then you don't ever need to
create buffer space at all.
 
I

Ike Naar

cout << 55 << "\n";

It would also be more idiomatic to use endl rather than "\n".

It's not the same thing. "\n" outputs a newline,
std::endl output a newline and performs a flush.
 
J

James Kuyper

[Restored context:]
....

This actually works in a C program???

No, it was a comment referring to C++ code, as you can tell from the
restored context quoted above.
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top