c - 试图找到两个数组之间的最大差异

标签 c

编辑:显然变量dmax不会随着每个循环而更新。

我有 2 个文件被扫描并输入到 2 个单独的数组中,但是当我运行代码来查找 2 个数组的相同元素之间的每日最大差异时,输出达到 107374208.000000。下面是我的代码。

void diff()
{
float ftemp[size], mtemp[size], diff[size], count = 1.0;

feb = fopen("feb.txt", "r");
mar = fopen("mar.txt", "r");

for(i = 1; i < size; i++)
{
    fscanf(feb, "%f", &ftemp[i]);
    fscanf(mar, "%f", &mtemp[i]);

    dmax = (i * 3) - 3;

    if((mtemp[dmax] - ftemp[dmax]) > count && (mtemp[dmax] - ftemp[dmax]) > 0)
    {
        count = mtemp[dmax] - ftemp[dmax];
    }
}

printf("The highest temperature difference between March and February is %f.\n", count);
}

这是二月份的每日气温

maximum     minimum    average
31.6        22.4        25.9
30.2        22.7        25.5
31.2        22.9        26.1
31.3        23.4        26.4
30.7        23.2        26.2
31.3        23.1        26.4
31.6        23.9        26.4
31.6        24.0        26.9
32.7        24.7        27.5
33.8        24.8        27.7
32.4        25.0        27.6
32.1        24.9        27.6
32.7        25.4        27.9
31.9        25.5        27.6
31.9        25.4        27.8
32.1        25.3        27.8
31.7        25.6        27.8
32.6        25.2        27.7
32.2        24.9        27.5
32.2        24.9        27.7
31.7        25.8        27.7
32.3        25.5        27.9
32.1        24.4        27.3
31.5        24.6        27.2
31.8        24.0        27.0 
32.0        24.4        27.4 
32.4        24.9        27.8
32.1        25.0        27.6

这是三月份的每日气温

maximum     minimum    average
32.7        25.1        27.7
33.8        24.8        28.0 
32.9        24.7        27.6
32.9        25.0        27.8
32.9        25.0        27.8
33.0        23.8        27.5
32.6        24.2        27.6
32.8        24.8        27.9
32.0        24.2        27.6
32.3        24.9        27.8
33.6        25.0        28.1
33.4        25.6        28.3
33.8        24.7        28.3
34.1        25.2        28.6
32.7        25.9        28.6
28.2        23.6        25.9
30.7        24.3        26.4
32.7        24.9        27.5
32.5        25.4        27.5
33.6        25.9        27.6
33.1        25.3        27.7
31.0        25.0        27.5
32.8        24.2        27.9
33.0        24.7        28.1
33.2        25.2        28.4
34.0        25.7        28.8
34.4        25.8        29.1
32.7        26.2        28.6
33.3        26.5        28.5
32.3        25.8        28.5
33.0        26.6        28.8    

最佳答案

代码无法编译,因为有一堆未声明的变量,例如 dmaxftemp

修复后...

  1. fopen 未选中。
  2. 假定文件具有一定的大小。
  3. 它的读取远远超出了数组的初始化部分。
  4. fscanf 未检查。
  5. fscanf 是一个错误生成器。

让我们看看您的循环。

for(i = 1; i < size; i++)
{
    fscanf(feb, "%f", &ftemp[i]);
    fscanf(mar, "%f", &mtemp[i]);

    dmax = (i * 3) - 3;

    if((mtemp[dmax] - ftemp[dmax]) > count && (mtemp[dmax] - ftemp[dmax]) > 0)
    {
        count = mtemp[dmax] - ftemp[dmax];
    }
}

第一次迭代后,dmax 将始终大于 i (i = 0, dmax = 0; i = 1, dmax = 3; i = 2, dmax = 6)。但循环只填充到i。因此,当您尝试使用 mtemp[dmax]ftemp[dmax] 时,它们永远不会被填充。你会得到垃圾。

我怀疑您假设 fscanf(feb, "%f", &ftemp[i]) 正在扫描一整行数字。就像您所要求的那样,它只是扫描其中一份。要完成整行,您必须提出要求。

for( int i = 0; i < size; i += 3 ) {
    fscanf(feb, "%f %f %f", &ftemp[i], &ftemp[i+1], &ftemp[i+2]);
    fscanf(mar, "%f %f %f", &mtemp[i], &mtemp[i+1], &mtemp[i+2]);

    ...
}

