Solved

C routine needed to convert inger to string

Posted on 2001-06-20
33
409 Views
Last Modified: 2010-04-02

I want to convert DEC(11) values into CHAR(11) values. After converting this DEC(11) value, I have assign it to CHAR(11).  I need a C routine for this.

Experts , can you help me,please?
0
Comment
Question by:veeramani
  • 10
  • 7
  • 7
  • +6
33 Comments
 
LVL 10

Expert Comment

by:makerp
ID: 6213198
char *_itoa( int value, char *string, int radix );

so

int number = 11;
char buffer[10];

_itoa(number,buffer,10);

printf("NUMBER %d STRING %s\n",number,buffer);
0
 
LVL 3

Expert Comment

by:elcapitan
ID: 6213302
>>I want to convert DEC(11) values into CHAR(11) values
What do you mean by DEC(11)? Do mean that each integer in the array will contain only 1 digit, or each integer can be more then 1 digit?
if, as I suspect, the first case is what you meant, then you need to convert each digit to its character. Something like that:

void ConvertArray(int *intArray, char *charArray, int nSize)
{
  for(int i=0; i<nSize; ++i)
  {
    charArray[i] = '0'+intArray[i];
  }
  charArray[i]='\0';
}

Of coursr, you need to make sure that the int array contains only 1 digit in each cell.

--EC--
0
 
LVL 1

Author Comment

by:veeramani
ID: 6213366
It means, length of the integer field and string field are same as 11 digits.

Ex : '12345678901'  and 12345678901
0
 
LVL 10

Expert Comment

by:makerp
ID: 6213374
well just use itoa and make sure the buffer you use is big enough
0
 
LVL 30

Expert Comment

by:Axter
ID: 6213920
itoa is not part of the ANSI C++ standards.

You can use sprintf;
int n = 123456;
char data[32];
sprintf(data,"%i",n);
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6214858
> You can use sprintf;
or stringstream which is even more C++ like:

    std::stringstream is;
    is << 123456;
    std::string s = is.str();
    char buffer[32];
    strcpy(buffer, s.c_str());



0
 

Expert Comment

by:sindbad
ID: 6215639

since, it is C, use sprintf.

#include <stdio.h>

int i = 12345;
sprintf("%11d",i);

0
 

Accepted Solution

by:
wkmatt42 earned 50 total points
ID: 6216073
Try this - it will fill and right-justify your buffer with a number. While it requires a little more code than the above solutions, it's faster and more flexible. It also makes a few assumptions, some of which you explicitly stated, others are a guess based on the wording of a question.

1. In stating that CHAR(11) is the same size as DEC(11), you're not leaving any room for the null-terminator, so I skipped it.

2. For the same reason, I've omitted any error-checking code to make sure that the buffer you supply is not too small for the provided value.

3. The character array is right-justified and any excess digits on the left are filled with spaces, since that is a friendly way to display numbers.

4. This code only supports positive integers (if all you need to translate is positive numbers, this code is faster).

The code is easily modified, so if any of the above assumptions are wrong, feel to clarify them for me and I'll be happy to tweak the code.


void translateIntToChar(unsigned int nValue, char* pchBuffer, int nBufferSize)
{
    char pch* = pszBuffer + nBufferSize - 1;

    while (nValue > 0)
    {
        *pch-- = '0' + (nValue % 10);
        nValue /= 10;
    }

    /* left-fill with spaces (or whatever you prefer) */
    while (pch >= pszBuffer)
    {
        *pch-- = ' ';
    }
}

You can either call the function above or use a macro like:

#define INT_TO_CHAR(value, buffer) \
    translateIntToCharvalue, buffer, sizeof(buffer))
0
 

Expert Comment

by:wkmatt42
ID: 6216094
Oops - I'm new so I didn't realize that posting "answers" was frowned upon. I'll be sure to opt for "comment" in the future.

- Matt
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6218417
wkmatt42, Macros are generally regarded as bad news (especially in C++), and ones like yours, which don't actually work are likely to be regarded as bad news, even in C.  I suggest you work out what sizeof actually does.
0
 

Expert Comment

by:wkmatt42
ID: 6218488
Macros are not a bad idea, even in C++. They can be and often are misused, hence their bad reputation. In C++, macros should be less frequent simply because we have the ability to replace most of them with constants and inline functions.

I frequently use macros like the one above to avoid using repetitive and lengthy sizeof expressions. There is, of course, a typo in the one above (I omitted a leading parenthesis after translateIntToChar). Use of the macro also expects that your buffer is a character array (i.e. char buffer[11]). Otherwise, you can simply call the function directly - not a big deal.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6218545
wkmatt42,
I myself don't mine using macros, as long as they are used properly.
But you'll find a lot of hardcore C++ programmers, that feel macros should not be use under any circumstances, and there is nothing you can say to change their mind.
0
 

