home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / SCANFRAC.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  4KB  |  127 lines

  1. /* +++Date last modified: 05-Jul-1997 */
  2.  
  3. /* function scanfrac - scan an input string for a numeric value.
  4. **
  5. ** Written in ANSI C and contributed to the public domain by
  6. ** Thad Smith III, Boulder, CO.     August 5, 1991
  7. */
  8.  
  9. /*******************************************************************
  10. ** scanfrac() scans an input string for a numeric value, which can
  11. ** be specified as:
  12. **  1. an integer,               5
  13. **  2. a floating point value,   5.1
  14. **  3. a fraction, or            3/4
  15. **  4. a mixed fraction.         5 3/4  or  5-3/4
  16. **
  17. ** Conditions:
  18. **  1. Preceding whitespace is allowed.
  19. **  2. The input number may be signed.
  20. **  3. The fractional part of a mixed fraction (but not pure fraction)
  21. **     must be less than 1.
  22. **  4. The numerator and denominator of a fraction or mixed fraction
  23. **     must be less than 2^31.
  24. **
  25. ** Parameters:
  26. **  1. Input buffer containing value.
  27. **  2. Pointer to double to receive return value.
  28. **
  29. ** Return status:
  30. **  0 = OK, value returned in f,
  31. **  1 = bad input format,
  32. **  2 = can't allocate memory
  33. */
  34.  
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <math.h>
  39. #include "snipmath.h"
  40.  
  41. int scanfrac (const char buf[], double *f)
  42. {
  43.       char *tbuf = malloc (strlen(buf) +2);   /* input + terminator     */
  44.       static char term[] = "\a";              /* terminator flag        */
  45.       char t1,t2,t3;                          /* separator chars        */
  46.       char sign;                              /* possible sign          */
  47.       int nc;                                 /* # conversions          */
  48.       long int b,c;                           /* 2nd & 3rd inputs       */
  49.  
  50.       if (!tbuf)                          /* couldn't allocate memory   */
  51.             return 2;
  52.  
  53.       /* Copy the input to a temporary buffer and append a terminator
  54.       ** character.  This terminator is used to determine whether the
  55.       ** scanning of the input field by sscanf() was terminated by end
  56.       ** of input or by an invalid character.  If terminated properly,
  57.       ** the terminator character picked up in t1, t2, or t3.
  58.       */
  59.  
  60.       strcat (strcpy(tbuf, buf), term);       /* input + term flag      */
  61.       nc = sscanf (tbuf, " %lf%c %ld %c %ld %c",
  62.                            f,&t1,&b,&t2,&c,&t3);
  63.       free (tbuf);
  64.  
  65.       switch (nc)                   /* number of sscanf() conversions   */
  66.       {
  67.       case 2:         /* single floating value: a */
  68.             if (t1 == *term) return 0;
  69.             break;
  70.       case 4:         /* pure fraction: a/b */
  71.             if (t1 == '/' && t2 == *term && fmod (*f,1.0) == 0.0 && b > 0)
  72.             {
  73.                   *f /= b;
  74.                   return 0;
  75.             }
  76.             break;
  77.       case 6:         /* mixed fraction: a b/c  or  a-b/c */
  78.             if ((t1 == ' ' || t1 == '-') && t2 == '/' && t3 == *term &&
  79.                   fmod (*f,1.0) == 0.0 && b >= 0 && c > b)
  80.             {
  81.                   /* get first non-blank character so that
  82.                   ** -0 b/c will be neg
  83.                   */
  84.  
  85. #ifdef __ZTC__  /* fix for missing const in sscanf() declaration */
  86.                   sscanf ((char*)buf, " %c", &sign);
  87. #else
  88.                   sscanf (buf, " %c", &sign);
  89. #endif
  90.                   if (sign == '-')
  91.                         *f -= (double)b/c;
  92.                   else  *f += (double)b/c;
  93.                   return 0;
  94.             }
  95.       }
  96.       return 1;
  97. }
  98.  
  99. #ifdef TEST
  100.  
  101. /* This is a simple test driver.  It should be omitted before
  102. ** placing scanfrac() into a library.
  103. */
  104.  
  105. main ()
  106. {
  107.       char buf[80];
  108.       double f;
  109.       int stat;
  110.  
  111.       printf ("Enter 999. or generate EOF to stop\n");
  112.       do
  113.       {
  114.             printf ("Enter value: ");
  115.             if (! gets (buf))
  116.             {
  117.                   printf ("EOF detected. Aborting.\n");
  118.                   return 1;
  119.             }
  120.             stat = scanfrac (buf, &f);
  121.             printf ("\nStat = %d, value = %f\n", stat, f);
  122.       } while ( f != 999.);
  123.       return 0;
  124. }
  125.  
  126. #endif /* TEST */
  127.