I have a "Temp.dat" with 200 lines that looks like this:
0.060493 1 0.5 1
1.596961 0 0.1 2
0.87758 1 0.3 1.5
0.165453 1 0 3
0.07085 1 0.3 4
0.125379 1 0.2 3
0.454202 1 0.2 2
0.373227 1 0.3 1
0.131486 1 0.3 3
0.867477 0 0.5 4
0.122609 0 0.8 9
I am trying to read each line and store each column of data into separate arrays with the following code:
#include <stdio.h>
#include <stdlib.h>
#define MAX 200
int main(){
double x[MAX], y[MAX];
double a, b;
int m = 0;
FILE* file;
file = fopen("Temp.dat", "r");
if ( file != NULL ){
/* Read the two columns. */
while(fscanf(file, "%d %d", &a, &b) == 2)
{ x[m] = a;
y[m] = b;
m++;
}
}
printf("%d %d\n", x[4], y[1]); # Test the stored inputs of the two arrays
return(0);
}
When I tried printing out the result, it gave 1 13258992
, rather than 0.165453 0
. I cannot understand where it got the pair 1 13258992
, as I thought the line fscanf(file, "%d %d", &a, &b) == 2
did what it's supposed to do: go through each row of the file Temp.dat
and read the two double-type
integers, then stored in the two arrays x[MAX]
and `y[MAX]. Therefore, could anyone please help me fix this issue?
Another question: After storing the two columns above in two arrays x[MAX]
and y[MAX]
, I would like to sort the two arrays in an increasing order based on the values in the first array x[MAX]
. This would look like:
0.060493 1
0.07085 1
0.122609 0
0.125379 1
0.131486 1
0.165453 1
0.373227 1
0.454202 1
0.867477 0
How could I do this sorting
routine in C, as it's quite hard to arrange the elements in y[MAX]
to follow the order of their corresponding elements in x[MAX]
?
You can declare a structure with x
and y
, so that the two values are tied together, x
and y
will keep their relation when array elements are swapped during sort. Example:
struct data_t
{
double x;
int y;
};
int compare(const void *a, const void *b)
{
const struct data_t *m = a;
const struct data_t *n = b;
if(m->x == n->x)
return m->y > n->y;
return m->x > n->x;
}
int main(void)
{
struct data_t data[MAX];
FILE* file = fopen("Temp.dat", "r");
int count = 0;
while(fscanf(file, "%lf %d", &data[count].x, &data[count].y) == 2)
{
count++;
if (count == MAX)
break;
}
qsort(data, count, sizeof(struct data_t), compare);
for(int i = 0; i < count; i++)
printf("%lf %d\n", data[i].x, data[i].y);
return 0;
}
Use %lf
for double
values, or use %f
for float
, as shown in the other answers
About the compare function, lets say you have these values in your data:
0.060493 1
0.060493 5
0.060493 2
In this case the x
value from first element is same as x
value from the other element. If you only test for m->x > n->x
then sorting does not occur. So you want to compare m->y > n->y
if x
is the same.
qsort
is a standard C function. It doesn't know your data type, we have to have to tell it about the data type. That's done inside the compare function which receives pointers a
and b
, we know these are pointers to elements in data
array, so that's reason behind the conversion.
The data set can contain up to 200
items since we declared it as struct data_t data[MAX];
where MAX
is 200
.
double arr[MAX + 1][8]
Note that the first index of the array is rows from 0
to MAX
. It's set up this way so it can be sorted later. Now we can read the file directly in to the array, and sort the array (no need for structure). Make sure you don't mix this up with the old solutions which had arr[8][MAX + 1]
int compare_2d_array(const void *pa, const void *pb)
{
double a = *(double*)pa;
double b = *(double*)pb;
return a > b;
}
int main(void)
{
//array with MAX + 1 rows, and 8 columns, initialized to zero
double arr[MAX + 1][8] = { 0 };
FILE* file = fopen("temp.dat", "r");
int count = 0;
while(fscanf(file, "%lf %lf", &arr[count][0], &arr[count][1]) == 2)
{
count++;
if(count == MAX) break;
}
qsort(arr, count, sizeof(arr[0]), compare_2d_array);
//arr[0] and arr[1] are ready, now set up the other columns:
for(int i = 0; i < count; i++)
{
//make modifications to other columns
arr[i][2] = i ? arr[i - 1][0] : 0;
arr[i][3] = arr[i][0];
arr[i + 1][4] = i + 1;
printf("%.6lf %.0lf %.6lf %.6lf %.0lf\n",
arr[i][0], arr[i][1], arr[i][2], arr[i][3], arr[i][4]);
}
return 0;
}