Expert Comment

by:wkmatt42
ID: 6218591
That doesn't mean I shouldn't feel obliged to gently nudge them from time to time, since I may some day have to fix their code.

Actually, I've been doing this long enough to realize we all have our little eccentricities - it was his condescending tone that I could have done without.
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6219224
First the macro is bad, it doesn't always do the right thing, it would fail, silently with code like this:

void f(char* s)
{
   INT_TO_CHAR(123456,s);
}

> But you'll find a lot of hardcore C++ programmers, that feel macros

more than just hardcore C++ programmers.  There is no excuse for them in C++ code at all (this kind of macro is far better replaced with an inline function).  C++ is designed to remove the need for macros.

There are many, many potential pitfalls, this link describes a few:

http://www.gotw.ca/gotw/077.htm



0
 

Expert Comment

by:wkmatt42
ID: 6219325
1. Show me an inline function that does that can do what the INT_TO_CHAR macro does and I'll use it. The article you reference only makes the case that it's a good idea not to use macros when they could be implemented with inline functions. I made the same case above.

2. Reread my previous comment and you'll see that I specify that the macro only works if you are providing it with a character array.

3. C++ was actually designed to provide an object-oriented language that the existing C developer community would be comfortable with.

4. Finally, how painful do you suppose ATL development would be if you could use the handy macros Microsoft supplies (particular those for building the message handler maps).

Are you getting all this, veeramani? C++ religious wars can at times be more entertaining than writing code.
0
 
LVL 22

Expert Comment

by:nietod
ID: 6221215
wkmatt42, you should listen to jason.  he doesn't post these things lightly.   What woudl be better than using that macro?  How about using a string class object instead of character arrays (Almost always a good idea anyways) then there is no need for that macro.   I strongly reocmment you consider any alternative possible to avoid macros.     I also wonder why you think yourr code qualifies as an answer when axter's and jason's doesn't?  Especially since those solutiosn don't suffer from many of the weaknesses that you've mentioned in your own.
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 

Expert Comment

by:wkmatt42
ID: 6221248
I already explained that posting as an answer was a newbie mistake that won't happen again.

Had veeramani asked how to convert a DEC(11) to a string, I would have explained how to convert it to a string. What he wanted to know was how to convert it to a CHAR(11), so I chose to answer the question he asked. Terribly presumptious of me, I know.

I also never said my answer was an improvement on what axter and jason proposed - it was simply an alternative in case veeramani was actually working with a character array, as his question seemed to imply, rather than a null-terminated string. My solution is also faster than most implementations of sprintf and WAY faster than using streams.
0
 
LVL 22

Expert Comment

by:nietod
ID: 6222226
>> I already explained that posting as an answer was a
>> newbie mistake that won't happen again.

What you said was

>>  I'm new so I didn't realize that posting "answers" was frowned upon.

Actually don't be fooled.   In this topic are posting answers is not frowned upon as long as the post qualifies as an answer.  (Currently some experts are on a crusade to prevent people from posting answers.  But the EE rules do allow you to post answers when appropriate.)  However, your post doesn't really qualify as an answer since better solutions were previously posted.

>> Had veeramani asked how to convert a DEC(11) to a string, I would have
>> explained how to convert it to a string.
My points was to you.  That you can almost always avoid using macros.  The point is that better solutiosn are available that eliminates the need for macros.  

>> I also never said my answer was an improvement on what
>> axter and jason proposed
The fact that you answered suggests that it is.  That might have been a mistake on your part as a newbie.  But you need to realize that the client often can't differentiate between good and bad solutions and is likely to go with the solution that is posted as an answer simply because it "claims" to be the answer.  Thus you have to be careful to not post as an answer if you are not reasonably certain that it is the best solution, especially if there are previous posts that might be better.

>> My solution is also faster than most implementations of
>> sprintf and WAY faster than using streams.
The difference in speed with sprinf() is not likely to be significant, however, sprinf() could be faster.  Cetainly it should use a better algorithm than translateIntToChar(), but it does have addtional overhead because of its numerous features.  
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6224063
The problem with macro's is that they fail to easily,  the C convention of passing around sizes with arrays is there for a reason - any other test is unreliable.

Your macro only works in a very restricted situation, one that is probably not all that common in real programs. But the worst point is that it is very easily (accidentally) misused.

i.e. you have code like:

char buffer[2];
INT_TO_CHAR(12, buffer)

someone changes it, maybe to fit in two numbers,
char buffer[5];
INT_TO_CHAR(12, buffer)
INT_TO_CHAR(12, buffer+3)

