在C语言中如何通过引用传递一个二维数组

3
我需要帮助一个作业问题。
作业的描述是:
使用C语言设计程序,采用按引用传递的方法,对一个由M个学生和N个课程测验组成的班级的成绩进行统计,这些课程测验都具有相等的权重,每个测验的得分为10分。当执行程序时,该程序应按照以下顺序执行:
1.要求用户在键盘上输入学生数量M和测验数量N,其中M表示表示二维数组x [M] [N]中的行数,N表示列数。
2.要求用户在键盘上输入数组x [M] [N]的所有元素的值。
3.在控制台上显示输入的数组元素值的M行和N列。
4.生成并在console上显示一个一维数组p [M]的元素,其中该数组的每个元素p [M]代表每个M个学生整个学期的平均成绩。
5.生成并在console上显示一个一维数组q [N]的元素,其中q [N]的每个元素代表N个课程测验中班级中的平均成绩。
6.生成并在console上显示整个学期班级的平均成绩z。
这是我到目前为止完成的代码:
#include <stdio.h>
#define students 300
#define quizzes 20

void averageGradeOfStudents(int M, int N, float p[], float *xPtr);
float averageGradeOfClass();
float averageGradeOfWholeClass();

int main() {
    int M, N;
    float x[students][quizzes];

    printf("Enter the number students (Maximum: 300): ");
    scanf_s("%d", &M);

    printf("\nEnter the number of Quizzes (Maximum: 20): ");
    scanf_s("%d", &N);

    for (int i = 0; i < M; i++) {
        for (int k = 0; k < N; k++) {
    printf("Enter the grade for student %d, Quiz %d: ", i, k);
            scanf_s("%f", &x[i][k]);
        }
    }
    printf("\n--------------------------------------------------------------------------------\n\n");

    for (int k = 1; k <= N; k++) {
        printf("\t\tQuiz%d", k);
    }

    for (int i = 0; i < M; i++) {
        printf("\nStudent%d Grades: ", i);
        for (int k = 0; k < N; k++) {
            printf("%.2f\t\t", x[i][k]);
        }

    }
    printf("\n\n\n--------------------------------------------------------------------------------\n\n");

    float p[students];
    averageGradeOfStudents(M, N, p, &x[0][0]);

    float q[quizzes];

    float z;

    getchar();
    return 0;
}

void averageGradeOfStudents(int M, int N, float p[], float *xPtr) {
    float grade[students];

    for (int i = 0; i < M; i++) {
        for (int k = 0; k < N; k++) {
            grade[i] += *(xPtr + i);
        }
    }

    for (int k = 0; k < M; k++) {
        p[k] = grade[k] / N;
        printf("The average grade of student%d is: %.2f\n\n", k, p[k]);
    }    
}
float averageGradeOfClass() {



}

float averageGradeOfWholeClass() {



}

我遇到的问题是无法找到一种方法来分别对数组中的每一行求和。
4个回答

2

在您知道M和N的值之前,请不要声明数组。因此,main的第一部分应如下所示。(这也允许您转储studentsquizzes常量。)并且始终检查库函数的返回值。

int main( void )
{
    int M, N;

    printf("Enter the number students (Maximum: 300): ");
    if ( scanf_s("%d", &M) != 1 || M > 300 ) {
        printf( "Whatever\n" );
        exit( 1 );
    }

    printf("\nEnter the number of Quizzes (Maximum: 20): ");
    if ( scanf_s("%d", &N) != 1 || N > 20 ) {
        printf( "Sigh...\n" );
        exit( 1 );
    }

    float x[M][N];

    // ...
}

当向函数传递数组时,您可以使用数组表示法。并且允许省略数组的第一个维度。因此,以下两个函数声明都是有效的。

void averageGradeOfStudents(int M, int N, float p[M], float x[M][N]);    
void averageGradeOfStudents(int M, int N, float p[], float x[][N]);

在函数内部存在一些问题

  • grade[i]在使用前未初始化(这应该导致编译器警告)
  • 每个grade[i]应该是N个成绩的平均值(由k而不是i索引)
  • 您实际上不需要grade数组,因为您已经有了p数组

这是我如何编写该函数的代码(我更改了索引名称以保持我的行和列清晰)

void averageGradeOfStudents(int M, int N, float p[], float x[][N])
{
    for (int row = 0; row < M; row++) {
        p[row] = 0;                         // initialize the sum to zero
        for (int col = 0; col < N; col++) {
            p[row] += x[row][col];          // update the sum with each test result
        }
        p[row] /= N;                        // convert the sum to the average
    }

    for (int row = 0; row < M; row++) {
        printf("The average grade of student%d is: %.2f\n\n", row, p[row]);
    }    
}

这个函数应该这样调用:

averageGradeOfStudents(M, N, p, x);

2

你的任务进展非常顺利。看到完整的代码和付出的努力真是让人耳目一新。在我们进行平均值计算之前,有几件事情可以帮助你。首先,这也是良好的实践,初始化你的变量。这对于数组尤其重要,因为它可以防止意外尝试从未初始化的值中读取数据,在字符数组的情况下,还可以自动提供空终止符以便第一次复制到数组(只要你只复制了size-1个字符)。

    int M = 0, N = 0;
    float x[students][quizzes] = {{ 0 }};
    float p[students] = {0};
    float q[quizzes] = {0};
    float z = 0;

