APPFS
Advanced practical programming for scientists
 All Data Structures Files Functions Variables Typedefs Macros
Macros | Functions
ex1a2.c File Reference

Appfs Exercise 1: direct read input, big endian is handled, use of int32_t and uint32_t. More...

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>

Go to the source code of this file.

Macros

#define MAX_NUMS   ((INT32_MAX >> 5) + 1)
 Maximum number of 32 bit ints we need to store bits. More...
 
#define BUF_NUMS   4096
 read buffer size More...
 

Functions

static bool is_little_endian (void)
 Check if the architecture is little endian. More...
 
static int32_t reverse_int32 (int32_t val)
 Reverse the 4 bytes of an int between little and big endian. More...
 
int main (int argc, char **argv)
 Program to read a file with binary positive 32 bit integers, sort the numbers and print them sorted. More...
 

Detailed Description

Author
Thorsten Koch
Date
24Oct2014

gcc -O3 -Wall -std=c99 -o ex1a2 ex1a2.c

Using direct read() for input Improvements to ex1a: big endian is handled, use of int32_t and uint32_t. Adding of static inline.

Definition in file ex1a2.c.

Macro Definition Documentation

#define BUF_NUMS   4096

Definition at line 24 of file ex1a2.c.

#define MAX_NUMS   ((INT32_MAX >> 5) + 1)

Definition at line 23 of file ex1a2.c.

Function Documentation

static bool is_little_endian ( void  )
inlinestatic

This check is constant and can be optimized away by the compiler during compile time. All conditionals depending on it are then decided at compile time

Returns
true if the machine uses little endian, false otherwise.

Definition at line 31 of file ex1a2.c.

32 {
33  union { uint32_t u; char c[sizeof(uint32_t)]; } bint = { 0x01020304 };
34 
35  return bint.c[0] == 4;
36 }
int main ( int  argc,
char **  argv 
)

Actually, the numbers are not sorted. There is an array with one bit for each possible number. Upon reading the respective bit is set for the number recognized. At the end the array is scanned in order and the numbers present are printed.

Parameters
argv[1] name of file to read

Definition at line 58 of file ex1a2.c.

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
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
static int32_t reverse_int32 ( int32_t  val)
inlinestatic

Byte order 1 2 3 4 ist reversed to 4 3 2 1

Parameters
valvalue to be reversed
Returns
reversed value

Definition at line 43 of file ex1a2.c.

44 {
45  val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
46 
47  return (val << 16) | ((val >> 16) & 0xFFFF);
48 }