Solved

Help with arrays of pointers to functions!!!

Posted on 2003-11-09
39
536 Views
Last Modified: 2010-04-01
Hello all!  I have been working on this work a few days now and can't seem to get the exact answer I am looking for.  Maybe someone here can help me out.  What I am trying to do is this: I am trying to get all the pointers to have the same type.  The pointers must be to functions of the same return type that receive arguments of the same type. The minimum and maximum functions  print only the minimum and maximum and don't return anything.  The average should return nothingand take the same parameters as printArray, minimum, and maximum.  The pointers of the four functions should be stored in array processGrades and use the choice made by the user as teh subscript into the array for calling each function.  Please HELP me!! Thank you.
Here is my code so far:

#include <iostream>

using std::fixed;
using std::endl;
using std::cout;
using std::left;
using std::cin;

#include <iomanip>

using std::setw;
using std::setprecision;

const int students = 3;
const int exams = 4;

void minimum (int [] [exams], int, int);
void maximum (int [] [exams], int, int);
double average (int [], int);
void printArray (int [] [exams], int, int);

int main()
{
      int choice = 0;
      int studentGrades [students][exams] =
      {{77, 68, 86, 73},
      {96, 87, 89, 78},
      {70, 90, 86, 81}};
while (choice != 4){
      cout << "\nEnter a choice:" << endl;
      cout << " 0  Print the array of grades" << endl;
      cout << " 1  Find the minimum grade" << endl;
      cout << " 2  Find the maximim grade" << endl;
      cout << " 3  Print the average on all tests for each student" << endl;
      cout << " 4  End program" << endl;
      cout << "? ";
      cin >> choice;
      
      if (choice == 4) break;
      if (choice == 0){
            cout << "The is ";
            printArray (studentGrades, students, exams);      }
      if (choice == 1){
      cout << "\n\tThe lowest grade is ";
             minimum(studentGrades, students, exams);}
      if (choice == 2){
      cout << "\n\tThe highest grade is ";
             maximum(studentGrades, students, exams);}
      if (choice == 3){
      cout << fixed << setprecision(2);
      for (int person = 0; person < students; person++)
            cout << "\n\tThe average for student " << person << " is ";
          average (studentGrades[person], exams);}
}
return 0;
}


void minimum (int grades[][exams], int pupils, int tests)
{
      int lowGrade = 100;
      for (int i = 0; i < pupils; i++)
            for (int j = 0; j < tests; j++)
                  if (grades[i][j] < lowGrade)
                        lowGrade = grades[i][j];
      cout << lowGrade << endl;
}
void maximum (int grades[][exams], int pupils, int tests)
{
      int highGrade = 0;
      for (int i = 0; i < pupils; i++)
            for (int j = 0; j < pupils; j++)
                  if (grades[i][j] > highGrade)
                        highGrade = grades[i][j];
      cout << highGrade << endl;
}

double average (int setOfGrades[], int tests)
{
      int total = 0;
      for (int i = 0; i < tests; i++)
            total += setOfGrades[i];
      cout << static_cast<double>(total) / tests << endl;
      
}

void printArray (int grades[] [exams], int pupils, int tests)
{
      cout << left << "            [0]  [1]  [2]  [3]";

      for (int i = 0; i < pupils; i++){
            cout << "\nstudentGrades[" << i << "]";

      for (int j = 0; i < tests; j++)
            cout << setw(5) << grades[i][j];
      }
}
0
Comment
Question by:marcypark
  • 16
  • 10
  • 8
  • +1
39 Comments
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 9712271
Declare an array of pointers something like

void ( * processGrades[4] ) (int grades[][], int, int ) ;

The above declaration says that procesGrades is an array (of size 4) of pointers to functions which return void and take 3 parameters - a 2-dimensional int array, int, int

Now, before your while loop, let the array locations point to your functions by saying


processGrades [0] = printArray ;
processGrades [1] = minimum;
processGrades [2] = maximum ;
processGrades [3] = average ;


Altenatively, you can also use the following statements to do the same
processGrades [0] = &printArray ;
processGrades [1] = &minimum;
processGrades [2] = &maximum ;
processGrades [3] = &average ;


Now in your while loop, after accepting the user's choice, just call the respctive function in the respcetive array locations as below

( * processGrades[choice] ) (studentGrades, students, exams) ;















0
 
LVL 15

Expert Comment

by:efn
ID: 9712479
Sys_Prog gave you most of the answer.

