0

开发一个程序,该程序将从几个文件中读取数据,将其扫描成数组,并最终在屏幕上打印 13 个名称,每个名称旁边有 4 个数字,并且在一种分级表中这些数字后面有一个字母。

但是,我正在使用的功能之一是计算平均值时遇到问题。它将一个学生测试的所有分数组合成一个值,然后将其除以 4 以找到平均值,然后将该平均值存储到不同数组的一个元素中。

函数调用是:

avg(&scores, &average);

分数和平均值定义如下:

int scores[13][4];
float average[13];

并且分数已使用此循环填充:

for(i=0; i<=13; i++)
{
    for(j=0; j<=4; j++)
    {
    fscanf(score, "%d", &scores[i][j]);
    }
}
fclose(score);

作为参考,使用的文件打开语句是:

FILE *student, *score;
score = fopen("scores.dat", "r");

函数本身如下所示:

void avg(int *scores, float *average)
{
int total1 = scores[0][0] + scores[0][1] + scores[0][2] + scores[0][3];
int total2 = scores[1][0] + scores[1][1] + scores[1][2] + scores[1][3];
int total3 = scores[2][0] + scores[2][1] + scores[2][2] + scores[2][3];
int total4 = scores[3][0] + scores[3][1] + scores[3][2] + scores[3][3];
int total5 = scores[4][0] + scores[4][1] + scores[4][2] + scores[4][3];
int total6 = scores[5][0] + scores[5][1] + scores[5][2] + scores[5][3];
int total7 = scores[6][0] + scores[6][1] + scores[6][2] + scores[6][3];
int total8 = scores[7][0] + scores[7][1] + scores[7][2] + scores[7][3];
int total9 = scores[8][0] + scores[8][1] + scores[8][2] + scores[8][3];
int total10 = scores[9][0] + scores[9][1] + scores[9][2] + scores[9][3];
int total11 = scores[10][0] + scores[10][1] + scores[10][2] + scores[10][3];
int total12 = scores[11][0] + scores[11][1] + scores[11][2] + scores[11][3];
int total13=  scores[12][0] + scores[12][1] + scores[12][2] + scores[12][3];

float avg1 = total1 / 4;
float avg2 = total2 / 4;
float avg3 = total3 / 4;
float avg4 = total4 / 4;
float avg5 = total5 / 4;
float avg6 = total6 / 4;
float avg7 = total7 / 4;
float avg8 = total8 / 4;
float avg9 = total9 / 4;
float avg10 = total10 / 4;
float avg11 = total11 / 4;
float avg12 = total12 / 4;
float avg13 = total13 / 4;

return;
}

还没有完成,我还是要告诉函数把 avg1-avg13 分配给数组。但是一旦我修复了这个错误,我就会努力解决这个问题。

尝试按原样运行程序会给我很多错误,所有这些都基本相同:

ghp11.c: In function 'avg':
ghp11.c:127: error: subscripted value is neither array nor pointer

我不确定如何修复它以使其正常工作。我正在尝试将 4 个数组值组合成一个整数值并将其存储在 total1 中,等等;以便它们可以被平均化并存储。

4

3 回答 3

2

删除&from&scores&average调用 to avg

avg( scores, average );

将原型更改avg

void avg( int (*scores)[4], float *average ) // or int scores[][4]

并将身体更改avg

{
  int i = 0;

  for ( i = 0; i < 13; i++ )
  {
    // you could write another loop for summing your total, 
    // but for just 4 elements writing it out isn't a big deal.

    int total = scores[i][0] + scores[i][1] + scores[i][2] + scores[i][3];
    average[i] = total / 4.0;
  }
}

为什么会这样:除非它是 、 或一元运算符的操作数,sizeof_AlignofN&元素数组T”类型的表达式被转换(“衰减”)为“指针指向T”类型的表达式。由于scores调用中的类型avg是“4 元素数组的 13 元素数组int”,因此传递给函数的表达式将具有类型“指向 4 元素数组的指针int”,或者int (*)[4]

同样,表达式“average”的类型将从“13-element array of float”转换为“pointer to float”。

的类型&scores将是“指向 4 元素数组的 13 元素数组的指针int”,或int (*)[14][3]. 您可以这样做,但您必须scoresavg函数中显式取消引用才能为其下标,例如

int total = {*scores)[0][0] + (*scores)[0][1] + ...;

但是,由于我们将它传递为int (*scores)[4],我们可以写

int total = scores[0][0] + scores[0][1] + ...;

因为下标操作scores[0]隐式地取消引用指针。

请注意,在您的代码中,您的平均值最终都会被截断为较低的整数值;一个整数除以一个整数给出一个整数结果,所以像这样的表达式5/4会产生 1,并且3/4会产生 0。如果你想得到一个小数值,你需要将其中一个操作数设为浮点数:

average[i] = total / 4.0;

最后,您不会将结果平均值写入average数组;您只是在创建和分配一堆avg函数本地的变量;一旦函数退出,这些变量就会消失。在上面的代码中,我只是用数组元素替换了你的变量。avgNavgNaverage

任何时候你发现自己创建了一堆变量,比如avg1, avg2, avg3,退后一步,意识到你真正想要的是一个数组。同样,当你发现自己在写这样的陈述时

avg1 = total1 / 4.0;
avg2 = total2 / 4.0;
avg3 = total3 / 4.0;

真正想要的是一个循环:

for ( i = 0; i < N; i++ )
   avg[i] = total[i] / 4.0;

唯一真正剩下的缺陷是该avg函数假定每个数组中总是有 13 个元素,这限制了它的实用性。最好将行数作为单独的参数传递:

void average( int (*scores)[4], int *average, size_t rows )
{
  size_t i;

  for ( i = 0; i < rows; i++ )
  {

    int total = scores[i][0] + scores[i][1] + scores[i][2] + scores[i][3];
    average[i] = total / 4.0;
  }
}

并将其称为

size_t rows = sizeof scores / sizeof scores[0]; // divides the total number of bytes
                                                // in the array by the number of bytes
                                                // in a single element, giving the
                                                // number of elements in the array
avg( scores, average, rows );

当然,其中的列数scores仍然固定为 4。如果您想支持具有任意列数的分数,那么您将不得不做一些不同的事情。但是,我们将把它留到未来。

于 2013-04-22T23:39:29.403 回答
1

要将二维数组传递给函数,您必须像这样编写函数定义

void avg( int score[][4], float *average );
于 2013-04-22T23:04:42.880 回答
1

我注意到的第一件事是你的缓冲区溢出。for i 和 for j 循环溢出一个。

于 2013-04-22T23:05:15.050 回答