// (C) Copyright Adolfo Di Mare 2011 // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // Revision history: // 11 Oct 2011 Adolfo Di Mare // Initial (non boost) version // mnyfmtts.c (C) 2011 adolfo@di-mare.com // Test file for mnyfmt() // - Works with Borland C++ 3.1 (1992) // - Works with Code::Blocks 10.05 (2010) /** \file mnyfmtts.c \brief Test program for \c mnyfmt(). \author Adolfo Di Mare \date 2011 */ // Define this macro if your compiler does not have a (long long) data type // #define MNYFMT_NO_LONG_LONG #include "mnyfmt.h" // This works in the Borland C++ 3.1 IDE // Alt-Options -> Compiler -> Code generation... // -> Defines MNYFMT_NO_LONG_LONG #ifdef __cplusplus // To compile the C source using the C++ compiler, override the file's extension. // The GNU gcc compiler does this with option -x: gcc -x c++ // - http://google.com/search?as_qdr=all&num=100&as_q=mix+c+c%2B%2B #endif #include "uUnit.h" // assertTrue()+assertFalse() #include // malloc() && free() #include // printf() #include // strcpy() strlen() etc. #include // modf() #include // LONG_MAX #if 0 #ifndef __cplusplus // namespace polution ??? #define mnyfmt( a,b,c,d) mnyfmt(a,b,c,d) #define format_money(a,b,c,d) mnyfmt(a,b,c,d) #else #define mnyfmt( a,b,c,d) mnyfmt(a,b,c,d) #define format_money(a,b,c,d) mnyfmt(a,b,c,d) #endif #endif /// Ensure that, at least for this test program [mnyfmtts.c], /// the formatting \c char is digit \c '9'. typedef char mnyfmtts_REQUIRES_mnyfmt_format_char_EQUAL_TO_digit_9 [ (mnyfmt_format_char=='9' ? 1 :-1 ) ]; /// s1 == s2 ??? int eqstr(const char *s1, const char *s2) { #ifndef __cplusplus const int false = 0; const int true = !false; #endif if (s1==0 && s2==0) { return true; } if (s1==0 || s2==0) { return false; } return (strcmp(s1,s2) == 0) ? true : false; } /// Used by 'mnyfmt_wrap()' to check for memory overwrites typedef struct { char *sgn; ///< Returned by mnyfmt() char before [128]; ///< Filler before str[] char str [256]; ///< Format string for mnyfmt() char after [128]; ///< Filler after str[] } FMTSTR; /// Wrapper around 'mnyfmt()' to check that it does not overwrite adyacent memory char* mnyfmt_wrap( char *format, char dec, mnyfmt_long intpart, unsigned CE) { char fill[] = { '!', (char)(0xf0) , 0x0f, 0x8, 2 , 0 }; FMTSTR fmtstr[ (sizeof(fill)/sizeof(*fill)) ]; unsigned i,dim, len; // handle the null pointer as argument case if (!format) { return mnyfmt( (char*)(0), dec, intpart,CE ); } dim = (sizeof(fill)/sizeof(*fill)); len = strlen(format); if (len >= sizeof(fmtstr[0].str) ) { return 0; } for ( i=0; i[%s]\n", #x, x ); } while(0) /// Abreviation to invoke show(fmtstr) #define sh show(fmtstr); /// test ==> mnyfmt() int mnyfmtts( const int argc , const char* argv[] ) { {{ // test.example // (2^128 < 10^40) && (2*40<96) ==> char[96] holds a char *sgn, fmtstr[96],mem[96]; // 128 bit integer unsigned CE, ten_pow_CE; CE = 2; ten_pow_CE = 100; // 10^CE -> "Currency Exponent" strcpy( mem, "USD$ " ); // Picture clause strcpy( fmtstr , "99,999,999.99999" ); if (( sgn = mnyfmt( fmtstr , '.' ,-10245587,CE ) )) { assertTrue( eqstr( fmtstr , "0-,102,455.87000") ); if ( (*sgn=='-') && (','==*(sgn+1)) ) { ++sgn; *sgn='-'; } assertTrue( eqstr( sgn, "-102,455.87000") ); strcat( mem , sgn ); assertTrue( eqstr( mem, "USD$ -102,455.87000") ); } else { assertFalse( "ERROR [???]: " "-102,455.87000" ); } }} {{ // test.neg.comma // (2^128 < 10^40) && (2*40<96) ==> char[96] holds a char *sgn, fmtstr[96]; // 128 bit integer strcpy( fmtstr , "9,999,999.99" ); if (( sgn = mnyfmt( fmtstr , '.' ,-45587,2 ) )) { assertTrue( eqstr( sgn, "-,455.87" ) ); assertTrue( eqstr( fmtstr, "0,00-,455.87" ) ); // handle the "-," problem if ( (*sgn=='-') && (','==*(sgn+1)) ) { ++sgn; *sgn = '-'; // put '-' sign in a nice place } assertTrue( eqstr( sgn, "-455.87" ) ); assertTrue( eqstr( fmtstr, "0,00--455.87" ) ); } }} {{ // test.neg.comma.more char *sgn, fmtstr[mnyfmt_size]; strcpy( fmtstr , "9,999" ); if (( sgn = mnyfmt( fmtstr , '.' ,-2455,0 ) )) { assertFalse( eqstr( sgn, "-2,455" ) ); // another '9' is needed to format! // '-' didn't fit on top of a '9' } else { assertTrue( "5 digits are required to format " "-2,455" ); assertTrue( sgn == (char*)(0) ); } }} {{ // test.-245587 char *sgn, fmtstr[mnyfmt_size]; strcpy( fmtstr , "999,999,999.99" ); if (( sgn = mnyfmt( fmtstr , '.' ,-245587,2 ) )) { assertTrue( eqstr( fmtstr,"000,0-2,455.87" ) ); assertTrue( eqstr( sgn, "-2,455.87" ) ); // handle the "-," problem if ( (*sgn=='-') && (','==*(sgn+1)) ) { ++sgn; *sgn = '-'; // put '-' sign in a nice place } assertTrue( eqstr( sgn, "-2,455.87" ) ); assertTrue( eqstr( fmtstr, "000,0-2,455.87" ) ); assertTrue( fmtstr+5 == sgn ); } }} {{ // test.PITFALL char *sgn, fmtstr[mnyfmt_size], buffer[mnyfmt_size]; strcpy( buffer, "USD$ " ); // Picture clause strcpy( fmtstr , "99,999,999" ); if (( sgn = mnyfmt( fmtstr , '.' ,-102455,87 ) )) { assertFalse( "ERROR [CE should be 0 not " ",87" "]" ); } else { assertTrue( sgn == 0 ); // NULL means mnyfmt() returns ERROR } strcpy( fmtstr , "99,999,999.9999" ); if (( sgn = mnyfmt( fmtstr , '.' ,-1024550077,4 ) )) { assertTrue( eqstr( sgn , "-,102,455.0077" ) ); // handle the "-," problem if ( (*sgn=='-') && (','==*(sgn+1)) ) { ++sgn; *sgn = '-'; // put '-' sign in a nice place } assertTrue( eqstr( sgn , "-102,455.0077" ) ); } }} {{ // test.few.decimals char *sgn, fmtstr[mnyfmt_size]; strcpy( fmtstr , "999,999,999.9999" ); if (( sgn = mnyfmt( fmtstr , '.' , -124550077,2 ) )) { assertTrue( eqstr( sgn , "-1,245,500.7700" ) ); assertFalse( eqstr( sgn , "-102,455.00" ) ); assertFalse( eqstr( sgn , "-102,455.0077" ) ); } }} {{ // test.overwrite typedef struct struct_overwrite { long align; // probably aligned char bytes_8[8]; // 64 bits: probably aligned int int_neg; // -1 usually has all its bits equal to 1 } overwrite; overwrite o = { 0, {'1','2','3','4','5','6','7','\0' }, -1 }; assertTrue( 8-1==strlen(o.bytes_8) && o.int_neg == -1 ); strcpy( o.bytes_8, "1234567.." ); // 2 more bytes... assertTrue( 9==strlen(o.bytes_8) ); assertFalse( o.int_neg == -1 && "Adjacent memory overwritten " ); assertTrue( o.int_neg != -1 ); assertTrue( CHAR_BIT == 8 && "8 bits bytes required" ); }} {{ // test.sgn.ptr char *sgn, fmtstr[mnyfmt_size]; // Picture clause strcpy( fmtstr , "999.999.999,99" ); if (( sgn = mnyfmt( fmtstr , ',', 12345678988,2 ) )) { assertTrue( eqstr( fmtstr , "123.456.789,88" ) ); assertTrue( eqstr( fmtstr , sgn ) && (fmtstr == sgn) ); } strcpy( fmtstr , "999.999.999,99" ); if (( sgn = mnyfmt( fmtstr , ',' , -10245587,2 ) )) { assertTrue( eqstr( fmtstr , "00-.102.455,87" ) ); assertTrue( eqstr( sgn , "-.102.455,87" ) ); if ( (*sgn=='-') && ('.'==*(sgn+1)) ) { ++sgn; *sgn='-'; } assertTrue( eqstr( sgn , "-102.455,87" ) ); } { assertFalse( 0077 == 77 ); // 0077 is an octal literal assertTrue( 0077 == 8*7+7 ); // 0077 == 63 decimal } }} {{ // test.too.small char *sgn, fmtstr[mnyfmt_size]; strcpy( fmtstr , "999.99999" ); if (( sgn = mnyfmt( fmtstr , '.' , 24558700,4 ) )) { // never executed ==> buffer too small // 2455 has 4>3 digits [999.] } assertTrue( sgn == 0 ); assertTrue( eqstr( fmtstr , "999.99999") ); }} {{ // test.parentheses char *sgn, fmtstr[mnyfmt_size], buffer[mnyfmt_size]; strcpy( buffer, "USD$ " ); strcpy( fmtstr , "9,999,999.999" ); if (( sgn = mnyfmt( fmtstr , '.' ,-102455087,3 ) )) { if ( *sgn=='-' ) { // put parentheses around the formatted value if (','==*(sgn+1)) { ++sgn; *sgn='-'; } // skip comma strcat( buffer , "(" ); strcat( buffer , sgn ); strcat( buffer , ")" ); assertTrue( eqstr( buffer, "USD$ (-102,455.087)") ); } else { strcat( buffer , sgn ); } } }} {{ typedef char mnyfmt_size_96_is_enough [ (( (65536.0 * 65536.0 * 65536.0 * 65536.0) < 1.0e20 ) ? 1 :-1 ) ]; mnyfmt_size_96_is_enough ch; assertTrue( 1 == sizeof(ch) ); }} {{ // test.parentheses.no char *sgn, fmtstr[mnyfmt_size], buffer[mnyfmt_size]; strcpy( fmtstr , "9,999,999.999" ); sgn = mnyfmt( fmtstr , '.' ,2455087,3 ); strcpy( buffer, "USD$ " ); if ( sgn!=0 ) { if ( *sgn=='-' ) { // put parentheses around formatted value strcat( buffer , "(" ); strcat( buffer , sgn ); strcat( buffer , ")" ); } else { strcat( buffer , sgn ); assertTrue( eqstr( buffer, "USD$ 2,455.087") ); } } }} {{ // test.asterisks char *sgn, fmtstr[mnyfmt_size]; strcpy( fmtstr , "$9,999,999.999" ); if (( sgn = mnyfmt( fmtstr , '.' , -455870,3 ) )) { if ( (*sgn=='-') && (','==*(sgn+1)) ) { ++sgn; *sgn='-'; } assertTrue( eqstr( sgn , "-455.870") ); for ( --sgn; (sgn!=fmtstr ); --sgn ) { *sgn = '*'; // avoid writing over "$" } assertTrue( eqstr( fmtstr , "$*****-455.870" ) ); } }} {{ // test.modf char *sgn, fmtstr[mnyfmt_size]; double intdouble, fractdouble; long intpart, fracpart; unsigned CE, ten_pow_CE; CE = 5; ten_pow_CE = 100*1000; // 10^CE fractdouble = modf( 2455.87 , &intdouble ); intpart = intdouble; // 2455 fracpart = (unsigned)(fractdouble*ten_pow_CE); // .86000 { assertFalse( fracpart == 87000 && "???"); assertTrue( fracpart == 86999 && "!!!"); // binary rounding... } strcpy( fmtstr , "[[ 999,999.99999 ]]" ); if (( sgn = mnyfmt( fmtstr , '.' , intpart*ten_pow_CE+fracpart,CE ) )) { assertTrue( eqstr( fmtstr , "[[ 002,455.86999 ]]" ) ); assertTrue( eqstr( sgn , "2,455.86999 ]]") ); { // std::round_toward_infinity fracpart = (unsigned)(ceil(fractdouble*100))*1000; strcpy( fmtstr , "[[ 999,999.99999 ]]" ); assertTrue( fracpart == 87000 && "!!!"); if (( sgn = mnyfmt( fmtstr , '.' , intpart*ten_pow_CE+fracpart,5 ) )) { assertTrue( eqstr( sgn, "2,455.87000 ]]") ); } } } }} {{ // test.SCALE #define SCALE(f,CE) ( (mnyfmt_long) ( (f) * 1.0e##CE ) ) // beware of truncation char *sgn, fmtstr[mnyfmt_size]; double val_double = -102455.87; strcpy( fmtstr , "99,999,999.99999" ); if (( sgn = mnyfmt( fmtstr , '.' ,SCALE(val_double,2),2 ) )) { assertTrue( eqstr( fmtstr , "0-,102,455.86000") ); if ( (*sgn=='-') && (','==*(sgn+1)) ) { ++sgn; *sgn='-'; } assertTrue( eqstr( sgn, "-102,455.86000") ); } // rounding and trucations yields .86 instead of .87 else { assertFalse( "ERROR [???]: " "-102,455.86000" ); } }} #undef SCALE {{ // test.0-7.SCALE #define SCALE(f,CE) ( (mnyfmt_long) ( (f) * 1.0e##CE ) ) { assertTrue ( SCALE(1,0) == 1 ); assertTrue ( SCALE(1,1) == 10 ); assertTrue ( SCALE(1,2) == 100 ); assertTrue ( SCALE(1,3) == 1000 ); assertTrue ( SCALE(1,4) == 10000 ); assertTrue ( SCALE(1,5) == 100000 ); assertTrue ( SCALE(1,6) == 1000000 ); assertTrue ( SCALE(1,7) == 10000000 ); } #undef SCALE }} {{ // test.four.decimals char *sgn, fmtstr[mnyfmt_size]; double intdouble, fractdouble; long intpart, fracpart; unsigned CE; fractdouble = modf( 2455.87 , &intdouble ); intpart = intdouble*10000; // 2455 fracpart = (unsigned)(fractdouble*100)*100; // .8600 CE = 4; { assertFalse( fracpart == 8700 && "???"); assertTrue( fracpart == 8600 && "!!!"); // binary rounding... } strcpy( fmtstr , "[[ 999,999.9999 ]]" ); if (( sgn = mnyfmt( fmtstr , '.' , intpart+fracpart,CE ) )) { assertTrue( eqstr( fmtstr , "[[ 002,455.8600 ]]" ) ); assertTrue( eqstr( sgn , "2,455.8600 ]]") ); { // std::round_toward_infinity fracpart = (unsigned)(ceil(fractdouble*100))*100; strcpy( fmtstr , "[[ 999,999.9999 ]]" ); assertTrue( fracpart == 8700 && "!!!"); if (( sgn = mnyfmt( fmtstr , '.' , intpart+fracpart,CE ) )) { assertTrue( eqstr( sgn, "2,455.8700 ]]") ); } } } }} // This works in the Borland C++ 3.1 IDE // Alt-Options -> Compiler -> Code generation... // -> Defines MNYFMT_NO_LONG_LONG // - Borland C++ 3.1 does not support the (long long) integer type {{ // test.limit char *sgn, fmtstr[mnyfmt_size]; #ifndef MNYFMT_NO_LONG_LONG mnyfmt_long max = LONG_LONG_MAX; strcpy( fmtstr , "999,999,999,999,999,999,999" ); // 9,223,372,036,854,775,807 if ( 9223372036854775807LL == LONG_LONG_MAX ) { if (( sgn = mnyfmt( fmtstr , ' ' , max,0 ) )) { assertTrue( eqstr( "9,223,372,036,854,775,807", sgn ) ); } } else { assertFalse( "BEWARE: (long long) is not 8 bytes wide" ); } #endif { mnyfmt_long max = LONG_MAX; strcpy( fmtstr , "999,999,999,999" ); // 2,147,483,647 if ( 2147483647L == LONG_MAX ) { if (( sgn = mnyfmt( fmtstr , ' ' , max,0 ) )) { assertTrue( eqstr( "2,147,483,647", sgn ) ); } } else { assertFalse( "BEWARE: (long) is not 4 bytes wide" ); } } }} {{ // test.fract.zero char *sgn, fmtstr[mnyfmt_size]; // The fraction 643/2136 approximates log10(2) to 7 significant digits. int N = ( ( CHAR_BIT * sizeof(int) - 1 ) * 643 / 2136 ) * (10000*10000); strcpy( fmtstr , "999,999,999,999.999999" ); if (( sgn = mnyfmt( fmtstr , '.', -N,0 ) )) { if ( (*sgn=='-') && (','==*(sgn+1)) ) { ++sgn; *sgn='-'; } assertTrue( eqstr( fmtstr ,"00--900,000,000.000000" ) ); assertTrue( eqstr( sgn , "-900,000,000.000000" ) ); assertFalse( eqstr( fmtstr , "00--455.000000012" ) ); assertFalse( eqstr( sgn , "-455.000000012" ) ); } }} {{ // test.copy.wchar {{ // Convert a char[] into a wchar_t[] char *src, chBuff[128]; wchar_t *dst, *wcBuff; strcpy (chBuff, "Convert me to (wchar_t)"); wcBuff = (wchar_t*)( malloc( sizeof(chBuff)*sizeof(wchar_t) ) ); for ( dst=wcBuff,src=chBuff; (*dst=*src); ++dst,++src ) {} // ... C++ will let you use more sophisticated stuff free(wcBuff); }} { assertTrue( 1==1 ); // Run to cursor } if ( 0 ) { #if defined(__BORLANDC__) && (__BORLANDC__ <= 0x0410) #define wcslen strlen #endif /// Number of letters in array. #define DIM 256 char SRC[DIM], *src; wchar_t DST[DIM], *dst; strcpy( SRC, "Convert me to (wchar_t)"); // strlen()==01234567890123456789012345 for ( dst=DST,src=SRC; (*dst=*src); ++dst,++src ) {} assertTrue( DIM==sizeof(SRC) ); assertTrue( strlen(SRC)==23 ); printf( "sizeof(wchar_t) == %d\n", sizeof(wchar_t) ); printf("%s strlen(SRC)==%d\n", SRC , strlen(SRC) ); printf("%ls wcslen(SRC)==%d\n", DST , wcslen(DST) ); #undef wcslen #undef DIM { unsigned i; for ( i=0 ; i "rupees." } assertTrue( eqstr( sgn , "3 crores 25 lakhs 84,729 rupees 25 paise" )); // Rp3,25,84,729.25 is read as three crore(s), twenty-five lakh(s), // eighty-four thousand, seven hundred and twenty-nine rupees and // twenty-five paise. // - http://en.wikipedia.org/wiki/Indian_rupee#Numeral_system }} #endif {{ // test.times char *sgn, fmtstr[mnyfmt_size]; strcpy( fmtstr , "99/99/9999" ); if (( sgn = mnyfmt( fmtstr , 000, 9272002,0 ) )) { assertTrue( eqstr( fmtstr , "09/27/2002" ) ); assertTrue( eqstr( sgn , "9/27/2002" ) ); } strcpy( fmtstr , "99:99:99" ); if (( sgn = mnyfmt( fmtstr , '?', 21435,0 ))) { assertTrue( eqstr( fmtstr , "02:14:35") ); assertTrue( eqstr( sgn , "2:14:35") ); } }} {{ // test.times.more char *sgn, fmtstr[mnyfmt_size]; strcpy( fmtstr , "99-99-9999" ); if (( sgn = mnyfmt( fmtstr , '*' , 07272002,0 ) )) { // 0... octal assertFalse( eqstr( sgn , "07-27-2002" ) ); assertTrue( eqstr( sgn , "1-93-0242" ) ); assertTrue( eqstr( fmtstr , "01-93-0242" ) ); assertTrue( "BEWARE of octal literal !!!" ); } strcpy( fmtstr , "99-99-9999" ); if (( sgn = mnyfmt( fmtstr , '*' , 27092002,0 ) )) { assertTrue( eqstr( sgn , "27-09-2002" ) ); } strcpy( fmtstr , "99-99-9999" ); if (( sgn = mnyfmt( fmtstr , '*' , 1012002,0 ) )) { assertTrue( eqstr( sgn , "1-01-2002" ) ); assertTrue( eqstr( fmtstr , "01-01-2002" ) ); } strcpy( fmtstr , "999,999,999" ); if (( sgn = mnyfmt( fmtstr , ':' , 27092002,0 ) )) { assertTrue( eqstr( sgn , "27,092,002" ) ); } strcpy( fmtstr , "999,999,999" ); if (( sgn = mnyfmt( fmtstr , '.' , 123456789,0 ) )) { assertTrue( eqstr( sgn , "123,456,789" ) ); } }} #ifndef MNYFMT_NO_LONG_LONG {{ // test.longlongmax char *sgn, fmtstr[mnyfmt_size]; mnyfmt_long max = -LONG_LONG_MAX-1; strcpy( fmtstr , "99,999,999,999,999,999,999" ); // 9,223,372,036,854,775,807 sgn = mnyfmt( fmtstr , ' ' , max,0 ); assertTrue( sgn==0 ); assertTrue( eqstr( "99,999,999,999,999,999,999", fmtstr ) ); }} #else {{ // test.longmax char *sgn, fmtstr[mnyfmt_size]; mnyfmt_long max = -LONG_MAX-1; strcpy( fmtstr , "9,999,999,999" ); // 2,147,483,647 sgn = mnyfmt( fmtstr , ' ' , max,0 ); assertTrue( sgn==0 ); assertTrue( eqstr( "9,999,999,999", fmtstr ) ); assertTrue( sizeof(mnyfmt_long)==sizeof(long) ); }} #endif {{ // test.no.strcpy char *sgn, fmtstr[mnyfmt_size]; strcpy( fmtstr , "9,999." ); if (( sgn = mnyfmt( fmtstr , '.' , 2455,0 ) )) { assertTrue( eqstr( sgn , "2,455." ) ); } if (( sgn = mnyfmt( fmtstr , '.' , 1400,0 ) )) { // never executed: missing strcpy() // no char in "2,455." is a format char } else { assertFalse( eqstr( fmtstr , "1,400." ) ); assertTrue( eqstr( fmtstr , "2,455." ) ); // ??? assertTrue( "BEWARE: missing strcpy()" ); // ??? { strcpy( fmtstr , "9,999." ); sgn = mnyfmt( fmtstr , '.' , 1400,0 ); assertTrue( eqstr( sgn , "1,400." ) ); } } }} {{ // test.dot.comma char *sgn, fmtstr[mnyfmt_size]; strcpy( fmtstr , ".9,999." ); // leading dot sgn = mnyfmt( fmtstr , '.' , 2455,0 ); // with dot '.' assertTrue( sgn == 0 && !sgn ); assertTrue( eqstr( fmtstr , ".9,999." ) ); sgn = mnyfmt( fmtstr , ',' , 2455,0 ); // with comma ',' assertTrue( sgn == 0 && !sgn ); assertTrue( eqstr( fmtstr , ".9,999." ) ); // 2455 has 4 digits ==> it needs '9' format digits before dec.sep strcpy( fmtstr , "9,999" ); sgn = mnyfmt( fmtstr , '.' , 2455,0 ); // with dot '.' assertTrue( sgn && sgn != 0 ); assertTrue( eqstr( fmtstr , "2,455" ) ); sgn = mnyfmt( fmtstr , ',' , 2455,0 ); // with comma ',' assertTrue( sgn == 0 && !sgn ); strcpy( fmtstr , "9" ); sgn = mnyfmt( fmtstr , ',' , 0,0 ); assertTrue( eqstr( fmtstr , "0" ) ); strcpy( fmtstr , "9" ); sgn = mnyfmt( fmtstr , ',' , 9,0 ); assertTrue( eqstr( fmtstr , "9" ) ); }} {{ // test.zero char *sgn, fmtstr[mnyfmt_size]; strcpy( fmtstr , "9.999." ); sgn = mnyfmt( fmtstr , '.' ,-0,0 ); assertTrue( eqstr( fmtstr , "0.000." ) ); assertTrue( eqstr( fmtstr , sgn ) ); strcpy( fmtstr , "9," ); sgn = mnyfmt( fmtstr , ',' ,-0,0 ); assertTrue( eqstr( fmtstr , "0," ) ); strcpy( fmtstr , "," ); sgn = mnyfmt( fmtstr , ',' ,0,0 ); assertTrue( eqstr( fmtstr , "," ) ); strcpy( fmtstr , ",9" ); sgn = mnyfmt( fmtstr , ',' ,0,0 ); assertTrue( eqstr( fmtstr , ",9" ) ); strcpy( fmtstr , "9,9" ); sgn = mnyfmt( fmtstr , ',' ,0,0 ); assertTrue( eqstr( fmtstr , "0,0" ) ); strcpy( fmtstr , "9,9999999" ); sgn = mnyfmt( fmtstr , ',' ,0,0 ); assertTrue( eqstr( fmtstr , "0,0000000" ) ); strcpy( fmtstr , "" ); sgn = mnyfmt( fmtstr , ',' ,1241,2 ); assertTrue( eqstr( fmtstr , "" ) ); strcpy( fmtstr , "0123456" ); assertTrue( eqstr( fmtstr+1 , "123456" ) ); *fmtstr = 0; sgn = mnyfmt( fmtstr , ',' ,1,0 ); assertTrue( eqstr( fmtstr , "" ) ); assertTrue( eqstr( fmtstr+1 , "123456" ) ); }} {{ // test.nines char *sgn, fmtstr[mnyfmt_size]; strcpy( fmtstr , "999,99,999" ); sgn = mnyfmt( fmtstr , '.' , 99999999,0 ); assertTrue( eqstr( sgn , "999,99,999" ) ); strcpy( fmtstr , "999,99,999" ); sgn = mnyfmt( fmtstr , '.' , 88888888,0 ); assertTrue( eqstr( sgn , "888,88,888" ) ); }} {{ // test.no.dec char *sgn, fmtstr[mnyfmt_size]; strcpy( fmtstr , "9,999." ); // Ok: '.' in "9,999." sgn = mnyfmt( fmtstr , '.' , 2455,0 ); assertTrue( eqstr( fmtstr , "2,455." ) ); strcpy( fmtstr , "9.999." ); sgn = mnyfmt( fmtstr , '?' , 2455,0 ); // NO '?' in "9,999." assertTrue( strchr( fmtstr, '?' ) == 0 ); assertTrue( eqstr( fmtstr , "2.455." ) ); assertTrue( eqstr( fmtstr , sgn ) ); }} {{ // test.Banana char *sgn, fmtstr[mnyfmt_size]; // - 24 55 .8 strcpy( fmtstr , "Banana 99 x099-099 32 .9.999." ); if (( sgn = mnyfmt( fmtstr , '.' ,-245587,2 ) )) { assertTrue( eqstr( "Banana 0- x024-055 32 .8.999.", fmtstr ) ); assertTrue( eqstr( "- x024-055 32 .8.999.", sgn ) ); assertFalse( eqstr( "Banana 0- x024-055 32 .7.999.", fmtstr ) ); assertFalse( eqstr( "- x024-055 32 .7.999.", sgn ) ); } }} {{ // test.null.string char *sgn, fmtstr[mnyfmt_size]; // - 24 55 .8 strcpy( fmtstr , "Banana 99 x099-099 32 .9.999." ); strcpy( fmtstr , "" ); assertTrue( ! (* fmtstr) ); assertTrue( eqstr( fmtstr+1, "anana 99 x099-099 32 .9.999." ) ); if (( sgn = mnyfmt( fmtstr , '.' ,-245587,2 ) )) { assertFalse( "NULL string error!!!" ); assertFalse( eqstr( "anana 0- x024-055 32 .8.999.", fmtstr+1 ) ); } else { assertTrue( "Sorry: I forgot to use a non null string" ); } }} {{ // test.null.ptr char *sgn; if (( sgn = mnyfmt( (char*)(0) , '.' ,-245587,2 ) )) { assertFalse( "NULL pointer error!!!" ); } else { assertTrue( "Sorry: I forgot to use a non null pointer" ); } }} {{ // test.mnyfmt.ptr typedef char* (*format_money_type)( char *, char , mnyfmt_long , unsigned ); format_money_type format_money = mnyfmt_wrap; char *sgn, fmtstr[mnyfmt_size]; strcpy( fmtstr , "9,999." ); if (( sgn = format_money( fmtstr , '.' , 245587,2 ) )) { assertTrue( eqstr( fmtstr , "2,455." ) ); assertTrue( eqstr( fmtstr , sgn ) ); } }} {{ // test.modf() ==> double modf( double param, double * intpart ); { // modf() with positive numbers double fractpart, intpart; fractpart = modf( 3.14159265 , &intpart ); assertTrue( intpart == 3.0 ); assertTrue( fabs( fractpart - 0.14159265 ) < pow(10.0,-8.0) ); if ( fractpart == 0.14159265 ) { assertFalse( "NEVER executed due to floating point rounding error" ); // What Every Computer Scientist Should Know About Floating-Point Arithmetic assertTrue( !!! "http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html" ); } } { // modf() with negative numbers // NOTE ==> each part has the same sign as param. double fractpart, intpart; fractpart = modf( -3.14159265 , &intpart ); assertTrue( intpart == -3.0 ); // intpart is negative assertTrue( fractpart < 0.0 ); // fractpart is negative assertTrue( fabs( -fractpart - 0.14159265 ) < pow(10.0,-8.0) ); } }} {{ // test.round double adh_round(double val); /// [Dirty] Trick to force round() to be \c adh_round() #define round adh_round assertTrue( round( 1.7 ) == 2.0 ); assertTrue( round( 1.5 ) == 2.0 ); assertTrue( round( 1.3 ) == 1.0 ); assertTrue( round( -1.3 ) == -1.0 ); assertTrue( round( -1.5 ) == -2.0 ); assertTrue( round( -1.7 ) == -2.0 ); assertTrue( round( 0.1 ) == 0.0 ); assertTrue( round( -0.1 ) == 0.0 ); assertTrue( round( -0.9 ) == -1.0 ); assertTrue( round( 11.7 ) == 12.0 ); assertTrue( round( 11.5 ) == 12.0 ); assertTrue( round( 11.3 ) == 11.0 ); assertTrue( round( -11.3 ) == -11.0 ); assertTrue( round( -11.5 ) == -12.0 ); assertTrue( round( -11.7 ) == -12.0 ); #undef round }} return 0; } void test_str2mnyCE() { {{ // test::07::str2mnyCE() assertTrue( -1024558700 == str2mnyCE(" -102,455.87", '.', 4) ); assertTrue( -102455870 == str2mnyCE(" -102,455.87", '.', 3) ); assertTrue( -10245587 == str2mnyCE(" -102,455.87", '.', 2) ); assertTrue( -1024558 == str2mnyCE(" -102,455.87", '.', 1) ); assertTrue( -102455 == str2mnyCE(" -102,455.87", '.', 0) ); assertTrue( 1024550700 == str2mnyCE(" 102,455.07", '.', 4) ); assertTrue( 102455070 == str2mnyCE(" 102,455.07", '.', 3) ); assertTrue( 10245507 == str2mnyCE(" 102,455.07", '.', 2) ); assertTrue( 1024550 == str2mnyCE(" 102,455.07", '.', 1) ); assertTrue( 102455 == str2mnyCE(" 102,455.07", '.', 0) ); }} {{ // test::str2mnyCE() assertTrue( -1024550700 == str2mnyCE(" -102,455.07", '.', 4) ); assertTrue( -102455070 == str2mnyCE(" -102,455.07", '.', 3) ); assertTrue( -10245507 == str2mnyCE(" -102,455.07", '.', 2) ); assertTrue( -1024550 == str2mnyCE(" -102,455.07", '.', 1) ); assertTrue( -102455 == str2mnyCE(" -102,455.07", '.', 0) ); assertTrue( 1024558700 == str2mnyCE(" 102,455.87", '.', 4) ); assertTrue( 102455870 == str2mnyCE(" 102,455.87", '.', 3) ); assertTrue( 10245587 == str2mnyCE(" 102,455.87", '.', 2) ); assertTrue( 1024558 == str2mnyCE(" 102,455.87", '.', 1) ); assertTrue( 102455 == str2mnyCE(" 102,455.87", '.', 0) ); }} { assertTrue( -1024558700 == str2mnyCE("$ -102,455.87", '.', 4) ); assertTrue( 102455 == str2mnyCE("US$102,455.87", '.', 0) ); assertTrue( 2455 == str2mnyCE(" 2,455.87", '.', 0) ); assertTrue( 2455 == str2mnyCE(" 2,455.87", '.', 0) ); assertTrue( 2455 == str2mnyCE("US$ 2,455 ", '.', 0) ); assertTrue( 2455 == str2mnyCE("US$ 2,455. ", '.', 0) ); assertTrue( 455000 == str2mnyCE("US$ 455. 1", '.', 3) ); assertTrue( 4550000 == str2mnyCE("US$ 455. 2", '.', 4) ); assertTrue( 455000 == str2mnyCE("US$ 455", '.', 3) ); assertTrue( 4550000 == str2mnyCE("US$ 455.", '.', 4) ); assertTrue( 0 == str2mnyCE( ".9",'.', 0) ); assertTrue( 9 == str2mnyCE( ".9",'.', 1) ); assertTrue( 9 == str2mnyCE(".000009",'.',6) ); assertTrue( 4550000 == str2mnyCE("US$ 455", '.', 4) ); assertTrue( 455 == str2mnyCE("US$ 455", '.', 0) ); assertTrue( 0 == str2mnyCE("BANANA",'.', 0) ); assertTrue( 0 == str2mnyCE("BANANA",'.', 4) ); assertTrue( 0 == str2mnyCE("BANANA",'.', 6) ); assertTrue( 0 == str2mnyCE( "",'.', 6) ); assertTrue( 0 == str2mnyCE( "1",'.', 6+1) ); assertTrue( 9 == str2mnyCE( "9",'.', 0) ); assertTrue( 0 == str2mnyCE( ".9",'.', 0) ); assertTrue( 9 == str2mnyCE( ".9",'.', 1) ); assertTrue( 9 == str2mnyCE(".000009",'.',6) ); assertTrue( 9000000 == str2mnyCE("9",'.',6) ); assertTrue( 900000 == str2mnyCE(".9",'.',6) ); assertTrue( 0 == str2mnyCE( "-.9",'.', 0) ); assertTrue( -9 == str2mnyCE( "-.9",'.', 1) ); assertTrue( -9 == str2mnyCE("-.000009",'.',6) ); } { assertTrue( !0 ); // 'Run to cursor' in Code::Blocks } } /// Round to integer, rounding halfway cases away from zero double adh_round(double val) { // unbiased rounding // return ( (val>0.0) ? floor(val+0.5) : ceil( val-0.5) ); return ( (val>0.0) ? floor(val+0.5) : -floor(-val+0.5) ); } /// Main test program int main( const int argc , const char* argv[] ) { printf( "TestCase [mnyfmtts.c]\n" ); assertFalse( 1==2 ); // ok! test_str2mnyCE(); return mnyfmtts(argc , argv); } // EOF: mnyfmtts.c