I made text file called qsort.txt and wrote arbitrary many integers in file (In my case 35 integers to be precise). My goal is to count how many integers are in that file, put them into an array defined by malloc()
and sort them using qsort()
. After that I want sorted numbers writen into a text file called sorted.txt.
This is my code, but obviously doesn't work as expected. Also I want to be more flexible with code so in FILE *fa = fopen(argv[1], "r+")
is argv[1]
so I can put any other text file to be sorted. Anyway my problem is that I don't know how to count how many integers are in file.
#include <stdio.h>
#include <stdlib.h>
int compare(const void *a, const void *b) {
if (*(int*)a < *(int*)b)
return -1;
else if (*(int*)a > *(int*)b)
return 1;
else
return 0;
}
int main(int argc, char **argv) {
FILE *fa = fopen(argv[1], "r+");
if (!fa)
exit(1);
FILE *fb = fopen("sortirano.txt", "w+");
long duljina, i;
long *ptr, *zapis;
long count = 0;
while (!feof(fa))
count++;
printf("%lu\n", count);
fseek(fa, 0, SEEK_END);
duljina = ftell(fa);
fseek(fa, 0, SEEK_SET);
ptr = (long *)malloc(sizeof(long));
while (!feof(fa)) {
fscanf(fa, "%lu", ptr);
count++;
}
printf("count: %lu\n", count);
for (i = 0; i < count; i++)
printf("%lu ", ptr[i]);
printf("\n");
free(ptr);
fclose(fa);
fclose(fb);
return 0;
}
EDIT:
This is my new code, which is simpler:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int compare(const void *a, const void *b) {
if (*(long*)a > *(long*)b)
return 1;
if (*(long*)a < *(long*)b)
return -1;
else
return 0;
}
int main() {
FILE *fa = fopen("qsort.txt", "r"); assert(fa != NULL);
FILE *fb = fopen("sorted.txt", "w+"); assert(fa != NULL);
long *ptr;
long save;
long count = 0;
long i;
long k;
while ((fscanf(fa, "%ld", &save)) == 1) //number of elements
prebroji++;
printf("count: %ld\n", count); //checking how many elements i have, just to make sure it works ok
ptr = (long *)malloc(count * sizeof(long)); //mallociranje
for (i = 0; i < count; i++)
fscanf(fa, "%ld", &ptr[i]);
for (i = 0; i < count; i++) //checking if numbers were saved at malloc array
printf("%ld ", ptr[i]);
qsort(ptr, count, sizeof(long), compare);
for (i = 0; i < count; i++) //checking if sorted correctly
printf("%ld ", ptr[i]);
for (i = 0; i < count; i++)
fprintf(fb, "%ld", ptr[i]);
printf("\n");
free(ptr);
fclose(fa);
fclose(fb);
return 0;
}
But it doesn't work: all I got are zeros printed.
Since the file only contains integers and whitespace, you can parse it with fscanf("%ld", ...)
and store the numbers into an array you reallocate on purpose as you read more numbers.
Note these remarks:
Your comparison function is OK for use with qsort
.
There is no need to open the files for update with +
in the mode string,
nor is there any need for seeking to the end of file.
testing for end of file with while(!feof(fa))
is always wrong. You should instead test for fscanf()
success and reallocate the array as needed.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare(const void *aa, const void *bb) {
const long int *a = aa;
const long int *b = bb;
return (*a > *b) - (*a < *b);
}
int main(int argc, char **argv) {
if (argc < 2) {
fprintf(stderr, "missing argument\n");
return 1;
}
FILE *fa = fopen(argv[1], "r");
if (!fa) {
fprintf(stderr, "cannot open %s: %s\n", argv[1], strerror(errno));
return 1;
}
long *ptr = NULL;
size_t alloc = 0, count = 0;
long value;
while (fscanf(fa, "%ld", &value) == 1) {
if (count == alloc) {
size_t new_alloc = alloc + alloc / 2 + 32;
long *new_ptr = realloc(ptr, sizeof(*ptr) * new_alloc);
if (!new_ptr) {
fprintf(stderr, "out of memory for %zu entries\n", new_alloc);
free(ptr);
fclose(fa);
return 1;
}
ptr = new_ptr;
alloc = new_alloc;
}
ptr[count++] = value;
}
fclose(fa);
printf("count: %zu\n", count);
qsort(ptr, count, sizeof(*ptr), compare);
const char *outfile = "sorted.txt";
FILE *fb = fopen(outfile, "w");
if (!fb) {
fprintf(stderr, "cannot open %s: %s\n", outfile, strerror(errno));
free(ptr);
return 1;
}
for (size_t i = 0; i < count; i++) {
fprintf(fb, "%ld\n", ptr[i]);
}
fclose(fb);
free(ptr);
return 0;
}
EDIT:
You new code has multiple problems:
there is no need to open sorted.txt in update mode, just use "w"
.
you should assert(fb)
after opening the second file
prebroji
should be count
you should add assert(ptr)
after you allocate the array
you must add rewind(fa);
after you allocate the array to re-read the file from the beginning. This explains why you get all values as 0
because you do not test the return value of fscanf()
that returns 0
or EOF
for every try.
it is less brittle to write qsort(ptr, count, sizeof(*ptr), compare);
to avoid size inconsistencies if you change the type of the array.
similarly, writing ptr = malloc(count * sizeof(*ptr))
is more reliable as it remains consistent should you change the type of ptr
.
you should add a separator in fprintf(fb, "%ld", ptr[i])
to separate the numbers you write into the output file.