Passing structures to functions.

Hello, I have to write a program which allows the input of a student's id, name and marks in 4 different subjects using a function input_stud and another function calculate_over to calculate his overall percentage of marks(the total exam marks are 400). I have been able to get the first function right but the function calculate_over is not displaying the correct percentage and I am not permitted to use pointers.
Here is what I have worked out so far:
Any improvisations and modifications would be greatly appreciated.

#include <iostream>

using namespace std;

struct student
{
int id;
string surname;
string othername;
int marks1,marks2,marks3,marks4,total;
double avg;

};

void input_stud(student);

student calculate_over(student&);

int main()

{
student s, z;

input_stud (s);
z=calculate_over(s);

cout<< "The overall percentage is:"<<z.avg<< " %"<<endl;


return 0;
}


void input_stud (student std)
{

cout<< "\nEnter the following details of the student. "<<endl;
cout<< "\n ID number:";
cin>>std.id;

cout<< "\n Surname:";
cin>>std.surname;

cout<< "\n Other names:";
cin>>std.othername;

cout<< "\n Marks obtained:";
cout<< "\n Subject 1:";
cin>>std.marks1;

cout<< "\n Subject 2:";
cin>>std.marks2;

cout<< "\n Subject 3:";
cin>>std.marks3;

cout<< "\n Subject 4:";
cin>>std.marks4;

}

student calculate_over(student& std)
{
student result;
int total= (std.marks1+ std.marks2+ std.marks3+ std.marks4);
result.avg= (total/400)*100;

return result;
}
Last edited on
Problem is in your input_stud function. It does nothing. It receives a copy of some struct, changes it... and that is all. No changes would be visible outside.
You need to pass structure as reference, as you did in calculate_over.

Additionally there is a problem with average claculation in calculate_over.
Quiz time: what is the result of (399/400)*100?
Time is up, answer is: 0. As 399/400 is 0. You are performing integer division here. which discards fractional part.
Easiest way to fix it is to make total double. This wy you will force floating point division and everything will be all right.
Do a call by reference, Or use pointers, ... there are more solutions.

At this moment when your std object gets out of scope it is lost.

void input_stud (student & std)

and I think
result.avg= (total/4);

Last edited on
@MiNiPaa I have understood what u said about the average calculation so I have made total of type double but I am not sure if I have quite got what you have said about the input_stud function. I have come up with this but it is still not displaying the correct avg.

#include <iostream>
using namespace std;

struct student
{
int id;
string surname;
string othername;
int marks1,marks2,marks3,marks4;
double avg;

};

void input_stud(student);

student calculate_over(student&);

int main()

{
student s;

input_stud (s);
calculate_over(s);



return 0;
}


void input_stud (student std)
{

cout<< "\nEnter the following details of the student. "<<endl;
cout<< "\n ID number:";
cin>>std.id;

cout<< "\n Surname:";
cin>>std.surname;

cout<< "\n Other names:";
cin>>std.othername;

cout<< "\n Marks obtained:";
cout<< "\n Subject 1:";
cin>>std.marks1;

cout<< "\n Subject 2:";
cin>>std.marks2;

cout<< "\n Subject 3:";
cin>>std.marks3;

cout<< "\n Subject 4:";
cin>>std.marks4;

cout<< "The overall percentage is:"<<std.avg<< " %"<<endl;


}

student calculate_over(student& std)
{
student result;
double total= (std.marks1+ std.marks2+ std.marks3+ std.marks4);
result.avg= (total/4)*100;

return result;
}
1
2
3
4
5
6
7
8
int main()
{
    student s; //Creates s filled with random data

    input_stud (s); //Does not change s at all as it was passed by copy
    std::cout << s.mark1 << '\n'; //Look for yourself
    calculate_over(s); //Calls function, s contains random data
}

Quiz: what the difference between
1
2
3
(student )
//and
(student&)
and how one or other wuld change program execution.
@MiiNiPaa

Well... I think both (student) and (student&) access the same data structure that is struct student.
Actually, this is my first question working with passing structure to two functions so I am really at a loss at this.
I think both (student) and (student&) access the same data structure that is struct student.
So, what that & means and why do you have it in calculate_over(student&); and don't in input_stud(student);? (actual question. Why did you write like this?)

The answer is, something like void foo(int ) passes by copy and all operations inside function are done on copy:
1
2
3
4
5
6
7
8
9
10
11
int foo(int i) //Copies argument into i
{
    i = 5; //Changes copy
} //i is destroyed here. There is no way to read its value now

int main()
{
    int x = 0; //Create variable
    foo(x); //Copy x into foo and operate on copy
    //x here is still 0, as it was not changed in function
}


