C++ program starting with void PrintTranscript

  • Context: C/C++ 
  • Thread starter Thread starter Nusc
  • Start date Start date
  • Tags Tags
    C++ Program
Click For Summary

Discussion Overview

The discussion revolves around a C++ program that includes a function named PrintTranscript, which is intended to print a student's course transcript. Participants are addressing issues related to syntax errors, function definitions, and the handling of student data structures. The scope includes debugging, coding practices, and function implementation.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • Post 1 presents a syntax error related to the scope of the variable j in nested loops, prompting requests for help.
  • Post 2 suggests that additional brackets are needed for clarity in the loop structure.
  • Post 4 emphasizes the importance of using braces for all loops and branches to avoid scoping issues.
  • Post 5 introduces new errors related to undefined references for functions ReadStudent and ComputeGPA, indicating that they have not been defined in the code.
  • Post 6 clarifies that the undefined references are due to the absence of function definitions despite their prototypes being declared.
  • Post 10 points out that the ComputeGPA function is incorrectly handling a vector of students instead of a single student, suggesting a need for adjustment in either the argument list or the function body.
  • Post 11 shows an attempt to define the ReadStudent function but indicates incomplete code, suggesting ongoing issues with implementation.

Areas of Agreement / Disagreement

Participants generally agree on the need for proper function definitions and the use of braces in loops. However, there is disagreement on how to correctly implement the ComputeGPA function, with differing views on whether it should handle a vector of students or a single student.

Contextual Notes

Limitations include unresolved issues regarding the correct handling of student data structures and the proper implementation of function definitions. The discussion also reflects varying levels of understanding about C++ syntax and programming practices.

Nusc
Messages
752
Reaction score
2
void PrintTranscript( const vector <student>& a )
{
count << "Here is a list of courses that you have taken:" << endl;
for (int i = 0; i<a.size(); i++)
{
line 104: for (int j = 0; j<a.size(); j++)
count << a.firstname << " " << a.lastname << " " << a.id << endl;
line 106: count << a.courses[j].session << " " << a.courses[j].year << " " << a.courses[j].coursename << " " << a.courses[j].percentage << " " << a.courses[j].lettergrade << endl;
}
}

PI.cc:106: error: name lookup of `j' changed for new ISO `for' scoping
PI.cc:104: error: using obsolete binding at `j'


Can anyone please help me?
 
Technology news on Phys.org
The loop in which j is defined is only one line long. You want more brackets, I think.
 
Where do I put the brackets?
 
You are referencing j in line 106, so that line should be in the loop over j.

The easiest way to solve this problem is to always code as if the C required braces for all loops and branches. In other words, pretend
for (i=0;i<n;i++) do_something_with(i)

is illegal.

This rule is automatically enforced by code checkers in many programming shops. Get in the habit of always using braces.
 
void PrintTranscript( const vector <student>& a )
{
count << "Here is a list of courses that you have taken:" << endl;
for (int i = 0; i<a.size(); i++)
{
count << a.at(i).firstname << " " << a.at(i).lastname << " " << a.at(i).id << endl;
for (int j = 0; j<a.size(); j++)
{

count << a.at(i).courses.at(j).session << " " << a.at(i).courses.at(j).year << " " << a.at(i).courses.at(j).coursename << " " << a.at(i).courses.at(j).percentage << " " << a.at(i).courses.at(j).lettergrade << endl;
}
}
}

Error
undefined reference to `ReadStudent(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<student, std::allocator<student> >&)'

undefined reference to `ComputeGPA(std::vector<student, std::allocator<student> > const&)'


undefined reference to `ReadStudent(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<student, std::allocator<student> >&)'
collect2: ld returned 1 exit status

I don't even understand what this means, what's wrong now?
 
Those undefined references (ReadStudent and ComputeGpA) are methods you are invoking but that you have not defined.
 
void ReadStudent(string id, vector<student>& a);
void PrintTranscript(const vector<student>& a);
double ComputeGPA(const vector <student>& a);
int main()
{
string id;
string filename;
vector <student> a;

count <<"Please enter your student ID number"<< endl;
cin >> id;
ReadStudent(id, a);
char choice;

do
{
count << "What do you wish to do with the database?" << endl;
count << "Input the relevant letter: Options are" << endl;
count << "(a) List the courses taken by the student" << endl;
count << "(b) Compute and display the student's grade point average (GPA)" << endl;
count << "(c) Open the file of another student" << endl;
count << "(d) Quit the program" << endl;

cin >> choice;
count << "You have entered:" << choice << endl;
switch (choice)
{
case ('a'):
PrintTranscript(a);
break;
case ('b'):
ComputeGPA(a);
break;
case ('c'):
count << "Please enter another student ID" << endl;
cin >> id;
ReadStudent(id,a);
break;
case ('d'):
{
count << "Program ending" << endl;
}
}
}while(choice != 'd');
return 0;
}

