Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* Read file or stdin into a dynamically allocated 2D array
- filename is expected as 1st argument, otherwise read from stdin.
- initial allocation of ROWS pointers to array of COLS long,
- rows and columns are reallocated as needed. an equal number of
- colums is enforced. conversion from string to long is provided
- by strtol. input file format is flexible. all values within a
- line are considered in the same row. all separators and
- delimiters are ignored.
- */
- #include <stdio.h>
- #include <stdlib.h> /* for strtol */
- #include <string.h> /* for memset */
- #include <limits.h> /* for INT_MIN/INT_MAX */
- #include <errno.h> /* for errno */
- #define ROWS 128 /* max number of rows in array */
- #define COLS 32 /* max number of cols in array */
- void *xcalloc (size_t n, size_t s);
- void *xrealloc (void *ptr, size_t psz, size_t *nelem);
- int main (int argc, char **argv)
- {
- long **array = NULL;
- char *ln = NULL;
- size_t n, row, nrows, col, ncols, rmax = ROWS;
- FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
- n = row = nrows = col = ncols = 0;
- if (!fp) { /* validate file open */
- fprintf (stderr, "error: file open failen '%s'.\n", argv[1]);
- return 1;
- }
- /* allocate ROWS pointers initially */
- array = xcalloc (ROWS, sizeof *array);
- /* read each line in file */
- while (getline (&ln, &n, fp) != -1) {
- char *p = ln; /* p & ep -- pointers for strtol */
- char *ep = p;
- size_t cmax = COLS;
- col = errno = 0;
- /* allocate COLS number of int for each row */
- array[row] = xcalloc (COLS, sizeof **array);
- /* convert each string of digits into number */
- while (errno == 0) {
- /* skip any non-digit characters */
- while (*p && ((*p != '-' && (*p < '0' || *p > '9')) ||
- (*p == '-' && (*(p+1) < '0' || *(p+1) > '9')))) p++;
- if (!*p) break;
- /* convert string to number */
- array[row][col++] = strtol (p, &ep, 10);
- if (errno) break; /* check for error - covers all strtol err */
- if (col == cmax) /* check if column full */
- array[row] = xrealloc (array[row], sizeof *array[row], &cmax);
- /* skip delimiters/move pointer to next digit */
- while (*ep && *ep != '-' && (*ep < '0' || *ep > '9')) ep++;
- if (*ep)
- p = ep;
- else /* break if end of string */
- break;
- }
- if (row == 0) /* set number of columns in file on 1st row */
- ncols = col;
- if (col != ncols) { /* if columns not equal, throw error */
- fprintf (stderr, "error: invalid number of columns, row '%zu'.\n",
- nrows);
- exit (EXIT_FAILURE);
- }
- if (++row == rmax) /* increment row, check against ROWS */
- array = xrealloc (array, sizeof *array, &rmax);
- }
- nrows = row; /* set final numer of rows */
- free (ln); /* free mem allocated by getline */
- if (fp != stdin) fclose (fp); /* close file if not default stdin */
- printf ("\narray read from '%s'\n\n", argc > 1 ? argv[1] : "stdin");
- for (row = 0; row < nrows; row++)
- {
- printf (" [");
- for (col = 0; col < ncols; col++)
- {
- printf (" %3ld", array[row][col]);
- }
- printf (" ]\n");
- }
- for (row = 0; row < nrows; row++) /* free allocated memory */
- free (array[row]);
- free (array);
- return 0;
- }
- /** xcalloc allocates memory using calloc and validates the return.
- * xcalloc allocates memory and reports an error if the value is
- * null, returning a memory address only if the value is nonzero
- * freeing the caller of validating within the body of code.
- */
- void *xcalloc (size_t n, size_t s)
- {
- register void *memptr = calloc (n, s);
- if (memptr == 0) {
- fprintf (stderr, "xcalloc() error: virtual memory exhausted.\n");
- exit (EXIT_FAILURE);
- }
- return memptr;
- }
- /** realloc 'ptr' of 'nelem' of 'psz' to 'nelem * 2' of 'psz'.
- * returns pointer to reallocated block of memory with new
- * memory initialized to 0/NULL. return must be assigned to
- * original pointer in caller.
- */
- void *xrealloc (void *ptr, size_t psz, size_t *nelem)
- {
- void *memptr = realloc ((char *)ptr, *nelem * 2 * psz);
- if (!memptr) {
- fprintf (stderr, "realloc() error: virtual memory exhausted.\n");
- exit (EXIT_FAILURE);
- } /* zero new memory (optional) */
- memset ((char *)memptr + *nelem * psz, 0, *nelem * psz);
- *nelem *= 2;
- return memptr;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement