APPFS
Advanced practical programming for scientists
 All Data Structures Files Functions Variables Typedefs Macros
ex1a3.c
Go to the documentation of this file.
1 
11 #include <sys/types.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <stdint.h>
15 #include <stdbool.h>
16 #include <limits.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <string.h>
20 #include <assert.h>
21 
22 #define MAX_NUMS ((INT32_MAX >> 5) + 1)
23 #define BUF_NUMS 4096
24 
25 
30 static inline bool is_little_endian(void)
31 {
32  union { uint32_t u; char c[sizeof(uint32_t)]; } bint = { 0x01020304 };
33 
34  return bint.c[0] == 4;
35 }
36 
42 static inline int32_t reverse_int32(int32_t val)
43 {
44  val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
45 
46  return (val << 16) | ((val >> 16) & 0xFFFF);
47 }
48 
52 static int store_numbers(
53  const char* filename,
54  uint32_t* have_num,
55  const unsigned int max_nums)
56 {
57  int32_t buf[BUF_NUMS];
58  int fd;
59  int n;
60  int total_nums = 0;
61 
62  assert(NULL != filename);
63  assert(0 < strlen(filename));
64  assert(NULL != have_num);
65  assert(0 < max_nums);
66 
67  /* Open file
68  */
69  if (0 > (fd = open(filename, O_RDONLY)))
70  {
71  perror(filename);
72  return -1;
73  }
74 
75  /* Read from file until data exhausted
76  */
77  while(0 < (n = read(fd, buf, sizeof(buf))))
78  {
79  int nums_read = n / sizeof(buf[0]);
80 
81  assert(nums_read <= BUF_NUMS);
82 
83  total_nums += nums_read;
84 
85  /* Run through buffer of read numbers and set mark bits
86  */
87  for(int i = 0; i < nums_read; i++)
88  {
89  int32_t num = buf[i];
90 
91  if (!is_little_endian())
92  num = reverse_int32(num);
93 
94  // fprintf(stderr, "%d\n", num);
95 
96  /* Check input: really >= 0 ? Otherwise ignore
97  */
98  if (num >= 0)
99  {
100  int idx = num >> 5; // n / 32
101  uint32_t msk = 1 << (num & 31); // bit number n mod 32
102 
103  assert(idx >= 0 && idx < max_nums);
104 
105  have_num[idx] |= msk;
106  }
107  }
108  }
109  /* man close(2):
110  * Not checking the return value of close() is a common but nevertheless serious programming error.
111  * It is quite possible that errors on a previous write(2) operation are first reported at the
112  * final close(). Not checking the return value when closing the file may lead to silent loss of data.
113  * This can especially be observed with NFS and with disk quota.
114  */
115  if (close(fd))
116  {
117  perror("close: ");
118  return -2;
119  }
120  return total_nums;
121 }
122 
125 static void output_numbers(
126  FILE* fp,
127  uint32_t* have_num,
128  const unsigned int max_nums)
129 {
130  assert(NULL != fp);
131  assert(NULL != have_num);
132 
133  for(int i = 0; i < max_nums; i++)
134  if (have_num[i]) // just for speed up
135  for(int k = 0; k < 31; k++)
136  if (have_num[i] & (1 << k))
137  fprintf(fp, "%d\n", (i << 5) + k);
138 }
139 
148 int main(int argc, char** argv)
149 {
150  const char* usage = "usage: %s filename\n";
151 
152  /* made static, because otherwise, the stack size might be too small.
153  */
154  uint32_t* have_num;
155  int total_nums;
156 
157  /* Check arguments, we need a filename.
158  */
159  if (argc < 2)
160  {
161  fprintf(stderr, usage, argv[0]);
162  exit(EXIT_FAILURE);
163  }
164  if (NULL == (have_num = calloc(MAX_NUMS, sizeof(*have_num))))
165  {
166  fprintf(stderr, "calloc of size %lu failed\n", MAX_NUMS * sizeof(*have_num));
167  exit(EXIT_FAILURE);
168  }
169 
170  if (0 > (total_nums = store_numbers(argv[1], have_num, MAX_NUMS)))
171  exit(EXIT_FAILURE);
172 
173  fprintf(stderr, "Total numbers read = %d\n", total_nums);
174 
175  output_numbers(stdout, have_num, MAX_NUMS);
176 
177  free(have_num);
178 
179  return EXIT_SUCCESS;
180 }
static int32_t reverse_int32(int32_t val)
Reverse the 4 bytes of an int between little and big endian.
Definition: ex1a3.c:42
int main(int argc, char **argv)
Program to read a file with binary positive 32 bit integers, sort the numbers and print them sorted...
Definition: ex1a3.c:148
static bool is_little_endian(void)
Check if the architecture is little endian.
Definition: ex1a3.c:30
static void output_numbers(FILE *fp, uint32_t *have_num, const unsigned int max_nums)
Read through the marked bits and print out the numbers in ascending order.
Definition: ex1a3.c:125
static int store_numbers(const char *filename, uint32_t *have_num, const unsigned int max_nums)
Read numbers from file and set bits in provided array.
Definition: ex1a3.c:52
#define MAX_NUMS
Maximum number of 32 bit ints we need to store bits.
Definition: ex1a3.c:22
NUMS * nums_read(const char *filename)
Read numbers into data structure.
Definition: nums.c:52
#define BUF_NUMS
read buffer size
Definition: ex1a3.c:23