Home > Mobile >  The pointer access representation of the program
The pointer access representation of the program

Time:05-31

The code ran differently than I predicted, I think *(score i*n j) is problematic, it could also be a problem elsewhere, I'm not quite sure, but I don't know how to modify it.

#include  <stdio.h>

#define STUD 30            // Maximum number of students possible
#define COURSE 5           // The maximum number of possible exam subjects

void  Total(int *score, int sum[], float aver[], int m, int n);
void  Print(int *score, int sum[], float aver[], int m, int n);

int main(void)
{
    int i, j, m, n, score[STUD][COURSE], sum[STUD];
    float aver[STUD];
    printf("Enter the total number of students and courses:\n");
    scanf("%d %d",&m,&n);
    printf("Enter score:\n");

    for (i = 0; i < m; i  )
    {
        for (j = 0; j < n; j  )
        {
            scanf("%d", &score[i][j]);
        }
    }

    Total(*score, sum, aver, m, n);
    Print(*score, sum, aver, m, n);
    return 0;
}

void  Total(int *score, int sum[], float aver[], int m, int n)
{
    int  i, j;

    for (i = 0; i < m; i  )
    {
        sum[i] = 0;

        for (j = 0; j < n; j  )
        {
            sum[i] = sum[i]   *(score   i * n   j);
        }

        aver[i] = (float) sum[i] / n;
    }
}

void  Print(int *score, int sum[], float aver[], int m, int n)
{
    int  i, j;
    printf("Result:\n");

    for (i = 0; i < m; i  )
    {
        for (j = 0; j < n; j  )
        {
            printf("M\t", *(score   i * n   j));
        }

        printf("]\t%6.1f\n", sum[i], aver[i]);
    }
}

Example of a program running:

Enter the total number of students and courses:
2 3↙
Enter score:
90↙
95↙
97↙
82↙
73↙
69↙
Result:
  90  95  97  282  94.0
  82  73  69  224  74.7

CodePudding user response:

Compiling your program yields no warnings or errors. Running it with the sample input you've provided yields:

Enter the total number of students and courses:
2 3
Enter score:
90
95
97
82
73
69
Result:
  90      95      97      282     94.0
404780     0      82    404862  134954.0

This is correct for the first set of scores, but not the second. As you intuited, this means your math for accessing the array via pointer math is probably wrong.

Consider what your array actually looks like in memory. You've allocated on the stack an array that looks like:

 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 
|   |   |   |   |   |
 --- --- --- --- --- 

Your example input has filled it like this:

 --- --- --- --- --- 
| 90| 95| 97|   |   |
 --- --- --- --- --- 
| 82| 73| 69|   |   |
 --- --- --- --- --- 
...

If you want to access the first element of the second row, you need your offset to be i * 5 rather than i * 3 which is what happens when you use i * n. This 5 we can get from your constant COURSE.

*(score   i * COURSE   j)

When you use a different offset you get data which has not been initialized, which is why you see garbage values. If you initialize all of the values in your array to 0, but leave your code otherwise unchanged, you can see this in action.

int i, j, m, n, score[STUD][COURSE] = {0}, sum[STUD];
Enter the total number of students and courses:
2 3
Enter score:
90
95
97
82
73
69
Result:
  90      95      97      282     94.0
   0       0      82       82     27.3

CodePudding user response:

As you note, the problem is your array accesses -- you use score[i][j] in main to fill the array and then *(score i * n j) in your Total and Print functions to try to access it, and these are different and incompatible. The easiest fix is probably just to fix the declarations of Total and Print to match the score you are using:

void  Total(int score[][COURSE], int sum[], float aver[], int m, int n);
void  Print(int score[][COURSE], int sum[], float aver[], int m, int n);

Then you can just use score[i][j] in them and everything should work. You would also pass score as just score instead of *score.

Alternately, change the declaration of score to score[STUD*COURSE] and use
*(score i * n j) (or score[i*n j]) in main to access it like you do in Total and Print.

CodePudding user response:

I am not sure why the code uses #defines to define values for rows and columns of the array score, then goes on to use scanf() to enter new values that may or may not conflict with the #defines, or even overflow the array memory. The array, as created is hard coded to use the #define values, so there is no need to use scanf() that I am aware of.

If a dynamic sized array is necessary, then it can be created as a pointer, or pointers to allocated memory, or by use of a VLA

To address your code as is. First, the following creates variables, but does not initialize any of them:

int i, j, m, n, score[STUD][COURSE], sum[STUD];
float aver[STUD];

To eliminate some of the issues you may be seeing, initialize:

int i=0, j=0, m=0, n=0, score[STUD][COURSE]={{0}}, sum[STUD]={0};
float aver[STUD]={0};

In the function prototype in your given code:

Total(int *score, int sum[], float aver[], int m, int n)

int *score

suggests a pointer to a single dimensional array is being passed, but if it is being used to represent score[STUD][COURSE], then it should be passed as `score[m][n], with the prototype changed as:

Total(int m, int n, int score[m][n], int sum[m], float aver[m]);  

Then called as:

Total(STUD, COURSE, int score[STUD][COURSE], int sum[STUD], float aver[STUD]){...} 

Note, this arrangement makes use of VLA type function arguemnts

Note also, an array such as: (shortened from your values for easier viewing)

int m = 5;
int n = 4
int array[m][n] = {{0}}   

creates a single contiguous block of memory, conceivably looking like this in memory:

`|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|...`
 0         5        10         15       20 

Where all of the elements can be accessed in a for loop like this:

for(int i=0; i<m; i  
   for(int j=0;j<n;j  )
       *(array   i*n   j);
   ...
...
  • Related