I'm trying to create a C program that creates a txt file with random integers, and then mmap
the said file and qsort
it. Creating the txt and mapping goes smoothly, but I can't figure out why qsort
just destroys it. My guess, it's something to do with data types, but even after playing around with them, I get more or less the same result.
compar:
int cmp(const void *p1, const void *p2)
{
return (*(const int *)p1 - *(const int *)p2);
}
mmap and qsort:
char *addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, myFile, 0);
for (int i = 0; i < size; i++)
printf("%c", addr[i]);
qsort(addr, 20, sizeof(char), cmp);
printf("\n-------------\n");
for (int i = 0; i < size; i++)
printf("%c", addr[i]);
output example:
10
19
9
8
18
2
9
6
3
7
15
12
12
14
6
2
4
3
15
13
-------------
296
1
9
93818
1
0
7
15
12
12
14
6
2
4
3
15
13
So 20 random integers are created in txt and mapped with no problems. But I guess qsort
doesn't like what's given to it.
I tried having mmap
as int
, but that created other problems like incorrect numbers in the array and incorrect amount of numbers and some 0s (perhaps I handled the output incorrectly). I'm not exactly sure what I'm doing wrong. here is the full code in case if it's needed:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <time.h>
#include <stdlib.h>
int cmp(const void *p1, const void *p2);
void rand_txt(int size);
int main() {
rand_txt(20);
int myFile = open("rand.txt", O_RDWR);
struct stat myStat = {};
fstat(myFile, &myStat);
off_t size = myStat.st_size;
char *addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, myFile, 0);
for (int i = 0; i < size; i++)
printf("%c", addr[i]);
qsort(addr, 20, sizeof(char), cmp);
printf("\n-------------\n");
for (int i = 0; i < size; i++)
printf("%c", addr[i]);
return 0;
}
int cmp(const void *p1, const void *p2) {
return (*(const int*)p1 - *(const int*)p2);
}
//Function to create a txt with random integers in given size
void rand_txt(int size) {
FILE *fp = fopen("rand.txt", "w");
srand(time(0));
for (int i = 0; i < size; i++)
fprintf(fp, "%d\n", (rand() % size) + 1);
fclose(fp);
}
Also a quickie:
Do the arrays and pointers behave in the same way in practice(like strings)? say we declare:
int *x = { 10, 20, 30, 40 };
can we just fprint("%d\t", x[i]);
or such type of arrays must be declared as int[] = { 10, 20... };
and not with pointers?
(I can and will test it myself and edit the "quickie" out if there is no answer until after I am able to test and study it)
You cannot sort a text file with numbers of different sizes by mapping the file in memory and calling qsort()
with the comparison function for multiple reasons:
qsort
needs an array where all entries have the same size, which is not the case of textual representations.int
, not an array of textual representationsint
, the comparison function would be inappropriate for large absolute values as the subtraction might overflow.To sort the text file, the classic approach is to allocate an array of int
and load the values from the file, converting from text representation to int
values, sort the array with qsort
with an appropriate comparison function, and write the sorted array converting back to string representations.
Here is a comparison function you can use:
int cmp(const void *p1, const void *p2) {
const int *i1 = p1;
const int *i2 = p2;
return (*i1 > *i2) - (*i1 < *i2);
}