and suddenly it doesn't work (crashes the program, at best) in a completely counter-intuitive way.

> 3. C++ was actually designed to provide an object-
> oriented language that the existing C developer community
> would be comfortable with.

and to remove the need to program using 'broken' C features.  From Bjarne Stroustrup's the Design & Evolution of C++, from one of the C++ design goals:

'Preprocessor usage should be eliminated: ... alternatives that fit with the syntax and semantics of C++ must be found ... root out the sources of many difficult bugs'

BTW, C++ is not strictly an OO language, it supports OO programming, but it does not mandate it, it also supports structured programming and generic programming amongst other paradigms.

0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6224518
> You can use sprintf;
or stringstream which is even more C++ like:

    std::stringstream is;
    is << 123456;
    std::string s = is.str();
    char buffer[32];
    strcpy(buffer, s.c_str());



0
 

Expert Comment

by:wkmatt42
ID: 6225331
You guys are getting awfully excited about the macro thing, considering it has nothing to do with the function itself. It was merely a suggestion ("you can either call the function or ... macro ..."). I still think your unconditional aversion to macros is a bit silly, much like the zero-tolerance drug policies that force expulsions for aspirin-popping teens, but to each his own. (Though I don't believe for a second that you code your ATL message maps without a macro or two.)

Now, as to the algorithm itself - most implementations of sprintf are probably comparable to the above function, though after the compiler has a chance to optimize it, mine will (and does) run faster. And the fact that mine is less than ten lines of code makes it an ideal canditate for inlining, saving even the overhead of a function call. Don't even get me started on the string/strstream version.

Finally, performance always matters. While veeramani may only be processing one or two numbers with this function, there's no reason to think he might not be generating or otherwise processing several million records, each with multiple fields that need translating. Or he might need to do so later. Regardless, it doesn't really take a lot of effort to type 10 lines of code. Nor is it exhausting to stash the code in a library for later use so you never have retype such an arduous algorithm. (The only purpose for the last sentence was for the alliteration at the end - I felt inspired.)

I'm working on a project I don't really enjoy doing, so I took a quick break to run a few tests to make sure I wasn't crazy:

CPU usage for 1000000 iterations of each solution on both AIX and Sun boxes

            AIX     Sun
---------  ------  ------
mine        1.31s   1.89s
sprintf     1.79s   2.51s
string     17.71s  42.71s

(Yes, folks - that's more than an order of magnitude!)

I don't know WHAT is up with Sun's STL implementation, but I ran it a few times to make sure the runtimes were accurate.
0
 
LVL 22

Expert Comment

by:nietod
ID: 6225447
>> I still think your unconditional aversion to macros is a bit silly,
some silly people in the field, like Scott Meyers, Bjarne Stroustrup, and Herb Sutter have also been simmilarly silly.

>> most implementations of sprintf are probably comparable to the above
>> function
I doubt that.  Its used enough that a good implimentation will take th time to make it fast.  A good implimentation will use unline assembly to avoid the redudant division and modulos operations (they can be done in one step), It will probably try to handle multiple digits per iteration (to reduce memory access), it will probably use loop unrolling, perhaps complete unrolling since the maximum number of iterations needed is low,

>> Finally, performance always matters.
That is a common falacy.    I recommend you read some good books on optimization, like "The Zen of Code Optimization".  learn about the 80-20 rule.

>> reason to think he might not be generating or otherwise processing several
>> million records, each with multiple fields that need translating.
if so, the disk accesses will swamp the overhead by 10,000 to one.  You could take an innifiecnt call to printf() and perform it 100 times for each time that it was needed only once and you would never be able to measure the overhead produced by not one, but 100*a million extra calls.  That is why the determination of bottlenecks is so important.

>> (Yes, folks - that's more than an order of magnitude!)
acually your code is on the same order of magnitiude as sprintf(), only slightly faster, but it is far far less powerful.  (sprintf() can handle hex, negatives, precision, padding, etc etc.


>> I don't know WHAT is up with Sun's STL implementation, but I ran it a few
>> times to make sure the runtimes were accurate.
Actually that is surprisingly good.  I would have though stringstream woudl have been 2 orders of magnitude slower.  It has MUCH more complexity.  It has to dynamcially allocate storeage space, that is significatn overhead, pluss it must handle localization, and its it template paramaterized for general data types.  The amount of work it has to do compared to your code is amazing.  The fact that it can do son in less than 20 times the time is amazing.
0
 
LVL 7

Expert Comment

by:KangaRoo
ID: 6225516
>> Show me an inline function that does that can do what the INT_TO_CHAR macro does...

You ask, we deliver:

template <int sz>
inline void translate(unsigned int n, char (&buff)[sz])
{
   translateIntToChar(n, buff, sz);
}

which will only allows arrays to be passed.
Even though the macro is just a sidestep I thought you might like to see it.
0
 
LVL 22

Expert Comment

by:nietod
ID: 6225533
excellent!
0
 

Expert Comment

by:wkmatt42
ID: 6225627
1. The order of magnitude is OBVIOUSLY a reference to the string code. Duh.

2. I think we all know that sprintf has some pretty powerful features, but the trade off is that it does some simple things slower. In fact, if I didn't already have access to a library of conversion functions similar to the one I wrote above, I'd likely use sprintf myself. But it does create null-terminated strings - the original reason I answered the question at all after others had already taken a crack at it was to provide the original poster with a non-null-terminated solution. (Since his original post was about the ambiguous CHAR(11) and I wanted to ensure we gave him every reasonable option.)

3. My surprise at the runtime of the Sun version was that it was so much greater than the AIX version, hence my reference only to Sun's STL implementation. There was no surprise that both were grossly slower than either my or the sprintf implementation.

3. The 80/20 rule addresses potentially time-wasting optimizations. My function only took about 20 seconds to write.

KangaRoo - I've never seen that done. Very cool. But now I have to change my conversion library. Thanks!
0
 
LVL 22

Expert Comment

by:nietod
ID: 6225976
>> it does some simple things slower.
In your case it was slightly slower.  You can't say that it is universally true and the results were pretty close.  You would have to have a very good reason to choose to go to the trouble to write and test a less powerful procedure when a standard procedure exists that is very powerful and nearly as fast--perhaps even faster at times.

>> 3. The 80/20 rule addresses potentially time-wasting optimizations.
That and much much more.  

>> My function only took about 20 seconds to write.
I've seen versions that I would guess took weeks to write.  
0
 
LVL 1

Author Comment

by:veeramani
ID: 6226065
The function is working fine. I didn't use the macro, because it still under investication. I learned a lot from your technical debating of experts. Thank you very much wkmatt42 and all who participate in this debate.

Regards,

Veeramani.
0
 

Expert Comment

by:wkmatt42
ID: 6226220
One last comment to address the following:

"... You would have to have a very good reason ..."

I did have what I thought was a good reason - the version I introduced handles non-null-terminated character arrays as opposed to the null-terminated strings addressed by the other solutions. Little did I know what I was getting in to.

And, as I said, I'm in the middle of a really boring project and so far I've managed to avoid actually working on it through any distraction I can find. This forum, I must say, is so far the most entertaining such distraction I've latched on to yet.

Thanks for the spirited debate.

- Matt
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6226888
> My function only took about 20 seconds to write.

And is much more likely to be the cause of hard to find bugs than an implementation using strings/streams.

The purpose of avoiding unecessary optimisation is to reduce the potential for bugs.  Many possible optimisations are (at least initially) simple (e.g. replace a vector with a C style array), but that doesn't mean it is a good idea to always do it.
0
 
LVL 22

Expert Comment

by:nietod
ID: 6227075
>> I did have what I thought was a good reason - the version I introduced
>> handles non-null-terminated character arrays
That might be a good reason.   Although I don't I see any evidence that a non-terminated string is required.  Did I miss something?
0
 

Expert Comment

by:wkmatt42
ID: 6227658
The question was ambiguous about null-terminated string vs character arrays, so I opted to provide a solution to the latter since solutions were already provided for the former. (Since I've mentioned that a few times already, I'd have to say yes you missed something. But I'll get over it.)

Jason - if a programmer can manage to screw up something as simple as calling translateIntToChar(), they don't have much business writing code anyway. And while the argument for sprintf is a good one (assuming the null-termination thing is an acceptable solution), implementing something more than 1000% slower (i.e. the string/stream solution) is completely without merit.
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6227840
> if a programmer can manage to screw up something as
> simple as calling translateIntToChar()

haven't you ever heard of anything like 'defensive programming'?

You should try to prevent users from forseeable misuse, particularly memory problems in C/C++.

Your function suffers from all the potential memory overwrite type problems that are commonplace.

A function like this:

template <typename T>
std::string translateValueToChar(T value, size_t minSize = 0, char padChar = ' ')
{
   std::ostringstream os;
   os << std::setw(minSize) << std::setfill(padChar) << value;  
   return os.str();
}

is much less error prone, more generic and simpler to call.
0
 
LVL 22

Expert Comment

by:nietod
ID: 6227865
>> implementing something more than 1000%
If it not a bottleneck, 100,000% slower probably won't matter.

>> is much less error prone, more generic and simpler to call.
"Make it right, then make it fast"--Herb Sutter.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now