home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 14 / CD_ASCQ_14_0694.iso / maj / 653 / scanfrac.c < prev    next >
C/C++ Source or Header  |  1994-04-03  |  4KB  |  120 lines

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