That's my main function, how did I not define those functions?
 
You specified prototypes for the functions. You did not define them.

Here is a function prototype, taken from your code:
double ComputeGPA(const vector <student>& a);


Somewhere you have to define the function, which would look like
Code:
double ComputeGPA(const vector <student>& a)
{
  double gpa;
  // Compute the student's GPA
  // GPA code computation omitted
  return gpa;
}
 
double ComputeGPA(const vector <student>& a)
{
double GPA = 0;
double sum = 0;
for( int i = 0; i<a.courses.size(); i++)
{
if(a.courses.at(i).lettergrade == "A+")
sum += 4.0;
if(a.courses.at(i).lettergrade == "A")
sum += 4.0;
if(a.courses.at(i).lettergrade == "A-")
sum += 3.7;
if(a.courses.at(i).lettergrade == "B+")
sum += 3.3;
if(a.courses.at(i).lettergrade == "B")
sum += 3.0;
if(a.courses.at(i).lettergrade == "B-")
sum += 2.7;
if(a.courses.at(i).lettergrade == "C+")
sum += 2.3;
if(a.courses.at(i).lettergrade == "C")
sum += 2.0;
if(a.courses.at(i).lettergrade == "C-")
sum += 1.7;
if(a.courses.at(i).lettergrade == "D")
sum += 1.0;
if(a.courses.at(i).lettergrade == "F")
sum += 0.0;
}
GPA = sum/a.courses.size();
count << "Average GPA:" << GPA << endl;
}
Which gives me:

