Subject: Re: Converting packed decimal to a char array From: Jevgeni Astanovski Date: Sat, 10 Jan 2015 13:06:05 +0200 List-archive: List-help: List-id: "Bare Metal Programming IBM i \(AS/400 and iSeries\)" List-post: List-subscribe: , List-unsubscribe: ,

Thanks Aaron.
Never saw such macros. Will give it a try.
This is, of course, a question of personal preferences, but I do not
like this sort of constructions. I'll get back and experiment with it.
Another option that I will probably evaluate is to switch to C++ and
use overloaded (?) functions. In fact the source data uses only a
limited number of decimal types - not more that 10 maybe. And it is
not so difficult to write 10 functions with the same name and
different types of arguments.
But it is not nice. Or elegant.

On Fri, Jan 9, 2015 at 6:37 PM, Aaron Albertson <albertaa@xxxxxxxxxx> wrote:

Hi Jevgeni,

Assuming that you want to avoid a complicated case statement in the
function you will have to use a (ugh) function-like macro. Here is an
example of what such a macro would look like. It is very bare bones.
You'd need to be sure first that the size of your intermediate string is as
large as your largest number of potential digits plus three (for the '-'
and '.' characters and the trailing null character), and second that the
size of the character array passed to the macro is as large as the number
of digits in the passed in packed decimal plus two (for the '-' and '.'
characters). The first part is easy by just setting the size of the
intermediate string to be the maximum possible size of a packed decimal
value plus three. The example below assumes you are not using 63-digit
packed decimals. If you want to use 63-digit packed decimals replace
DEC_DIG with DEC63_DIG. The second part could be verified in the macro.

Note: DEC_DIG, digitsof, and precisionof are all defined in the 'decimal.h'

----------------------------- Begin Example -----------------------------

#include <decimal.h>
#include <stdio.h>
#include <stdlib.h>

char intermediate_form[DEC_DIG + 3];
#define packedToCharArray(charArray, packedVal) { \
\
sprintf(intermediate_form, "%0*D(*,*)", \
digitsof(packedVal) + 2, \
digitsof(packedVal), \
precisionof(packedVal), \
packedVal); \
\
memcpy(charArray, intermediate_form, \
digitsof(packedVal) + 2); \
\
}

int main(void){
decimal (15,9) A = -123456.123456789D;
decimal (15,9) B = 123456.123456789D;
char sField[17];

packedToCharArray(sField, A);

printf("%.17s\n", sField);

packedToCharArray(sField, B);

printf("%.17s\n", sField);
}

----------------------------- End Example -------------------------------

Hope that helps!

Aaron

From: Jevgeni Astanovski <jevgeniast@xxxxxxxxx>
To: "Bare Metal Programming IBM i (AS/400 and iSeries)"
<c400-l@xxxxxxxxxxxx>
Date: 01/09/2015 03:01 AM
Subject: [C400-L] Converting packed decimal to a char array
Sent by: "C400-L" <c400-l-bounces@xxxxxxxxxxxx>

Hi all,

spend a lot of time and feeling like I run into a dead cycle with a
problem, that looks trivial.

I have packed decimals in my C programs that I need to convert to a
char array, representing the number (not zero terminated string).

For example:

decimal (15,9) A ;
char szTemp[32], sField[16] ;

sprintf(szTemp, "%016D(15,9)", A) ;
memcpy(sField, szTemp, 16) ;

What I want to achieve is get a function, that receives A and returns
sField.
Of course it must support any types of decimal - not only decimal
(15,9) but others like decimal(11,7), decimal (15,0), decimal (5,0)
and so on. And, of course, decimal can be positive or negative...

Any ideas?

Jevgeni.
--
This is the Bare Metal Programming IBM i (AS/400 and iSeries) (C400-L)
mailing list
To post a message email: C400-L@xxxxxxxxxxxx
To subscribe, unsubscribe, or change list options,
visit: http://lists.midrange.com/mailman/listinfo/c400-l
or email: C400-L-request@xxxxxxxxxxxx
Before posting, please take a moment to review the archives
at http://archive.midrange.com/c400-l.

--
This is the Bare Metal Programming IBM i (AS/400 and iSeries) (C400-L) mailing list
To post a message email: C400-L@xxxxxxxxxxxx
To subscribe, unsubscribe, or change list options,
visit: http://lists.midrange.com/mailman/listinfo/c400-l
or email: C400-L-request@xxxxxxxxxxxx
Before posting, please take a moment to review the archives
at http://archive.midrange.com/c400-l.