void ( * processGrades[4] ) (int grades[][], int, int ) ;

The declaration of the grades parameter in this shouldn't compile.  It should be

void ( * processGrades[4] ) (int grades[][exams], int, int ) ;

You will also, of course, have to change the average function so it matches the others.

--efn
0
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 9712501
Hi efn

My Function Pointer declaration does compile

Actually what u said is related to while declaring a function with multi-dimension array argument

When u are passing multi-dimension araay, u can omit the size of ONLY THE FIRST dimension. the size of rest all dimensions need to be given

But this is NOT TRUE when u are declaring a pointer to that function. Your function pointer need not mention the size of any of the array dimensions.



0
 
LVL 15

Expert Comment

by:efn
ID: 9712768
Hi Sys_Prog,

I couldn't find a definitive ruling on this in the standard, but Microsoft Visual C++ 6.0, Borland C++Builder 4, and gcc 3.2 all rejected the line.

VC++:

error C2087: '<Unknown>' : missing subscript

BCB:

E2453 Size of the type 'int[]' is unknown or zero.

gcc:

declaration of `grades' as multidimensional array must have bounds

The message from gcc appeared to be labeled as a warning, but was severe enough to keep the program from linking.  This was with dev-c++.

So what compiler do you use that compiles this?

--efn
0
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 9712783
I am using a GNU compiler  -  mingw32 and it works fine with this



0
 
LVL 15

Expert Comment

by:efn
ID: 9712806
So I guess what we can say to marcypark is:  If your compiler complains about the function pointer array declaration, try specifying the second array bound.

--efn
0
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 9712817
Yes, I guess that would be a better option

Thanks for your input  efn.

Amit
0
 
LVL 30

Expert Comment

by:Axter
ID: 9714024
Sys_Prog,

I'm not sure how you were able to compile that since in addition, it also has an extra variable name that doesn't belong there.

void ( * processGrades[4] ) (int grades[][], int, int ) ; //This should not compile

void ( * processGrades[4] ) (int [][exams], int, int ) ; // This is good


You can declare and initialize it at the same time via following method:

void ( * processGrades[4] ) (int [][exams], int, int ) = {minimum, maximum, printArray} ;

Before you can use the average function in this declaration, you need to change the return type and the arguments to match that of the other functions.

0
 
LVL 30

Expert Comment

by:Axter
ID: 9714056
Niether of the following two lines will compile on VC++ 7.1

void ( * processGrades[4] ) (int grades[][], int, int ) ; //This should not compile
void ( * processGrades[4] ) (int [][], int, int ) ; //This should not compile

The VC++ 7.1 compiler is considered more compliant to the C++ standard then the GNU 3.2.x compiler.


>>But this is NOT TRUE when u are declaring a pointer to that function. Your function pointer need not mention the size of any of
>>the array dimensions.

Can you reffer to the part of the standard that specifically states that this is allowed?
0
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 9714082
Hi Axter,

I have tried the same with gnu and VC 6.0 and did not face any problem

--Amit
0
 
LVL 30

Expert Comment

by:Axter
ID: 9714123
Can you post exactly what you have tried?

Please copy and paste the code, so we can be sure we're talking about the same thing.
0
 
LVL 30

Expert Comment

by:Axter
ID: 9714204
Simple test:

int main(int, char**)
{
   void ( * processGrades[4] ) (int grades[][], int, int ) = {minimum, maximum, printArray} ;
   return 0;
}

The above code does not compile on any C++ compliant compiler that I'm aware of.

I just tried to compile it on VC++ 6.0 and, it fails.

I also used Dev-C++ which uses the same compiler that mingw32 uses, and it also fails to compile.

I don't think you're testing the exact same code.
0
 
LVL 30

Expert Comment

by:Axter
ID: 9714220
FYI:
I'm not implying that VC++ 6.0 is a compliant C++ compiler.

On the other hand, VC++ 7.1 is considered to be a very good C++ compliant compilers.
0
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 9714229
I tried again on Dev C++, and it does compile at my installation

--Amit

 
0
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 9714234
Thanks for the info regarding compliance of VC 6 and VC 7 to C++.

But I do not have access to VC++ 7.0 compiler.

We can may be try on some UNIX based compiler, but it works with GNU compiler

-- Amit
0
 
LVL 30

Expert Comment

by:Axter
ID: 9714264
Again,
Please post the EXACT code you're using for testing, so we can be sure we're talking about the same thing.
0
 
LVL 30

Expert Comment

by:Axter
ID: 9714287
>>But I do not have access to VC++ 7.0 compiler.

7.0 is also not a very good C++ compliant compiler.  It's better then 6.0, but it still has too many compliance issues.

With 7.1 Microsoft finally got it right.
0
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 9714308
Hi Axter,

I am testing exactly the same code what u tried.

Only thing is that I corrected the signature for average in the questioner's code.

--Amit

0
 

Author Comment

by:marcypark
ID: 9718565
Ok, I tried to make the average function look like the other functions (maximum and minimum), but the compliler complains.  Also, I tried to insert the array of the students grades but only got 16 errors.  Can you please help me out a little more?  I am using Visual Basic 6.0 C++ in case you are wondering:

#include <iostream>

using std::fixed;
using std::endl;
using std::cout;
using std::left;
using std::cin;

#include <iomanip>

using std::setw;
using std::setprecision;

const int students = 3;
const int exams = 4;

void minimum (int [] [exams], int, int);
void maximum (int [] [exams], int, int);
void average (int [] [exams], int, int);
void printArray (int [] [exams], int, int);

int main()
{
      int choice = 0;
      int studentGrades [students][exams] =
      {{77, 68, 86, 73},
      {96, 87, 89, 78},
      {70, 90, 86, 81}};
while (choice != 4){
      cout << "\nEnter a choice:" << endl;
      cout << " 0  Print the array of grades" << endl;
      cout << " 1  Find the minimum grade" << endl;
      cout << " 2  Find the maximim grade" << endl;
      cout << " 3  Print the average on all tests for each student" << endl;
      cout << " 4  End program" << endl;
      cout << "? ";
      cin >> choice;
      
      if (choice == 4) break;
      if (choice == 0){
            cout << "The is ";
            printArray (studentGrades, students, exams);      }
      if (choice == 1){
      cout << "\n\tThe lowest grade is ";
             minimum(studentGrades, students, exams);}
      if (choice == 2){
      cout << "\n\tThe highest grade is ";
             maximum(studentGrades, students, exams);}
      if (choice == 3){
      cout << fixed << setprecision(2);
      for (int person = 0; person < students; person++)
            cout << "\n\tThe average for student " << person << " is ";
          average (studentGrades, students, exams);}
}
return 0;
}


void minimum (int grades[][exams], int pupils, int tests)
{
      int lowGrade = 100;
      for (int i = 0; i < pupils; i++)
            for (int j = 0; j < tests; j++)
                  if (grades[i][j] < lowGrade)
                        lowGrade = grades[i][j];
      cout << lowGrade << endl;
}
void maximum (int grades[][exams], int pupils, int tests)
{
      int highGrade = 0;
      for (int i = 0; i < pupils; i++)
            for (int j = 0; j < pupils; j++)
                  if (grades[i][j] > highGrade)
                        highGrade = grades[i][j];
      cout << highGrade << endl;
}

void average (int setOfGrades[], int tests)
{
      int total = 0;
      for (int i = 0; i < tests; i++)
            total += setOfGrades[i];
      cout << static_cast<double>(total) / tests << endl;
      
}

void printArray (int grades[] [exams], int pupils, int tests)
{
      cout << left << "            [0]  [1]  [2]  [3]";

      for (int i = 0; i < pupils; i++){
            cout << "\nstudentGrades[" << i << "]";

      for (int j = 0; i < tests; j++)
            cout << setw(5) << grades[i][j];
      }
}
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

Author Comment

by:marcypark
ID: 9718886
Can anyone help me?
0
 
LVL 15

Expert Comment

by:efn
ID: 9718891
I tried this in Visual C++ 6.0 (no Basic) and it compiled fine.  Only the linker complained because there was no average function that matched the declaration.  You have to change the average function itself as well as the declaration you have already changed.

--efn
0
 

Author Comment

by:marcypark
ID: 9719173
What could I change it to?
0
 
LVL 15

Expert Comment

by:efn
ID: 9719206
The way you have already declared it, the same as the other functions:

void average (int [] [exams], int, int);

One of the integer parameters can tell the function how many tests there are.  The other one can tell the function which student to use, rather than how many students there are as in the other functions.  If you make this design change, you will also have to change the call to the average function correspondingly.

--efn
0
 

Author Comment

by:marcypark
ID: 9719232
I am sooo lost.  Here is the code that I have changed.  What am I still doing wrong?

#include <iostream>

using std::fixed;
using std::endl;
using std::cout;
using std::left;
using std::cin;

#include <iomanip>

using std::setw;
using std::setprecision;

const int students = 3;
const int exams = 4;

void minimum (int [] [exams], int, int);
void maximum (int [] [exams], int, int);
void average (int [] [exams], int, int);
void printArray (int [] [exams], int, int);

int main()
{
      int choice = 0;
      int studentGrades [students][exams] =
      {{77, 68, 86, 73},
      {96, 87, 89, 78},
      {70, 90, 86, 81}};
while (choice != 4){
      cout << "\nEnter a choice:" << endl;
      cout << " 0  Print the array of grades" << endl;
      cout << " 1  Find the minimum grade" << endl;
      cout << " 2  Find the maximim grade" << endl;
      cout << " 3  Print the average on all tests for each student" << endl;
      cout << " 4  End program" << endl;
      cout << "? ";
      cin >> choice;
      
      if (choice == 4) break;
      if (choice == 0){
            cout << "The is ";
            printArray (studentGrades, students, exams);      }
      if (choice == 1){
      cout << "\n\tThe lowest grade is ";
             minimum(studentGrades, students, exams);}
      if (choice == 2){
      cout << "\n\tThe highest grade is ";
             maximum(studentGrades, students, exams);}
      if (choice == 3){
      cout << fixed << setprecision(2);
      for (int person = 0; person < students; person++)
            cout << "\n\tThe average for student " << person << " is ";
          average (studentGrades, students, exams);}
}
return 0;
}


void minimum (int grades[][exams], int pupils, int tests)
{
      int lowGrade = 100;
      for (int i = 0; i < pupils; i++)
            for (int j = 0; j < tests; j++)
                  if (grades[i][j] < lowGrade)
                        lowGrade = grades[i][j];
      cout << lowGrade << endl;
}
void maximum (int grades[][exams], int pupils, int tests)
{
      int highGrade = 0;
      for (int i = 0; i < pupils; i++)
            for (int j = 0; j < pupils; j++)
                  if (grades[i][j] > highGrade)
                        highGrade = grades[i][j];
      cout << highGrade << endl;
}

void average (int [] [exams], int, int)
{
      int total = 0;
      int tests;
      int setOfGrades;
      for (int i = 0; i < tests; i++)
            total += setOfGrades[i];
      cout << static_cast<double>(total) / tests << endl;
      
}

void printArray (int grades[] [exams], int pupils, int tests)
{
      cout << left << "            [0]  [1]  [2]  [3]";

      for (int i = 0; i < pupils; i++){
            cout << "\nstudentGrades[" << i << "]";

      for (int j = 0; i < tests; j++)
            cout << setw(5) << grades[i][j];
      }
}
0
 
LVL 30

Expert Comment

by:Axter
ID: 9719313
What did you change?

Please give details.

Exactly what did you change, and why do you feel something is wrong?
0
 
LVL 30

Expert Comment

by:Axter
ID: 9719319
>>I am testing exactly the same code what u tried.
>>Only thing is that I corrected the signature for average in the questioner's code.

Then it's not exactly the same.
You can't be testing the same thing that we're testing, because it fails to compile on VC++ 6.0 and on the GNU compiler.
So you have to be testing some thing different from what we're testing.

Don't be shy.... Post you got.
0
 

Author Comment

by:marcypark
ID: 9719326
I changed the average function to void and tried to make it like the others.  There is something wrong because the error reads: error C2109: subscript requires array or pointer type right at the average function.
0
 

Author Comment

by:marcypark
ID: 9719339
The code that I am testing is the code that I posted up last.
0
 
LVL 30

Expert Comment

by:Axter
ID: 9719357
What line is giving you the compile error?
0
 

Author Comment

by:marcypark
ID: 9719370
total += setOfGrades[i];

0
 
LVL 30

Expert Comment

by:Axter
ID: 9719388
Try changing your average function to the following:

void average (int setOfGrades[] [exams], int index, int tests)
{
      int total = 0;
    for (int i = 0; i < tests; i++)
            total += setOfGrades[index][i];
    cout << static_cast<double>(total) / tests << endl;
}
0
 
LVL 30

Expert Comment

by:Axter
ID: 9719393
And change the code calling average to the following:

                  for (int person = 0; person < students; person++)
                        cout << "\n\tThe average for student " << person << " is ";
                  average (studentGrades, person, exams);}
0
 

Author Comment

by:marcypark
ID: 9719410
The program runs, but when I choose option 0, to print the array, the program goes crazy and ends up with a message to send the error report to Mircosoft.  Also, with option 3, the average, it does not print the average for each student.  For student0 is shows nothing, for student1 it shows nothing and for student2 it shows 1399667.25?  What is going on here?  BTW, thank you for sticking with me!
0
 
LVL 30

Expert Comment

by:Axter
ID: 9719442
The last for-loop is using i instead of j in your printArray function
0
 
LVL 30

Expert Comment

by:Axter
ID: 9719447
Here's the correction:

void printArray (int grades[] [exams], int pupils, int tests)
{
    cout << left << "            [0]  [1]  [2]  [3]";
      
    for (int i = 0; i < pupils; ++i)
      {
            cout << "\nstudentGrades[" << i << "]";
            
            for (int j = 0; j < tests; ++j)
                  cout << setw(5) << grades[i][j];
    }
}
0
 

Author Comment

by:marcypark
ID: 9719449
Ok, the last question.  Why won't the program print the correct average for each student?
0
 
LVL 30

Expert Comment

by:Axter
ID: 9719481
Try the following for average:

void average (int grades[][exams], int pupils, int tests)
{
      cout << fixed << setprecision(2);
      for (int person = 0; person < pupils; person++)
      {
            cout << "\n\tThe average for student " << person << " is ";
            int total = 0;
            for (int i = 0; i < tests; i++)
                  total += grades[person][i];
            cout << static_cast<double>(total) / tests << endl;
      }
}

Then you can declare your function pointer via the following method:
void ( * processGrades[4] ) (int [][exams], int, int ) = {printArray, minimum, maximum, average} ;

You can then call it like this:
            if (choice == 4) break;
            processGrades[choice](studentGrades, students, exams);

0
 
LVL 30

Accepted Solution

by:
Axter earned 500 total points
ID: 9719487
Full example:
const int students = 3;
const int exams = 4;

void minimum (int [] [exams], int, int);
void maximum (int [] [exams], int, int);
void average (int [] [exams], int, int);
void printArray (int [] [exams], int, int);

int main()
{
    int choice = 0;
    int studentGrades [students][exams] =
    {{77, 68, 86, 73},
    {96, 87, 89, 78},
    {70, 90, 86, 81}};
      void ( * processGrades[4] ) (int [][exams], int, int ) = {printArray, minimum, maximum, average} ;
      
      while (choice != 4){
            cout << "\nEnter a choice:" << endl;
            cout << " 0  Print the array of grades" << endl;
            cout << " 1  Find the minimum grade" << endl;
            cout << " 2  Find the maximim grade" << endl;
            cout << " 3  Print the average on all tests for each student" << endl;
            cout << " 4  End program" << endl;
            cout << "? ";
            cin >> choice;
            
            if (choice == 4) break;
            processGrades[choice](studentGrades, students, exams);
      }
      return 0;
}


void minimum (int grades[][exams], int pupils, int tests)
{
    int lowGrade = 100;
    for (int i = 0; i < pupils; i++)
            for (int j = 0; j < tests; j++)
                  if (grades[i][j] < lowGrade)
                        lowGrade = grades[i][j];
                  cout << lowGrade << endl;
}
void maximum (int grades[][exams], int pupils, int tests)
{
    int highGrade = 0;
    for (int i = 0; i < pupils; i++)
            for (int j = 0; j < pupils; j++)
                  if (grades[i][j] > highGrade)
                        highGrade = grades[i][j];
                  cout << highGrade << endl;
}

void average (int grades[][exams], int pupils, int tests)
{
      cout << fixed << setprecision(2);
      for (int person = 0; person < pupils; person++)
      {
            cout << "\n\tThe average for student " << person << " is ";
            int total = 0;
            for (int i = 0; i < tests; i++)
                  total += grades[person][i];
            cout << static_cast<double>(total) / tests << endl;
      }
}

void printArray (int grades[] [exams], int pupils, int tests)
{
    cout << left << "            [0]  [1]  [2]  [3]";
      
    for (int i = 0; i < pupils; ++i)
      {
            cout << "\nstudentGrades[" << i << "]";
            
            for (int j = 0; j < tests; ++j)
                  cout << setw(5) << grades[i][j];
    }
}
0
 

Author Comment

by:marcypark
ID: 9719531
Thank you very much!!!
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now