#include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <errno.h> #define MAXL 32 #define NMAX 64 long xstrtol (char *p, char **ep, int base); long *realloc_long (long *lp, unsigned long *n); void prn_stats (long *a, size_t n); int main (void) { long *array = NULL; /* ptr to array of long */ char buffer[MAXL] = {0}; /* buffer for number string */ char *ep = buffer; /* end ptr for strtol */ size_t idx = 0; /* array index / counter */ size_t bidx = 0; /* buffer index / counter */ unsigned long nmax = NMAX; /* reallocation counter */ int c = 0; /* variable for getchar() */ /* allocate array of NMAX long using calloc to initialize to 0 */ if (!(array = calloc (NMAX, sizeof *array))) { fprintf (stderr, "error: memory allocation failed."); return 1; } /* read each value from csv file into array */ while ((c = getchar()) != EOF) { if (c == '-') { /* if sign character */ buffer[bidx++] = c; /* store, read next c */ if ((c = getchar()) == EOF) break; /* if EOF, done */ if (c < '0' || c > '9') /* if c not a digit */ { bidx = 0; continue; } /* reset bidx, continue */ } while (c >= '0' && c <= '9') { /* while c is a digit */ buffer[bidx++] = c; /* add c to buffer */ if ((c = getchar()) == EOF) break; /* read next char */ } if (bidx) { /* if chars in buffer */ buffer[bidx] = 0; /* null-terminate */ array[idx] = xstrtol (buffer, &ep, 10); /* convert to long */ if (errno == 0) idx++; /* if OK, increment idx */ if (idx == nmax) /* check idx == nmax */ array = realloc_long (array, &nmax); /* realloc if required */ bidx = 0; /* reset bidx for next */ } } prn_stats (array, idx); /* output min/max/avg.. */ free (array); /* free allocated mem */ return 0; } /* reallocate array of long values, increase to 2 * '*n'. * returns pointer to newly allocated zeroed block of memory * on success, otherwise program exits. value at 'n' is * updated to reflect the new allocation size. */ long *realloc_long (long *lp, unsigned long *n) { long *tmp = realloc (lp, 2 * *n * sizeof *lp); #ifdef DEBUG printf (" reallocating %lu to %lu\n", *n, *n * 2); #endif if (!tmp) { fprintf (stderr, "%s() error: reallocation failed.\n", __func__); // return NULL; exit (EXIT_FAILURE); } lp = tmp; memset (lp + *n, 0, *n * sizeof *lp); /* memset new ptrs 0 */ *n *= 2; return lp; } /* a simple strtol implementation with error checking. * any failed conversion will cause program exit. Adjust * response to failed conversion as required. */ long xstrtol (char *p, char **ep, int base) { errno = 0; long tmp = strtol (p, ep, base); /* Check for various possible errors */ if ((errno == ERANGE && (tmp == LONG_MIN || tmp == LONG_MAX)) || (errno != 0 && tmp == 0)) { perror ("strtol"); exit (EXIT_FAILURE); } if (*ep == p) { fprintf (stderr, "No digits were found\n"); exit (EXIT_FAILURE); } return tmp; } /* simple output routine for min, max, avg, total and array values * note: the array index output is formatted to 2 places below, * adjust as necessary to meet your needs. */ void prn_stats (long *a, size_t n) { long min = (long)(INT_MAX); long max = (long)(-INT_MAX - 1); long avg = 0; long total = 0; size_t i = 0; /* find min, max, iompute total & average & output */ for (i = 0; i < n; i++) { min = a[i] < min ? a[i] : min; max = a[i] > max ? a[i] : max; total += a[i]; } avg = n > 0 ? total/n : 0; printf("\nvalues : %ld\n", n); printf("minimum : %ld\n", min); printf("maximum : %ld\n", max); printf("total : %ld\n", total); printf("average : %ld\n\n", avg); int sf = n > 50 ? n / 50 : 1; /* scale factor to limit to 50 lines */ for (i = 0; i < n; i+=sf) printf (" a[%2zu] : %ld\n", i, a[i]); printf ("\n"); }