APPFS
Advanced practical programming for scientists
 All Data Structures Files Functions Variables Typedefs Macros
ex1a2.c
Go to the documentation of this file.
1 
12 #include <sys/types.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <stdint.h>
16 #include <stdbool.h>
17 #include <limits.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <string.h>
21 #include <assert.h>
22 
23 #define MAX_NUMS ((INT32_MAX >> 5) + 1)
24 #define BUF_NUMS 4096
25 
26 
31 static inline bool is_little_endian(void)
32 {
33  union { uint32_t u; char c[sizeof(uint32_t)]; } bint = { 0x01020304 };
34 
35  return bint.c[0] == 4;
36 }
37 
43 static inline int32_t reverse_int32(int32_t val)
44 {
45  val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
46 
47  return (val << 16) | ((val >> 16) & 0xFFFF);
48 }
49 
58 int main(int argc, char** argv)
59 {
60  const char* usage = "usage: %s filename\n";
61 
62  /* made static, because otherwise, the stack size might be too small.
63  */
64  static uint32_t have_num[MAX_NUMS];
65 
66  int32_t buf[BUF_NUMS];
67  int fd;
68  int n;
69  int total_nums = 0;
70 
71  /* we assume 32 bit integers, otherwise it will not work
72  */
73  assert(sizeof(int) >= 4);
74 
75  /* Check arguments, we need a filename.
76  */
77  if (argc < 2)
78  {
79  fprintf(stderr, usage, argv[0]);
80  exit(EXIT_FAILURE);
81  }
82  memset(have_num, 0, sizeof(have_num)); // Proably uneccessary
83 
84  /* Open file
85  */
86  if (0 > (fd = open(argv[1], O_RDONLY)))
87  {
88  perror(argv[1]);
89  exit(EXIT_FAILURE);
90  }
91 
92  /* Read from file until data exhausted
93  */
94  while(0 < (n = read(fd, buf, sizeof(buf))))
95  {
96  int nums_read = n / sizeof(buf[0]);
97 
98  assert(nums_read <= BUF_NUMS);
99 
100  total_nums += nums_read;
101 
102  /* Run through buffer of read numbers and set mark bits
103  */
104  for(int i = 0; i < nums_read; i++)
105  {
106  int32_t num = buf[i];
107 
108  if (!is_little_endian())
109  num = reverse_int32(num);
110 
111  // fprintf(stderr, "%d\n", num);
112 
113  /* Check input: really >= 0 ? Otherwise ignore
114  */
115  if (num >= 0)
116  {
117  int idx = num >> 5; // n / 32
118  uint32_t msk = 1 << (num & 31); // bit number n mod 32
119 
120  assert(idx >= 0 && idx < MAX_NUMS);
121 
122  have_num[idx] |= msk;
123  }
124  }
125  }
126  if (close(fd))
127  {
128  perror("close: ");
129  exit(EXIT_FAILURE);
130  }
131  fprintf(stderr, "Total numbers read = %d\n", total_nums);
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  printf("%d\n", (i << 5) + k);
138 
139  return EXIT_SUCCESS;
140 }
static bool is_little_endian(void)
Check if the architecture is little endian.
Definition: ex1a2.c:31
#define BUF_NUMS
read buffer size
Definition: ex1a2.c:24
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: ex1a2.c:58
static int32_t reverse_int32(int32_t val)
Reverse the 4 bytes of an int between little and big endian.
Definition: ex1a2.c:43
NUMS * nums_read(const char *filename)
Read numbers into data structure.
Definition: nums.c:52
#define MAX_NUMS
Maximum number of 32 bit ints we need to store bits.
Definition: ex1a2.c:23