home *** CD-ROM | disk | FTP | other *** search
/ Vectronix 2 / VECTRONIX2.iso / FILES_07 / MARK_WC1.LZH / SRC / PICTURE.C < prev    next >
C/C++ Source or Header  |  1988-04-27  |  8KB  |  277 lines

  1. /*
  2.  * The picture() function is designed to give C users the same
  3.  * numeric formatting ability as COBOL and BASIC users. 
  4.  *
  5.  * When compiled with -DTEST picture.c builds its own test stream.
  6.  * The various options of picture() are illustrated by the test stream
  7.  * in main().
  8.  * Who says self documenting programs are a myth?
  9.  */
  10. #include "stdio.h"
  11. #include "math.h"
  12. extern char *index();
  13. static int dmod10();
  14.  
  15. /* This routine emulates the COBOL picture clause for C programs.
  16.  * picture ( dble, format, output )
  17.  * The dble is the number to be formated.
  18.  * format is a COBOL style picture string
  19.  *     Z stands for zero suppression spaces which
  20.  *      either show numbers or spaces.
  21.  *    9 stands for digit space
  22.  *    $ is a floating dollar sign which lands before the 
  23.  *      first displayed digit.
  24.  *    ( is a floating left paren whic lands before the
  25.  *      first displayed digit if the number is minus.
  26.  *    * signifys * fill and replaces any lead spaces.
  27.  *    anything else within the number is displayed if
  28.  *    the number is already signifigant.
  29.  *    + trailing is displayed if the number is positive
  30.  *      and replaced with a - if the number is minus.
  31.  *    anything else behind the ones position is
  32.  *    only displayed if the number is minus.
  33.  *  output is the output string and will be exactly as long as
  34.  *  format.
  35.  *  picture returns a double which is the undisplayable overfolwed
  36.  *  value. 
  37.  *      picture(12345, "Z,ZZZ", output );
  38.  *        places 2,345 in output and returns a 1.
  39.  */
  40.  
  41. /*
  42.  * Format double precision number. Return any overflow.
  43.  */
  44. double
  45. picture (dble, format, output )
  46. double dble;    /* the number to format */
  47. char  *format;    /* the format mask */
  48. char  *output;    /* the output area. Must be at least as large as format */
  49. {
  50.     register int i, plus = 1;
  51.     register char *outp, tmp;
  52.     double numb = dble;
  53.     char *sig, *j;
  54.  
  55.     if (dble < 0.0) {
  56.         numb = -dble;
  57.         plus = 0;
  58.     } 
  59.  
  60.     if (outp = index(format, '.'))    /* if . in format adjust number */
  61.         for(; *outp != '\000'; outp++)
  62.             switch ( *outp ) {
  63.                 case '9' :
  64.                 case 'Z' :
  65.                 case 'J' :
  66.                 case 'K' :
  67.                 case 'S' :
  68.                 case 'T' :
  69.                     numb *= 10.0;
  70.             }
  71.     modf(numb + 0.5, &numb);    /* round number */
  72.      /* scan backward for slot */
  73.     for(i = strlen(format), output[i--] = '\000'; i >= 0; i--) {
  74.         outp = &output[i];
  75.         switch ( tmp=format[i] ) {
  76.             case '+' :
  77.                 *outp = plus ? '+' : '-';
  78.                 continue;
  79.             case 'T' :
  80.             case 'S' :
  81.             case 'J' :
  82.             case 'K' :
  83.             case '9' :
  84.             case 'Z' :
  85.                 break;
  86.             default:
  87.                 *outp = plus ? ' ' : tmp;
  88.                 continue;
  89.         } /* switch */
  90.         break;
  91.     } /* for */
  92.  
  93.     /* build output string */
  94.     for (sig = output - 1; i >= 0; i--) {
  95.         outp = &output[i];
  96.         switch ( tmp=format[i] ) {
  97.             case '9' :    /* slot for number */
  98.                 *outp = dmod10(&numb);
  99.                 sig = outp - 1;
  100.                 break;
  101.             case 'Z' :    /* lead zero suppress */
  102.                 if (numb >= 1.0) {
  103.                     *outp = dmod10(&numb);
  104.                     sig = outp - 1;
  105.                 }
  106.                 else
  107.                     *outp = ' ';
  108.                 break;
  109.             case 'J' :    /* lead zero shirnk */
  110.                 if (numb >= 1.0) {
  111.                     *outp = dmod10(&numb);
  112.                     sig = outp - 1;
  113.                 }
  114.                 else {
  115.                     sig--;
  116.                     strcpy(outp, (outp + 1));
  117.                 }
  118.                 break;
  119.             case 'K' :    /* all zero shrink */
  120.                 *outp = dmod10(&numb);
  121.                 if ( *outp == '0' ) {
  122.                     sig--;
  123.                     strcpy(outp, (outp + 1));
  124.                 }
  125.                 else
  126.                     sig = outp - 1;
  127.                 break;
  128.             case 'T' :    /* suppress trailing zeros */
  129.                 *outp = dmod10(&numb);
  130.                 if(*outp != '0' || sig >= output )
  131.                     sig = outp - 1;
  132.                 else
  133.                     *outp = ' ';
  134.                 break;
  135.             case 'S' :    /* shrink trailing zeros */
  136.                 *outp = dmod10(&numb);
  137.                 if(*outp != '0' || sig >= output )
  138.                     sig = outp - 1;
  139.                 else
  140.                     strcpy(outp, (outp + 1));
  141.                 break;
  142.             case '$' :    /* floating $ */
  143.                 *outp = ' ';
  144.                 if (sig >= output)
  145.                     *sig-- = '$';
  146.                 break;
  147.             case '-' :    /* floating lead - */
  148.             case '(' :    /* floating lead ( */
  149.                 *outp = ' ';
  150.                 if (sig >= output && !plus )
  151.                     *sig-- = tmp;
  152.                 break;
  153.             case '+' :    /* floating lead + or - */
  154.                 *outp = ' ';
  155.                 if (sig >= output)
  156.                     *sig-- = plus ? '+' : '-';
  157.                 break;
  158.             case '*' :    /* * fill */
  159.                 *outp = '*';
  160.                 for (j = outp+1; *j == ' ';)
  161.                     *j++ = '*';
  162.                 break;
  163.             case '.' :    /* decimal point */
  164.                 *outp = '.';
  165.                 break;
  166.             default :
  167.                 *outp = (numb >= 1.0) ? tmp: ' ';
  168.         }    /* switch */
  169.     }    /* for */
  170.     modf(numb, &numb);
  171.     return (numb >= 1.0) ? (plus ? numb : -numb) : 0.0;
  172. }
  173.  
  174. /*
  175.  * return low order decimal number of argument.
  176.  * divide argument by 10.
  177.  */
  178. static int
  179. dmod10(numb)
  180. register double *numb;
  181. {
  182.     return((int)((modf(*numb / 10.0, numb) * 10.0) + 48.5));
  183. }
  184.  
  185. #ifdef TEST
  186. static int    test_no;
  187.  
  188. /*
  189.  * Run picture and check the results.
  190.  */
  191. verify(mask, number, expect, oflow, descr)
  192. char *mask;    /* format mask for picturre */
  193. double number;    /* number to format */
  194. char *expect;    /* expected result of format */
  195. double oflow;    /* expected overflow */
  196. char *descr;    /* description */
  197. {
  198.     char   result[20];
  199.     double ret;
  200.  
  201.     test_no++;
  202.     if(descr != NULL)
  203.         printf("\n%s\n", descr);
  204.     printf("%10.3f passed through a mask of '%s' gives '%s'\n",
  205.         number, mask, expect);
  206.     if((int)oflow)
  207.         printf("    With an overflow of %-3.1f\n", oflow);
  208.     ret = picture(number, mask, result);
  209.     if((int)(ret - oflow))
  210.         printf("Expected oflow\t%e\ngot\t\t%e\ttest %d\n",
  211.             oflow, ret, test_no);
  212.     if(strcmp(result, expect))
  213.         printf("Expected\t'%s'\ngot\t\t'%s'\ttest %d\n",
  214.             expect, result, test_no);
  215. }
  216.  
  217. main()
  218. {
  219.    printf("The picture() function is designed to give C users the same\n");
  220.    printf("numeric formatting ability as COBOL and BASIC users. \n\n");
  221.    printf("double\n");
  222.    printf("picture (dble, format, output )\n");
  223.    printf("double dble;    /* the number to format */\n");
  224.    printf("char  *format;  /* the format mask */\n");
  225.    printf("char  *output;  /* the output area. Must be at least as large as format */\n");
  226.  
  227.     verify("999 CR",       5.0,    "005   ",    0.0,
  228.       "9    Provides a slot for a number.");
  229.     verify("999 CR",      -5.0,    "005 CR",    0.0, NULL);
  230.    printf(" Note: C & R are not special to picture. Trailing non special\n");
  231.    printf("       characters print only if the number is negitave\n");
  232.  
  233.     verify("ZZZ,ZZZ",    1034.0,    "  1,034",    0.0,
  234.       "Z    Provides a slot for a number but supresses lead zeros.");
  235.    printf(" Note: comma is not special to picture. Imbeded non special\n");
  236.    printf("       characters print only if preceeded by significant digits\n");
  237.     verify("JJJ,JJJ",    1034.0,    "1,034",    0.0,
  238.       "J    Provides a slot for a number but shrinks out lead zeros.");
  239.  
  240.     verify("K9/K9/K9",     70884.0,    "7/8/84",    0.0,
  241.       "K    Provides a slot for a number but shrinks out any zeros.");
  242.  
  243.     verify("$ZZZ,ZZZ",    105.0,    "    $105",    0.0,
  244.        "$    Floats a dollar sign to the front of the displayed number.");
  245.  
  246.     verify("Z,ZZZ.999",    105.67,    "  105.670",    0.0,
  247.        ".    Separates the number between decimal and integer portions.");
  248.  
  249.     verify("Z,ZZ9.9TT",    105.67,    "  105.67 ",    0.0,
  250.        "T    Provides a slot for a number but supresses trailing zeros.");
  251.  
  252.     verify("Z,ZZ9.9SS",    105.67,    "  105.67",    0.0,
  253.        "S    Provides a slot for a number but shrinks out trailing zeros.");
  254.  
  255.     verify("-Z,ZZZ",    105.0,    "   105",    0.0,
  256.        "-    Floats a - infront of negitive numbers");
  257.     verify("-Z,ZZZ",       -105.0,    "  -105",    0.0, NULL);
  258.  
  259.     verify("(ZZZ)",        105.0,    " 105 ",    0.0,
  260.         "(    Acts like - but prints a (");
  261.     verify("(ZZZ)",         -5.0,    "  (5)",    0.0, NULL);
  262.  
  263.     verify("+ZZZ",          5.0,    "  +5",        0.0,
  264.        "+    Floats a + or - infront of the number depending on its sign");
  265.     verify("+ZZZ",         -5.0,    "  -5",        0.0, NULL);
  266.  
  267.     verify("*ZZZ,ZZZ.99",    104.10,    "*****104.10",    0.0,
  268.        "*    Fills all lead spaces to its right");
  269.     verify("*$ZZZ,ZZZ.99",    104.10,    "*****$104.10",    0.0, NULL);
  270.  
  271.     verify("(ZZZ)",          -1234.0,    "(234)",       -1.0,
  272.        "Any overflow is returned by picture as a double precision number.");
  273.     verify("99",        123.4,    "23",        1.0, NULL);
  274.     verify("ZZ",           1200.0,    "00",           12.0, NULL);
  275. }
  276. #endif
  277.