See ChangeLog entry 19990520-03:00 EST David G. Holm <dholm@jsd-llc.com>
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
84
harbour/tests/working/teststr.prg
Normal file
84
harbour/tests/working/teststr.prg
Normal 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
|
||||
Reference in New Issue
Block a user