On the other hand something like void foo(int&) is passed by reference, which means that operations would be applied to passed variable:
1
2
3
4
5
6
7
8
9
10
11
void foo(int& i) //I is a reference to passed argument. Any changes to i will be reflected on passed variable
{
    i = 5; //Sets whichever variable was passed to 5;
}

int main()
{
    int x = 0;
    foo(x); //Pass x to function. foo changes value of x
    //x is now 5
}
Last edited on
Okay.. Do u mean that it should be like this? I am still not getting the answer right.:/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
using namespace std;

struct student
{
    int id;
    string surname;
    string othername;
    int marks1,marks2,marks3,marks4;
    double answer;
    double total, avg;


};

void input_stud(student);

student calculate_over(student);

int main()

{
    student s;

    input_stud (s);
    calculate_over(s);



   return 0;
}


void input_stud (student std)
{

    cout<< "\nEnter the following details of the student. "<<endl;
        cout<< "\n ID number:";
        cin>>std.id;

        cout<< "\n Surname:";
        cin>>std.surname;

        cout<< "\n Other names:";
        cin>>std.othername;

        cout<< "\n Marks obtained:";
        cout<< "\n Subject 1:";
        cin>>std.marks1;

        cout<< "\n Subject 2:";
        cin>>std.marks2;

        cout<< "\n Subject 3:";
        cin>>std.marks3;

        cout<< "\n Subject 4:";
        cin>>std.marks4;

        cout<< "The overall percentage is:"<<std.answer<< " %"<<endl;


}

student calculate_over(student std)
{
    student result;
    result.total= (std.marks1+ std.marks2+ std.marks3+ std.marks4);
    result.avg= (result.total/4);
    result.answer= result.avg*100;

    return result;
}
cout<< "The overall percentage is:"<<std.answer<< " %"<<endl;

You are printing out answer here (on line 60). But you never assign anything to it so you will get garbage being printed out. You read in marks, but do nothing with them.

Also, like Minipaa is trying to tell you, if you wish to use the same student object back in main(), (so you can pass it to calculate_over for example), then you must pass by reference.
http://www.learncpp.com/cpp-tutorial/73-passing-arguments-by-reference/
Do u mean that it should be like this?
No.
1
2
//void input_stud(student);
input_stud (s); //Value of s will not be changed 
Is this what you need? If not, what do you expect?
OP, as another clue your last method should look more like this:
1
2
3
4
5
6
7
8
void calculate_over(student& student)
{
    student.total= (student.marks1+ student.marks2+ student.marks3+ student.marks4);
    student.avg= (student.total/4);
    student.answer= student.avg*100;

   cout<< "The overall percentage is:"<<student.answer<< " %"<<endl;
}
& is like an alias to that object. If you change the alias you change the object.
That's what you need.

If you pass by value you have to return that value at the end of the function. return std; But!!! Then you also have to implement a copy constructor. (see deep and shallow copy) to know why and change your function to have a return value. IF you copy by value your data even doesn't get into your fuction without the copy Constructor.

Types like int,float,double,.. have build in copy constructors, your struct student has not.....
http://www.tutorialspoint.com/cplusplus/cpp_copy_constructor.htm

here is a the working program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>

 using namespace std;

 struct student
 {
 int id;
 string surname;
 string othername;
 int marks1,marks2,marks3,marks4,total;
 float avg;

 };
 void input_stud(student &);

 void calculate_over(student&);

int main()
{
    student s;
    input_stud (s);
    calculate_over(s);
    cout<< "The overall percentage is:"<<s.avg<< " %"<<endl;
    return 0;
}


 void input_stud (student &std)
 {

 cout<< "\nEnter the following details of the student. "<<endl;
 cout<< "\n ID number:";
 cin>>std.id;

 cout<< "\n Surname:";
 cin>>std.surname;

 cout<< "\n Other names:";
 cin>>std.othername;

 cout<< "\n Marks obtained (in %):";
 cout<< "\n Subject 1:";
 cin>>std.marks1;

 cout<< "\n Subject 2:";
 cin>>std.marks2;

 cout<< "\n Subject 3:";
 cin>>std.marks3;

 cout<< "\n Subject 4:";
 cin>>std.marks4;

 }

 void calculate_over(student& std)
 {

 int total= (std.marks1+ std.marks2+ std.marks3+ std.marks4);
 std.avg= (total/4);

 }


Last edited on
Then you also have to implement a copy constructor.
Or use a default ones if they are suit you.
I have finally understood the whole concept.
Thank you everyone for your help.

I immensely appreciate the quick responses to my question and as a first-timer on a forum (and this being my first question on a forum) it's nice to be here and to see so many people volunteering to help and explain the concepts.
Topic archived. No new replies allowed.