I'm struggling with the following task: write a C program which takes two parameters: input.bin and output.bin.
- input.bin and output.bin are binary files
- input.bin can contain max 65535 uint16_t numbers
- file output.bin must be created by the program and must contain the numbers from input.bin sorted in ascending order
- your program can work with only 256 KB RAM and 2MB disk space
So, I figured out that I can try to do it with counting sort. And here is what I do:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
if(argc != 3)
errx(1, "Usage: %s <input.bin> <output.bin>", argv[0]);
const char * in = argv[1];
char * out = argv[2];
struct stat st;
if(stat(in, &st) == -1)
err(2, "fail to stat file %s", in);
if(st.st_size % sizeof(uint16_t) != 0)
errx(3, "file %s is corrupted", in);
if(st.st_size / sizeof(uint16_t) > 0xffff)
warnx("overflow in file %s may occur", in);
int fd_i = open(in, O_RDONLY);
if(fd_i == -1)
err(4, "error while opening file %s", in);
uint16_t *counting = malloc(0xffff + 1);
if(counting == NULL)
errx(5, "not enough memory");
uint16_t buf[sizeof(uint16_t) * 1024];
ssize_t rd_sz;
while((rd_sz = read(fd_i, &buf, sizeof(buf))) > 0){
for(uint32_t i = 0; i < rd_sz; ++i){
++counting[buf[i]];
}
}
close(fd_i);
ssize_t fd_o = open(out, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP);
if(fd_o == -1){
const int _errno = errno;
close(fd_i);
free(counting);
errno = _errno;
err(6, "error while opening file %s", out);
}
size_t MAX = 0xffff + 1;
size_t pos = 0; // position
uint32_t i = 0;
while(i <= MAX){ // iterate over each number
pos = 0;
// fill the buffer
size_t buf_sz = sizeof(uint16_t) * 1024 - 1;
while(pos < buf_sz && i <= MAX) {
if (counting[i] == 0) {
++i; // move to next number
} else {
buf[pos] = i;
++pos;
--counting[i];
}
}
// write the buffer to the file
ssize_t wr_sz = write(fd_o, buf, pos);
if (wr_sz != (ssize_t)pos) {
err(7, "cannot write %ld bytes to output file", pos);
}
}
close(fd_o);
free(counting);
exit(0);
}
But unfortunately it gives me segmentation fault, and it doesn't work and i cannot figure out why :(