请注意,循环从 0 开始,因为数组从 0 开始。并且它前进 3,因为我们一次读取 3 个。

<小时/>

这仍然不起作用。文件的第一行都是字符串,而不是 float 。 fscanf 不会向前跳去查找匹配项,如果不匹配,则会停止。如果您继续尝试相同的匹配,它将不断尝试从同一位置一遍又一遍地读取。您的代码所做的就是尝试将每个文件的第一个字节作为 float 读取,失败,然后再次执行 size 次。 ftemp[i]mtemp[i] 仍未初始化,因此您会得到垃圾。

这就是为什么应该避免 scanffscanf 的原因。相反,读取整行并使用 sscanf 处理它们。

数组也是不必要的,您不需要对以前的值执行任何操作,您只需要当前的最小值和最大值。

<小时/>

考虑到所有这些以及其他一些因素,我将其重写如下:

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <math.h>
#include <stdlib.h>

/* A little function to open files while checking it was
   successful and giving a good error message if not */
FILE *open_file( const char *file, const char *mode ) {
    FILE *fp = fopen(file, mode);
    if( fp == NULL ) {
        fprintf(
            stderr,
            "Could not open '%s' for '%s': %s\n",
            file, mode, strerror(errno)
        );
        exit(1);
    }

    return fp;
}

/* Instead of using hard coded file names, they're passed in. */
/* Instead of hard coding the use of the diff, it's returned. */
/* I switched to doubles because that's what fabs() returns and
   the extra accuracy can't hurt. */
double largest_max_temp_diff(const char *file1, const char* file2) {
    FILE *feb = open_file(file1, "r");
    FILE *mar = open_file(file2, "r");

    char line1[1024];
    char line2[1024];

    /* Skip the header lines */
    fgets(line1, 1024, feb);
    fgets(line2, 1024, mar);

    double max_diff = 0;

    /* Loop infinitely, loop exit is handled using `break` */
    while(1) {
        /* Read in a line from each file.
           Stop when we reach the end of either file. */
        if( fgets(line1, 1024, feb) == NULL ) {
            break;
        }
        if( fgets(line2, 1024, mar) == NULL ) {
            break;
        }

        /* Read in just the first column, ignore the rest. */
        /* Make sure the parsing was successful. */
        double max1, max2;
        if( sscanf(line1, "%lf %*lf %*lf", &max1) < 1 ) {
            fprintf( stderr, "Could not understand '%s'", line1);
            continue;
        }
        if( sscanf(line2, "%lf %*lf %*lf", &max2) < 1 ) {
            fprintf( stderr, "Could not understand '%s'", line2);
            continue;
        }            

        /* Compare the diffs as absolute values */
        double diff = max2 - max1;
        if(fabs(diff) > fabs(max_diff)) {
            max_diff = diff;
        }
    }

    /* Return the max diff so it can be used as the caller likes */
    return max_diff;
}

int main() {
    /* Get the diff */
    double diff = largest_max_temp_diff("feb.txt", "mar.txt");

    /* Use it */
    printf("The highest temperature difference between March and February is %f.\n", diff);
}

这个新代码现在会跳过标题行。它读取一行并单独解析它,以保证它不会被卡住。它使用 sscanf 一次解析一行,仅存储最大值。它检查解析是否成功。

它使用绝对值来检查最大差异,因为 -4 的差异大于 3。

最后,它返回该值,以便调用者可以用它做它想做的事情。在同一函数中计算和打印(或任何格式)是一个危险信号;它使函数变得不灵活,并且您最终会编写大量重复代码。

这不是最好的代码,仍然有很多重复,但它更好,并且可以 self 检查。处理文件时,您始终必须检查您的假设。

关于c - 试图找到两个数组之间的最大差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41781293/

相关文章:

c - 我在哪里处理我不拥有的内存? (字符数组)

c - 段错误(核心转储)C 编程

c - 通过参数引用更新C中的全局变量

C - 从最后一行读取文件问题

c - 在 scanf() 中单独输入?

c - 为什么 fgets() 返回指向新填充的 char 数组的指针?

c - C 语言中用于日期验证的库?

c - c 中的字符串作为数组

c - ARM - 为什么 gcc 为单个字符分配 12 个字节?

c - Valgrind新手,似乎不能让它开心