下标值既不是数组也不是指针函数错误

处理一个程序,该程序将从几个文件中读取数据,将其扫描到数组中,最终在屏幕上打印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等中; 这样它们就可以被平均并存储起来。

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

 void avg( int score[][4], float *average ); 

&average调用中删除&scoresavg

 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_Alignof或一元&运算符的操作数,否则将“N元素数组T ”的表达式转换(“衰减”)为“指向T指针”的表达式。 由于对avg的调用中scores的类型是“ int元素的4元素数组的13元素数组”,因此传递给函数的表达式将具有“指向4元素数组int ”或“ int ”的类型“ int (*)[4]

类似地,表达式“average”的类型将从“13个元素的float数组”转换为“指向float指针”。

&scores的类型是“指向int的4元素数组的13元素数组”或int (*)[14][3] 。 你可以这样做,但是你必须在avg函数中明确地取消引用scores才能下标它,例如

 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.如果要获得小数值,则需要将其中一个操作数设为a浮动:

 average[i] = total / 4.0; 

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

任何时候你发现自己创建了一堆变量,如avg1avg2avg3 ,退后一步,意识到你真正想要的是一个数组。 同样,当你发现自己写的语句时

 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的列scores仍然固定为4.如果您想支持具有任意数量列的分数,那么您将不得不做一些不同的事情。 但是,我们将把它留给未来。

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