APPFS
Advanced practical programming for scientists
 All Data Structures Files Functions Variables Typedefs Macros
nums.c
Go to the documentation of this file.
1 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <assert.h>
12 
13 #include "nums.h"
14 
15 #define NUM_INC_STORE 100000
16 
19 struct num_store
20 {
21  size_t used;
22  size_t size;
23  int* num;
24 };
25 
28 static int is_valid(const NUMS* nsp)
29 {
30  if (NULL == nsp)
31  return 0;
32  if (0 < nsp->size && NULL == nsp->num)
33  return 0;
34  if (nsp->size < nsp->used)
35  return 0;
36  return 1;
37 }
38 
39 
52 NUMS* nums_read(const char* filename)
53 {
54  assert(NULL != filename);
55  assert(0 < strlen(filename));
56 
57  /* NUMS* np = calloc(1, sizeof(*np));
58  * FILE* fp = fopen(filename, "r") do this even if calloc failed ?
59  */
60  NUMS* nsp = NULL;
61  FILE* fp = stdin;
62  int n;
63 
64  if (NULL == (nsp = calloc(1, sizeof(*nsp))))
65  {
66  perror("calloc");
67  /* problem: out of memory.
68  * do what? quit or return NULL.
69  */
70  return NULL;
71  }
72  if (strcmp(filename, "-"))
73  {
74  if (NULL == (fp = fopen(filename, "r")))
75  {
76  perror(filename);
77 
78  /* and now? Have to free nsp
79  * free(nsp); return NULL;
80  * exchange order with allocation above
81  */
82  goto terminate;
83  }
84  }
85 
86  while(fread(&n, sizeof(n), 1, fp))
87  {
88  /* Check input: really >= 0 ? Otherwise ignore
89  */
90  if (n >= 0)
91  {
92  /* Check if enough storage is allocated
93  */
94  if (nsp->used >= nsp->size)
95  {
96  size_t new_size = nsp->size + NUM_INC_STORE; // * 2 Scales better
97 
98  if (NULL == (nsp->num = realloc(nsp->num, new_size * sizeof(nsp->num[0]))))
99  {
100  perror("realloc"); /* Arrgghhhhhhhh out of mem again */
101  goto terminate;
102  }
103  nsp->size = new_size;
104  }
105  assert(nsp->used < nsp->size);
106 
107  nsp->num[nsp->used] = n;
108  nsp->used++;
109  }
110  }
111  if (!feof(fp))
112  {
113  perror("fread");
114  goto terminate;
115  }
116  if (strcmp(filename, "-"))
117  {
118  if (fclose(fp))
119  {
120  perror("fclose");
121  goto terminate;
122  }
123  }
124  assert(is_valid(nsp));
125 
126  return nsp;
127 
128  terminate:
129  /* But what if we come from feof, then there is no close!
130  */
131  if (nsp->num != NULL)
132  free(nsp->num);
133  if (nsp != NULL)
134  free(nsp);
135 
136  return NULL;
137 }
138 
141 void nums_free(NUMS* nsp)
142 {
143  assert(is_valid(nsp));
144 
145  if (NULL != nsp->num)
146  free(nsp->num);
147 
148  free(nsp);
149 }
150 
153 static int cmp_num(const void *a, const void* b)
154 {
155  assert(NULL != a);
156  assert(NULL != b);
157 
158  const int* aa = a;
159  const int* bb = b;
160 
161  return *aa - *bb;
162 }
163 
166 void nums_print(const NUMS* nsp)
167 {
168  assert(is_valid(nsp));
169 
170  int prev = -1;
171 
172  qsort(nsp->num, nsp->used, sizeof(nsp->num[0]), cmp_num);
173 
174  for(int i = 0; i < nsp->used; i++)
175  {
176  if (nsp->num[i] != prev)
177  {
178  prev = nsp->num[i];
179 
180  printf("%d\n", prev);
181  }
182  }
183 }
184 
187 size_t nums_used(const NUMS* nsp)
188 {
189  assert(is_valid(nsp));
190 
191  return nsp->used;
192 }
Data structure to store numbers.
Definition: nums.c:19
void nums_free(NUMS *nsp)
Free NUMS data structure.
Definition: nums.c:141
static int is_valid(const NUMS *nsp)
Checks if data structure is ok.
Definition: nums.c:28
static int cmp_num(const void *a, const void *b)
Compare two ints.
Definition: nums.c:153
#define NUM_INC_STORE
Definition: nums.c:15
Appfs Exercise 1: Number storage and sorting subroutines.
NUMS * nums_read(const char *filename)
Read numbers into data structure.
Definition: nums.c:52
int * num
storage for numbers
Definition: nums.c:23
size_t used
next free num[]
Definition: nums.c:21
void nums_print(const NUMS *nsp)
Sort and print all numbers in the NUMS structure.
Definition: nums.c:166
size_t nums_used(const NUMS *nsp)
Return count of numbers in NUMS structure.
Definition: nums.c:187
size_t size
max number of entries off num
Definition: nums.c:22