See ChangeLog entry 19990520-03:00 EST David G. Holm <dholm@jsd-llc.com>

This commit is contained in:
David G. Holm
1999-05-20 07:57:39 +00:00
parent 4ed2ebdd98
commit 120db44828
5 changed files with 204 additions and 63 deletions

View File

@@ -1,3 +1,14 @@
19990520-03:00 EST David G. Holm <dholm@jsd-llc.com>
* include/extend.h
- Added new function hb_str() for public use.
* source/rtl/console.c
- hb_outstd() now uses hb_str() instead of formatting numerics itself.
* source/rtl/strings.c
- Added new hb_str() function to do all numeric formatting for all of Harbour.
- Rewrote STR() to call hb_str() after validating parameters.
+ tests/working/teststr.prg
- New module to test new function hb_str() via STR() and STDOUT().
19990519-23:50 EST David G. Holm <dholm@jsd-llc.com>
* source/rtl/extend.c
- Use wDec = hb_set.HB_SET_DECIMALS instead of wDec = 2.

View File

@@ -157,6 +157,7 @@ PITEM hb_arrayClone( PITEM pArray );
void hb_arrayAdd( PITEM pArray, PITEM pItemValue );
int hb_itemStrCmp( PITEM pFirst, PITEM pSecond, BOOL bForceExact ); /* our string compare */
char * hb_str( PITEM pNumber, PITEM pWidth, PITEM pDec ); /* convert number to string */
BOOL hb_strempty( char * szText, ULONG ulLen );
long hb_dateEncode( long lDay, long lMonth, long lYear );
void hb_dateDecode( long julian, long * plDay, long * plMonth, long * plYear );

View File

@@ -45,8 +45,15 @@ static void hb_outstd( WORD wParam )
printf ("%s", hb_dtoc (_pards (wParam), szBuffer));
break;
case IT_DOUBLE:
case IT_INTEGER:
printf( "%*i", pItem->wLength, pItem->value.iNumber );
case IT_LONG:
szText = hb_str( pItem, 0, 0 ); /* Let hb_str() do the hard work */
if( szText )
{
printf( "%s", szText );
_xfree( szText );
}
break;
case IT_NIL:
@@ -59,10 +66,6 @@ static void hb_outstd( WORD wParam )
printf( ".F." );
break;
case IT_LONG:
printf( "%*li", pItem->wLength, pItem->value.lNumber );
break;
case IT_STRING:
szText = _parc( wParam );
ulLenText = _parclen( wParam );
@@ -74,13 +77,6 @@ static void hb_outstd( WORD wParam )
}
break;
case IT_DOUBLE:
if( pItem->wDec )
printf( "%*.*f", pItem->wLength + 1 + pItem->wDec, pItem->wDec, pItem->value.dNumber );
else
printf( "%*ld", pItem->wLength, (long)pItem->value.dNumber );
break;
default:
break;
}

View File