PI.cc: In function `double ComputeGPA(const std::vector<student, std::allocator<student> >&)':
PI.cc:117: error: 'const class std::vector<student, std::allocator<student> >' has no member named 'courses'
PI.cc:119: error: 'const class std::vector<student, std::allocator<student> >' has no member named 'courses'
PI.cc:121: error: 'const class std::vector<student, std::allocator<student> >' has no member named 'courses'
PI.cc:123: error: 'const class std::vector<student, std::allocator<student> >' has no member named 'courses'
PI.cc:125: error: 'const class std::vector<student, std::allocator<student> >' has no member named 'courses'
PI.cc:127: error: 'const class std::vector<student, std::allocator<student> >' has no member named 'courses'
PI.cc:129: error: 'const class std::vector<student, std::allocator<student> >' has no member named 'courses'
PI.cc:131: error: 'const class std::vector<student, std::allocator<student> >' has no member named 'courses'
PI.cc:133: error: 'const class std::vector<student, std::allocator<student> >' has no member named 'courses'
PI.cc:135: error: 'const class std::vector<student, std::allocator<student> >' has no member named 'courses'
PI.cc:137: error: 'const class std::vector<student, std::allocator<student> >' has no member named 'courses'
PI.cc:139: error: 'const class std::vector<student, std::allocator<student> >' has no member named 'courses'
PI.cc:142: error: 'const class std::vector<student, std::allocator<student> >' has no member named 'courses'

Compilation exited abnormally with code 1 at Mon Apr 16 19:47:14

Those lines correspond to the if(a.courses.at(i).lettergrade == "A-") etc.

If needed:

#include <fstream>
#include <vector>
#include <iostream>
#include <cmath>
#include <cstdlib>

using namespace std;


struct course
{
char session;
int year;
string coursename;
int coursenumber;
double percentage;
string lettergrade;
};

struct student
{
vector <course> courses;
string firstname;
string lastname;
int id;
};

What's the problem now?
 
Last edited:
  • #10
Your argumet list indicates the funtion is receiving avector of students, but your function body is obviously dealing with just one student. You need to either fix the argument list (just one student, not a vector of students) or fix the function body (compute the GPAs of a vector of students).
 
  • #11
Okay I fixed that
void ReadStudent( string id,vector<student>& a)
{
student tmp;
id += ".txt";
ifstream infile(id.c_str());
infile >> tmp.firstname;
infile >> tmp.lastname;
infile >> tmp.id;
tmp.courses.resize(0);
while(!infile.eof())
{
tmp.courses.push_back(tmp);
int j = tmp.courses.size()-1;
infile >> tmp.courses.at(j).session;
infile >> tmp.courses.at(j).year;
infile >> tmp.courses.at(j).coursename;
infile >> tmp.courses.at(j).coursenumber;
infile >> tmp.courses.at(j).percentage;
infile >> tmp.courses.at(j).lettergrade;
}
}


but now I receive:

PI.cc: In function `void ReadStudent(std::string, std::vector<student, std::allocator<student> >&)':
PI.cc:88: error: no matching function for call to `std::vector<course, std::allocator<course> >::push_back(student&)'
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_vector.h:557: note: candidates are: void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = course, _Alloc = std::allocator<course>]

Compilation exited abnormally with code 1 at Mon Apr 16 20:22:51

what does this mean?
 
Last edited:
  • #12
I fixed it. My program compiles but when I run the text file associated with it I get aborted (core dumped).

#include <fstream>
#include <vector>
#include <iostream>
#include <cmath>
#include <cstdlib>

using namespace std;


struct course
{
char session;
int year;
string coursename;
int coursenumber;
double percentage;
string lettergrade;

};

struct student
{
vector <course> courses;
string firstname;
string lastname;
int id;
};


void ReadStudent(string id, vector<student>& a);
void PrintTranscript(const vector<student>& a);
double ComputeGPA(const vector<student>& a);
int main()
{
string id;
string filename;
vector <student> a;

count <<"Please enter your student ID number"<< endl;
cin >> id;
ReadStudent(id, a);
char choice;

do
{
count << "What do you wish to do with the database?" << endl;
count << "Input the relevant letter: Options are" << endl;
count << "(a) List the courses taken by the student" << endl;
count << "(b) Compute and display the student's grade point average (GPA)" << endl;
count << "(c) Open the file of another student" << endl;
count << "(d) Quit the program" << endl;

cin >> choice;
count << "You have entered:" << choice << endl;
switch (choice)
{
case ('a'):
PrintTranscript(a);
break;
case ('b'):
ComputeGPA(a);
break;
case ('c'):
count << "Please enter another student ID" << endl;
cin >> id;
ReadStudent(id,a);
break;
case ('d'):
{
count << "Program ending" << endl;
}
}
}while(choice != 'd');
return 0;
}

void ReadStudent( string id,vector<student>& a)
{
student tmp;
id += ".txt";
ifstream infile(id.c_str());
infile >> tmp.firstname;
infile >> tmp.lastname;
infile >> tmp.id;
tmp.courses.resize(0);
while(!infile.eof())
{
//tmp.courses.push_back(tmp);
int j = tmp.courses.size()-1;
infile >> tmp.courses.at(j).session;
infile >> tmp.courses.at(j).year;
infile >> tmp.courses.at(j).coursename;
infile >> tmp.courses.at(j).coursenumber;
infile >> tmp.courses.at(j).percentage;
infile >> tmp.courses.at(j).lettergrade;
a.push_back(tmp);
}
}

void PrintTranscript( const vector <student>& a )
{
count << "Here is a list of courses that you have taken:" << endl;
for (int i = 0; i<a.size(); i++)
{
count << a.at(i).firstname << " " << a.at(i).lastname << " " << a.at(i).id << endl;
for (int j = 0; j<a.size(); j++)
{

count << a.at(i).courses.at(j).session << " " << a.at(i).courses.at(j).year << " " << a.at(i).courses.at(j).coursename << " " << a.at(i).courses.at(j).percentage << " " << a.at(i).courses.at(j).lettergrade << endl;
}
}
}

double ComputeGPA(const vector <student>& a)
{
double GPA = 0;
double sum = 0;
for(int j = 0; j<a.size(); j++)
{
for( int i = 0; i<a.at(j).courses.size(); i++)
{
if(a.at(j).courses.at(i).lettergrade == "A+")
sum += 4.0;
if(a.at(j).courses.at(i).lettergrade == "A")
sum += 4.0;
if(a.at(j).courses.at(i).lettergrade == "A-")
sum += 3.7;
if(a.at(j).courses.at(i).lettergrade == "B+")
sum += 3.3;
if(a.at(j).courses.at(i).lettergrade == "B")
sum += 3.0;
if(a.at(j).courses.at(i).lettergrade == "B-")
sum += 2.7;
if(a.at(j).courses.at(i).lettergrade == "C+")
sum += 2.3;
if(a.at(j).courses.at(i).lettergrade == "C")
sum += 2.0;
if(a.at(j).courses.at(i).lettergrade == "C-")
sum += 1.7;
if(a.at(j).courses.at(i).lettergrade == "D")
sum += 1.0;
if(a.at(j).courses.at(i).lettergrade == "F")
sum += 0.0;
GPA = sum/a.at(j).courses.size();
}
}

count << "Average GPA:" << GPA << endl;
return GPA;
}
 
  • #13
Why are you pushing a student (tmp) onto a vector of courses?

Don't program by guessing. Think about what you want the program to do and what you are telling it to do.

Edited to add:
The above response was to post #11.

It looks like you are still programming by guessing.

For example, what makes you want to have a vector of students at all, when you are only dealing with one student at a time?
 
Last edited:
  • #14
Sorry the test file is:

123456.txt

John Smith 123456
F 2005 ENGG 205 62 C-
W 2006 ECON 209 79 B+
W 2006 ENGG 233 85 A
 
  • #15
I don't want a vector of students. I want a vector that will read this line say:

F 2005 ENGG 205 62 C-
 
  • #16
That function is still reading one student.

Can someone please tell me how to fix this?

One chance to help, one chance to write a final.
 
Last edited:
  • #17
Where can I go for help?
 
  • #18
You seem to be having tremendous problems just getting your code to compile, which indicates deep misunderstandings of the basics. You should get some help from your professor or TA immediately. Your needs may well be beyond what we can provide on an a forum.

- Warren
 
  • #19
The program compiles but I receive the following when running my program:
Aborted (core dumped)

My professor doesn't know C++ very well nor does my TA.
 
  • #20
Okay. I finally got the program to read the text file.

However, when it computes the average GPA it only says 3 which is not correct.

double ComputeGPA(const vector <student>& a)
{
double GPA = 0;
double sum = 0;
for(int j = 0; j<a.size(); j++)
{
for( int i = 0; i<a.at(j).courses.size(); i++)
{
if(a.at(j).courses.at(i).lettergrade == "A+")
sum += 4.0;
if(a.at(j).courses.at(i).lettergrade == "A")
sum += 4.0;
if(a.at(j).courses.at(i).lettergrade == "A-")
sum += 3.7;
if(a.at(j).courses.at(i).lettergrade == "B+")
sum += 3.3;
if(a.at(j).courses.at(i).lettergrade == "B")
sum += 3.0;
if(a.at(j).courses.at(i).lettergrade == "B-")
sum += 2.7;
if(a.at(j).courses.at(i).lettergrade == "C+")
sum += 2.3;
if(a.at(j).courses.at(i).lettergrade == "C")
sum += 2.0;
if(a.at(j).courses.at(i).lettergrade == "C-")
sum += 1.7;
if(a.at(j).courses.at(i).lettergrade == "D")
sum += 1.0;
if(a.at(j).courses.at(i).lettergrade == "F")
sum += 0.0;
GPA = sum/a.at(j).courses.size();
}
}

count << "Average GPA:" << GPA << endl;
return GPA;
}

If I take out the GPA = sum/a.courses.size() out of the for loop I get an error.
 
  • #21
Nusc said:
GPA = sum/a.at(j).courses.size();

This line is probably doing integer division, when you really want floating point division. Cast the size() result to double like this:

GPA = sum/double(a.at(j).courses.size());

- Warren
 
  • #22
chroot said:
This line is probably doing integer division, when you really want floating point division. Cast the size() result to double like this:

GPA = sum/double(a.at(j).courses.size());

- Warren

The line is doing floating point division (sum is a double).

However, Warren is right. You should still cast size to a double. Don't rely on implicit casts.

The GPA of 3.0 is correct. From post #14, John Smith received an A (4.0), a B+ (3.3), and a C- (1.7). The GPA is (4.0+3.3+1.7)/3 = 9.0/3 = 3.0.
 

Similar threads

  • · Replies 25 ·
Replies
25
Views
3K
  • · Replies 6 ·
Replies
6
Views
12K
  • · Replies 23 ·
Replies
23
Views
2K
  • · Replies 75 ·
3
Replies
75
Views
7K
  • · Replies 17 ·
Replies
17
Views
2K
  • · Replies 4 ·
Replies
4
Views
6K
  • · Replies 30 ·
2
Replies
30
Views
5K
  • · Replies 2 ·
Replies
2
Views
4K
  • · Replies 23 ·
Replies
23
Views
3K
  • · Replies 36 ·
2
Replies
36
Views
3K