summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/scanfrac.c
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/CONTRIB/SNIP/scanfrac.c')
-rwxr-xr-xreference/C/CONTRIB/SNIP/scanfrac.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/SNIP/scanfrac.c b/reference/C/CONTRIB/SNIP/scanfrac.c
new file mode 100755
index 0000000..87b623e
--- /dev/null
+++ b/reference/C/CONTRIB/SNIP/scanfrac.c
@@ -0,0 +1,119 @@
+/* function scanfrac - scan an input string for a numeric value.
+**
+** Written in ANSI C and contributed to the public domain by
+** Thad Smith III, Boulder, CO. August 5, 1991
+*/
+
+/*******************************************************************
+** scanfrac() scans an input string for a numeric value, which can
+** be specified as:
+** 1. an integer, 5
+** 2. a floating point value, 5.1
+** 3. a fraction, or 3/4
+** 4. a mixed fraction. 5 3/4 or 5-3/4
+**
+** Conditions:
+** 1. Preceeding whitespace is allowed.
+** 2. The input number may be signed.
+** 3. The fractional part of a mixed fraction (but not pure fraction)
+** must be less than 1.
+** 4. The numerator and denominator of a fraction or mixed fraction
+** must be less than 2^31.
+**
+** Parameters:
+** 1. Input buffer containing value.
+** 2. Pointer to double to receive return value.
+**
+** Return status:
+** 0 = OK, value returned in f,
+** 1 = bad input format,
+** 2 = can't allocate memory
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+int scanfrac (const char buf[], double *f)
+{
+ char *tbuf = malloc (strlen(buf) +2); /* input + terminator */
+ static char term[] = "\a"; /* terminator flag */
+ char t1,t2,t3; /* separator chars */
+ char sign; /* possible sign */
+ int nc; /* # conversions */
+ long int b,c; /* 2nd & 3rd inputs */
+
+ if (!tbuf) /* couldn't allocate memory */
+ return 2;
+
+ /* Copy the input to a temporary buffer and append a terminator
+ ** character. This terminator is used to determine whether the
+ ** scanning of the input field by sscanf() was terminated by end
+ ** of input or by an invalid character. If terminated properly,
+ ** the terminator character picked up in t1, t2, or t3.
+ */
+
+ strcat (strcpy(tbuf, buf), term); /* input + term flag */
+ nc = sscanf (tbuf, " %lf%c %ld %c %ld %c",
+ f,&t1,&b,&t2,&c,&t3);
+ free (tbuf);
+
+ switch (nc) /* number of sscanf() conversions */
+ {
+ case 2: /* single floating value: a */
+ if (t1 == *term) return 0;
+ break;
+ case 4: /* pure fraction: a/b */
+ if (t1 == '/' && t2 == *term && fmod (*f,1.0) == 0.0 && b > 0)
+ {
+ *f /= b;
+ return 0;
+ }
+ break;
+ case 6: /* mixed fraction: a b/c or a-b/c */
+ if ((t1 == ' ' || t1 == '-') && t2 == '/' && t3 == *term &&
+ fmod (*f,1.0) == 0.0 && b >= 0 && c > b)
+ {
+ /* get first non-blank character so that
+ ** -0 b/c will be neg
+ */
+
+#ifdef __ZTC__ /* fix for missing const in sscanf() declaration */
+ sscanf ((char*)buf, " %c", &sign);
+#else
+ sscanf (buf, " %c", &sign);
+#endif
+ if (sign == '-')
+ *f -= (double)b/c;
+ else *f += (double)b/c;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* This is a simple test driver. It should be omitted before
+** placing scanfrac() into a library.
+*/
+
+main ()
+{
+ char buf[80];
+ double f;
+ int stat;
+
+ printf ("Enter 999. or generate EOF to stop\n");
+ do
+ {
+ printf ("Enter value: ");
+ if (! gets (buf))
+ {
+ printf ("EOF detected. Aborting.\n");
+ return 1;
+ }
+ stat = scanfrac (buf, &f);
+ printf ("\nStat = %d, value = %f\n", stat, f);
+ } while ( f != 999.);
+ return 0;
+}