home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CSAPE32.ARJ / SOURCE / FUNCS / FNFIXDP.C < prev    next >
C/C++ Source or Header  |  1990-07-18  |  4KB  |  182 lines

  1. /*
  2.       fndecpt.c            6/10/90
  3.  
  4.     % strfixdp
  5.  
  6.     Routines for using fixed decimal points in numeric fields.
  7.  
  8.     C-scape 3.2
  9.     Copyright (c) 1990, by Oakland Group, Inc.
  10.     ALL RIGHTS RESERVED.
  11.  
  12.     Revision History:
  13.     -----------------
  14.      6/10/90 mla    rewrote from scratch
  15.      7/17/90 jmd    minor preening
  16. */
  17.  
  18. #include <stdio.h>
  19. #include <string.h>
  20.  
  21. #include <cscape.h>
  22.  
  23. OSTATIC boolean    is_sn(char *num, char dpc, char **dp, char **end);
  24. OSTATIC char   *strround(char *num, char *fix);
  25.  
  26. char *strfixdp(char *num, int fixdec, int len)
  27. /*
  28.  *    fixes fixdec decimal places in num.  assumes num is a string of digits
  29.  *    with no leading spaces.  maximum amount of storage for num is len.  
  30.  *    if fixdec is zero, num is fixed to a whole number.
  31.  */
  32. {
  33.     char    *dp, *end;
  34.     int        curdec, i;
  35.  
  36.     /*
  37.      *    if num is in scientific notation, do nothing.
  38.      *  else find the decimal point and end.
  39.      */
  40.     if (is_sn(num, ocountry.dec_char, &dp, &end)) {
  41.         return(num);
  42.     }
  43.  
  44.     if (dp == NULL) {
  45.  
  46.         /*  num has no decimal point  */
  47.  
  48.         /*  if storage space is inadequate, clip least significant digits  */
  49.         if (len < (i = strspn(num, "0123456789")) + 1 + fixdec) {
  50.             fixdec = len - i - 1;
  51.         }
  52.  
  53.         if (fixdec == 0) {
  54.             return(num);
  55.         }
  56.  
  57.         /* add enough trailing zeroes */
  58.         *end = ocountry.dec_char;
  59.         for (end++; fixdec > 0; fixdec--, end++) {
  60.              *end = '0';
  61.         }
  62.         *end = '\0';
  63.  
  64.         return(num);
  65.     }
  66.  
  67.     /*  else, num has a decimal point  */
  68.  
  69.     /* if storage space is inadequate, clip least significant digits */
  70.     if (len < (dp - num) + 1 + fixdec) {
  71.         fixdec = len - (dp - num) - 1;
  72.     }
  73.  
  74.     if (fixdec == 0) {
  75.         *dp = '\0';
  76.         return(num);
  77.     }
  78.  
  79.     curdec = end - dp - 1;
  80.  
  81.     if (curdec < fixdec) {
  82.         /*  add some decimal places  */
  83.  
  84.         for (i = (fixdec - curdec); i > 0; i--, end++) {
  85.              *end = '0';
  86.         }
  87.         *end = '\0';
  88.     }
  89.  
  90.     if (curdec > fixdec) {
  91.         /*  remove some decimal places  */
  92.  
  93.         strround(num, (dp + fixdec));
  94.     }
  95.  
  96.  
  97.     /*    if (curdec == fixdec), just return num  */
  98.  
  99.     return(num);
  100. }
  101.  
  102. static boolean is_sn(char *num, char dpc, char **dp, char **end)
  103. /*
  104.  *    Determines if num is in scientific notation by searching for 'E' or 'e'.
  105.  *    only if num is not in scientific notation does it report end of string
  106.  *    and location of decimal point thru extra parameters end and dp.
  107.  */
  108. {
  109.     for (; *num != '\0'; num++) {
  110.  
  111.         if (*num == dpc) {
  112.             *end = num + 1;
  113.             while (**end != '\0') {
  114.  
  115.                 if (otoupper(**end) == 'E') {
  116.  
  117.                     return (TRUE);
  118.                 }
  119.                 (*end)++;
  120.             }
  121.             *dp = num;
  122.             return (FALSE);
  123.         }
  124.  
  125.         if (otoupper(*num) == 'E') {
  126.  
  127.             return (TRUE);
  128.         }
  129.     }
  130.     
  131.     *end = num;
  132.     *dp = NULL;
  133.  
  134.     return (FALSE);
  135. }
  136.             
  137.  
  138. static char *strround(char *num, char *fix)
  139. /*
  140.     Rounds a string image of a floating point number off at location fix.
  141.     The variable space for num is assumed to start at num and end at lease 
  142.     one char after fix.  All checking must be done by caller.
  143.     Num is modified in place and returned.
  144. */
  145. {
  146.     char *s, *c;
  147.  
  148.     if (*(fix + 1) > '4') {  /*  round off?  */
  149.  
  150.         /*  work backwards thru num rounding 9's up to 0's  */
  151.         for (s = fix; s >= num && (*s == '9' || *s == '.'); s--) {
  152.  
  153.             if (*s == '.') {
  154.                 continue;
  155.             }
  156.             *s = '0';
  157.         }
  158.  
  159.         /*  if the high order digit of num was a 9, shift the whole 
  160.             string right one digit to make room to add a 1  */
  161.         if (s < num) {
  162.  
  163.             for (c = fix; c >= s; c--) {
  164.                 *(c + 1) = *c;
  165.             }
  166.  
  167.             *(s + 1) = '1';
  168.         }
  169.  
  170.         /*  otherwise increment the first digit that isn't a 9  */
  171.         else {
  172.  
  173.             *s += 1;
  174.         }
  175.     }
  176.  
  177.     /*  terminate string in either case  */
  178.     *(fix + 1) = '\0';
  179.  
  180.     return (num);
  181. }
  182.