@@ -987,68 +987,117 @@ HARBOUR VAL( void )
}
}
/* converts a numberic to a string with given width & precision */
/* converts a numeric to a string with optional width & precision.
This function should be used by any function that wants to format numeric
data for displaying, printing, or putting in a database.
Note: The caller is responsible for calling _xfree to free the results buffer,
but ONLY if the return value is not a NULL pointer!
*/
char * hb_str( PITEM pNumber, PITEM pWidth, PITEM pDec )
{
char * szResult = 0;
if( pNumber )
{
/* Default to the width and number of decimals specified by the item,
with a limit of 9 decimal places */
int iWidth = pNumber->wLength;
int iDec = pNumber->wDec;
if( iDec > 9 ) iDec = 9;
if( pWidth )
{
/* If the width parameter is specified, override the default value
and set the number of decimals to zero */
iWidth = _parnl(2);
if( iWidth < 1 ) iWidth = 10; /* If 0 or negative, use default */
iDec = 0;
}
if( pDec )
{
/* This function does not include the decimal places in the width,
so the width must be adjusted downwards, if the decimal places
parameter is greater than 0 */
iDec = _parnl(3);
if( iDec < 0 ) iDec = 0;
else if( iDec > 0 ) iWidth -= (iDec + 1);
}
if( iWidth )
{
/* We at least have a width value */
int iBytes, iSize = (iDec ? iWidth + 1 + iDec : iWidth);
/* Be paranoid and use a large amount of padding */
szResult = (char *)_xgrab( iWidth + iDec + 64 );
if( pNumber->wType == IT_DOUBLE || iDec != 0 )
{
double dNumber = _parnd( 1 );
if( iDec > 0 )
iBytes = sprintf( szResult, "%*.*f", iSize, iDec, dNumber );
else
iBytes = sprintf( szResult, "%*ld", iWidth, (long)dNumber );
}
else switch( pNumber->wType )
{
case IT_LONG:
iBytes = sprintf( szResult, "%*li", iWidth, pNumber->value.lNumber );
break;
case IT_INTEGER:
iBytes = sprintf( szResult, "%*i", iWidth, pNumber->value.iNumber );
break;
default:
iBytes = 0;
*szResult = 0;
break;
}
/* Set to asterisks in case of overflow (same reason for paranoia) */
if( iBytes > iSize )
{
memset( szResult, '*', iSize );
szResult[ iSize ] = 0;
}
}
}
return( szResult );
}
/* converts a numeric to a string with optional width & precision.
calls hb_str() after validating parameters
*/
HARBOUR STR( void )
{
if( _pcount() > 0 && _pcount() < 4 )
{
PITEM pNumber = _param(1, IT_NUMERIC);
if( pNumber )
BOOL bValid = TRUE;
PITEM pNumber = _param( 1, IT_NUMERIC ), pWidth = 0, pDec = 0;
if( !pNumber ) bValid = FALSE;
else
{
double dNumber = _parnd(1);
char szResult[348]; /* QUESTION: what about _really_ long numbers? */
PITEM pWidth = _param(2, IT_NUMERIC);
PITEM pDec = _param(3, IT_NUMERIC);
int iDec = (pDec? _parnl(3): -1);
int iWidth;
if( pWidth )
if( _pcount() > 1 )
{
iWidth = _parnl(2);
if( pDec && iDec )
{
if( sprintf(szResult, "%*.*f", iWidth, iDec, dNumber) > iWidth )
memset(szResult, '*', iWidth);
}
else if( sprintf(szResult, "%*.0f", iWidth, dNumber) > iWidth )
memset(szResult, '*', iWidth);
_retclen(szResult, iWidth);
pWidth = _param( 2, IT_NUMERIC );
if( !pWidth) bValid = FALSE;
}
else if( pDec )
if( _pcount() > 2 )
{
PITEM pError = _errNew();
_errPutDescription(pError, "Argument error: STR");
_errLaunch(pError);
_errRelease(pError);
pDec = _param( 3, IT_NUMERIC );
if( !pDec ) bValid = FALSE;
}
else
}
if( bValid )
{
char * szResult = hb_str( pNumber, pWidth, pDec );
if( szResult )
{
/*
TODO: Default formatting of Str()
Numeric expression Length of the return character string
--------------------------------------------------------------
Expressions/Constants At least ten digits plus decimal places
Field variable Field length including decimal places
Month()/Day() 3 digits
RecNo() 7 digits
Val() At least 3 digits
Year() 5 digits
*/
/* get the width of the decimal places */
int iDecWidth = sprintf(szResult, "%f", dNumber - (long)dNumber);
/* now print it with width 10 + decimals (the 9 is due to the ".") */
iWidth = sprintf(szResult, "%*f", 9 + iDecWidth, dNumber);
while( szResult[iWidth - 1] == '0' )
iWidth--;
if( szResult[iWidth - 1] == '.' )
iWidth--;
_retclen(szResult, iWidth);
_retc( szResult );
_xfree( szResult );
}
else _retc( "" );
}
else
{

View File

@@ -0,0 +1,84 @@
function main()
local a := 15.1
local b := 10.0002575
local nI, c, d
outstd (a)
outstd (-a)
outstd (b)
outstd (-b)
outstd (CHR(13)+CHR(10))
outstd (a + b)
outstd (a - b)
outstd (a * b)
outstd (a / b)
outstd (CHR(13)+CHR(10))
outstd (a % b)
outstd (a ** b)
outstd (CHR(13)+CHR(10))
c = a * b
d = b * a
outstd (CHR(13)+CHR(10))
outstd (str (c))
outstd (str (d))
outstd (CHR(13)+CHR(10))
outstd (str (c + d))
outstd (str (c - d))
outstd (str (c * d))
outstd (str (c / d))
outstd (CHR(13)+CHR(10))
outstd (CHR(13)+CHR(10))
outstd (a + b + c)
outstd (c - b - a)
outstd (b * a * c)
outstd (b * a * c * d)
b := 1.000213
outstd (b * b * b * b * b * b * b)
outstd (CHR(13)+CHR(10))
FOR nI := 1 to 20
outstd (CHR(13)+CHR(10))
outstd (10 ** nI)
NEXT nI
outstd (CHR(13)+CHR(10))
outstd (CHR(13)+CHR(10))
outstd (str (a))
outstd (CHR(13)+CHR(10))
outstd (str (b))
outstd (CHR(13)+CHR(10))
outstd (str (b, 12))
outstd (CHR(13)+CHR(10))
outstd (str (b, 12, 5))
outstd (CHR(13)+CHR(10))
outstd (str (b, 12, 7))
outstd (CHR(13)+CHR(10))
outstd (str (b, 5, 7))
outstd (CHR(13)+CHR(10))
outstd (str (b, 12, -7))
outstd (CHR(13)+CHR(10))
outstd (str (b, -12, 7))
outstd (CHR(13)+CHR(10))
outstd (str (b, 0))
outstd (CHR(13)+CHR(10))
return nil