传递数组始终是一个问题区域。当传递一个声明为2D数组的数组时,必须将数组的宽度作为函数参数的一部分进行传递:

void averageGradeOfStudents (int M, int N, float p[], float xPtr[][quizzes]);

然后你可以通过传递数组本身来简单地调用该函数。

    averageGradeOfStudents (M, N, p, x);

(注意: 任何数组的第一级间接引用在作为函数参数传递时都会转换为指针,但这是一个后续问题的主题。然而,供您参考,您的函数声明也可以正确地编写为):

void averageGradeOfStudents (int M, int N, float p[], float (*xPtr)[quizzes]);

现在回到您的平均值,您很接近了,只需要通过更改您正在索引的xPtr的方式(并初始化grade的值)来按学生汇总元素即可:

void averageGradeOfStudents (int M, int N, float p[], float xPtr[][quizzes]) 
{
    float grade[M];

    /* initialize variable length array to 0 */
    for (int i = 0; i < M; i++) grade[i] = 0;

    /* sum of grades for each student */
    for (int i = 0; i < M; i++) {
        for (int k = 0; k < N; k++) {
            grade[i] += xPtr[i][k];
        }
    }

    printf ("The average grades for the students are:\n\n");
    for (int k = 0; k < M; k++) {
        p[k] = grade[k] / N;
        printf("  student[%3d] is: %6.2f\n", k, p[k]);
    }    
}

一个简单的完整代码中使用它的示例可以是:

#include <stdio.h>
#define students 300
#define quizzes 20

void averageGradeOfStudents (int M, int N, float p[], float (*xPtr)[quizzes]);

int main (void) {

    /* good habit -- always initialize your variables */
    int M = 0, N = 0;
    float x[students][quizzes] = {{ 0 }};
    float p[students] = {0};

    printf("Enter the number students (Maximum: 300): ");
    scanf ("%d", &M);

    printf("\nEnter the number of Quizzes (Maximum: 20): ");
    scanf ("%d", &N);

    for (int i = 0; i < M; i++) {
        for (int k = 0; k < N; k++) {
            printf("Enter the grade for student %d, Quiz %d: ", i, k);
            scanf("%f", &x[i][k]);
        }
    }
    printf("\n--------------------------------------------------------------------------------\n\n");

    printf ("                        ");
    for (int k = 1; k <= N; k++) {
        printf(" Quiz%-2d", k);
    }
    putchar ('\n');

    for (int i = 0; i < M; i++) {
        printf("\n  Student[%3d] Grades: ", i);
        for (int k = 0; k < N; k++) {
            printf(" %6.2f", x[i][k]);
        }
    }
    printf("\n\n--------------------------------------------------------------------------------\n\n");

    averageGradeOfStudents (M, N, p, x);

    /* getchar(); */
    return 0;
}

void averageGradeOfStudents (int M, int N, float p[], float (*xPtr)[quizzes]) 
{
    float grade[M];

    /* initialize variable length array to 0 */
    for (int i = 0; i < M; i++) grade[i] = 0;

    /* sum of grades for each student */
    for (int i = 0; i < M; i++) {
        for (int k = 0; k < N; k++) {
            grade[i] += xPtr[i][k];
        }
    }

    printf ("The average grades for the students are:\n\n");
    for (int k = 0; k < M; k++) {
        p[k] = grade[k] / N;
        printf("  student[%3d] is: %6.2f\n", k, p[k]);
    }
    putchar ('\n');
}

使用/输出

$ ./bin/studentavg
Enter the number students (Maximum: 300): 3

Enter the number of Quizzes (Maximum: 20): 3
Enter the grade for student 0, Quiz 0: 8
Enter the grade for student 0, Quiz 1: 9
Enter the grade for student 0, Quiz 2: 8
Enter the grade for student 1, Quiz 0: 9
Enter the grade for student 1, Quiz 1: 9
Enter the grade for student 1, Quiz 2: 10
Enter the grade for student 2, Quiz 0: 7
Enter the grade for student 2, Quiz 1: 8
Enter the grade for student 2, Quiz 2: 9

--------------------------------------------------------------------------------

                         Quiz1  Quiz2  Quiz3

  Student[  0] Grades:    8.00   9.00   8.00
  Student[  1] Grades:    9.00   9.00  10.00
  Student[  2] Grades:    7.00   8.00   9.00

--------------------------------------------------------------------------------

The average grades for the students are:

  student[  0] is:   8.33
  student[  1] is:   9.33
  student[  2] is:   8.00

注意: 我已经将scanf_s更改为scanf,以适应我的系统,您需要将其改回。如果您有进一步的问题,请告诉我。


1

对数组求和是一个相当常见的习语:

double sumArray(double arr[], int arrLen)
{
    int i;
    double sum = 0.0;
    for (i = 0; i < arrLen; i++)
        sum += arr[i];

    return sum;
}

这个函数对一维数组求和,但要记住你的数组 x 的每一行都是一个一维数组。

0
int avg=0;
int sum=0;
for (int i = 0; i < M; i++) {
        for (int k = 0; k < N; k++) {
    printf("Enter the grade for student %d, Quiz %d: ", i, k);
            scanf("%f", &x[i][k]);
            sum=sum+x[i][k]
        }
    }avg=sum/M;

如果要得到平均值,你需要先求和...尝试这个方法可能会有帮助


是的,我最初是这样做的;但我必须使用按引用调用的方法。 - Anviori

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接