读取文本文件并对两个数组进行排序

Reading text file and sorting two arrays

我有一个包含 200 行的 "Temp.dat",如下所示:

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

我正在尝试使用以下代码读取每一行并将每一列数据存储到单独的数组中:

#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);
}    

当我尝试打印结果时,它给出了 1 13258992,而不是 0.165453 0。我不明白它从哪里得到一对 1 13258992,因为我认为行 fscanf(file, "%d %d", &a, &b) == 2 做了它应该做的事情:遍历文件 Temp.dat 的每一行并读取两个 [=18] =]整数,然后存储在x[MAX]和`y[MAX]两个数组中。因此,有人可以帮我解决这个问题吗?

另一个问题:将上面的两列存储在两个数组x[MAX]y[MAX]之后,我想根据第一个数组中的值对这两个数组进行升序排序x[MAX]。这看起来像:

    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

我如何在 C 中执行此 sorting 例程,因为很难安排 y[MAX] 中的元素以遵循它们在 x[MAX] 中相应元素的顺序?

先在while条件中加上&& m < MAX,这样才不会溢出缓冲区。

scanf 期望 %d 指向 int 而不是 double 的指针,它会将内容解析为整数。 您必须使用 %lf 来解析 double。这同样适用于 printf 调用:

while(fscanf(file, "%lf %lf", &a, &b) == 2 && m < MAX)
    ...

...

printf("%lf %lf\n", x[4], y[1]);

我明白了

0.070850 0.000000

这是你的 dat 文件的第五行(不是第四行,数组索引从 0 开始,而不是 1)。

关于你的另一个问题:

恐怕你必须编写自己的排序函数。

对于初学者尝试:

double a;
int b;

...

fscanf(file, "%f %d", &a, &b)

您将 ab 初始化为双精度类型,但您正在从 copy.dat 文件中读取整数 (%d)。 b 是一个 int 值,所以在 fscanf 中保留 %d 并更改初始化。

你可以用xy来声明一个结构,这样两个值就绑定在一起了,xy在数组元素时会保持它们的关系在排序过程中被交换。示例:

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;
}

%lf 用于 double 值,或将 %f 用于 float ,如其他答案所示

关于比较函数,假设您的数据中有这些值:

0.060493 1
0.060493 5
0.060493 2

在这种情况下,第一个元素的 x 值与另一个元素的 x 值相同。如果您只测试 m->x > n->x,则不会进行排序。所以你想比较 m->y > n->y 如果 x 相同。

qsort 是一个标准的 C 函数。它不知道你的数据类型,我们必须告诉它数据类型。这是在接收指针 ab 的比较函数内部完成的,我们知道这些是指向 data 数组中元素的指针,所以这就是转换背后的原因。

数据集最多可以包含 200 个项目,因为我们将其声明为 struct data_t data[MAX];,其中 MAX200


编辑 3 ******
使用数组,声明数组:

double arr[MAX + 1][8]

请注意,数组的第一个索引是从 0MAX 的行。它是这样设置的,以便以后可以对其进行排序。现在我们可以直接将文件读入数组,并对数组进行排序(不需要结构)。确保不要将其与具有 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;
}