The simplest and universally accepted solution is to use the Fisher-Yates algorithm consisting of store all possible numbers, so you have control that they will not be repeated, and only then randomly shuffle these numbers, then pick up the first numbers already properly scrambled.
Simple, complete solution without dependencies:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MIN 1
#define MAX 1000000
#define QTDE 10000 //precisa ser menor que MAX
void shuffle(int *array) {
for (int i = MAX - MIN - 1; i > 0; i--) {
int j = rand() % (i + 1);
int tmp = array[j];
array[j] = array[i];
array[i] = tmp;
}
}
int main(void) {
srand(time(NULL));
int * numeros = malloc((MAX - MIN) * sizeof(int));
if (!numeros) exit(EXIT_FAILURE);
for (int i = 0; i < MAX - MIN; i++) {
numeros[i] = i + MIN;
}
shuffle(numeros);
for (int i = 0; i < QTDE; i++) {
printf("%d\n", numeros[i]);
}
return 0;
}
See working on ideone and on CodingGround . There is an error by limiting ideone.
I believe this form is sufficient, to generate a non-tendentious sequence would complicate a little more, in general the staff works this way on simple things. If you want to insist you could create a function to generate the random numbers, which would consume much more time, something like this:
int rand_int(int n) {
int limit = RAND_MAX - RAND_MAX % n;
int rnd;
do {
rnd = rand();
} while (rnd >= limit);
return rnd % n;
}
But to tell you the truth I do not know if for this volume of numbers that can be drawn and the disproportion that will be used, it pays to do this type of algorithm. It will depend on the need and availability of resources.
I believe that saving to archive is not the problem, I did not put anything.