C/C++ C++ program starting with void PrintTranscript

  • Thread starter Thread starter Nusc
  • Start date Start date
  • Tags Tags
    C++ Program
AI Thread Summary
The discussion focuses on issues encountered while implementing a C++ program that manages student transcripts. Key problems include scoping errors with loop variables, undefined references to functions like ReadStudent and ComputeGPA, and incorrect handling of student course data structures. Suggestions emphasize the importance of using braces for loops to avoid scope-related errors and ensuring that function prototypes are matched with their definitions. The conversation also highlights the need to correctly manage vector operations and data types to prevent runtime errors and crashes. Overall, the thread provides insights into debugging common C++ programming challenges related to data structures and function definitions.
Nusc
Messages
752
Reaction score
2
void PrintTranscript( const vector <student>& a )
{
cout << "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++)
cout << a.firstname << " " << a.lastname << " " << a.id << endl;
line 106: cout << 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 )
{
cout << "Here is a list of courses that you have taken:" << endl;
for (int i = 0; i<a.size(); i++)
{
cout << a.at(i).firstname << " " << a.at(i).lastname << " " << a.at(i).id << endl;
for (int j = 0; j<a.size(); j++)
{

cout << 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;

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

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

cin >> choice;
cout << "You have entered:" << choice << endl;
switch (choice)
{
case ('a'):
PrintTranscript(a);
break;
case ('b'):
ComputeGPA(a);
break;
case ('c'):
cout << "Please enter another student ID" << endl;
cin >> id;
ReadStudent(id,a);
break;
case ('d'):
{
cout << "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();
cout << "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;

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

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

cin >> choice;
cout << "You have entered:" << choice << endl;
switch (choice)
{
case ('a'):
PrintTranscript(a);
break;
case ('b'):
ComputeGPA(a);
break;
case ('c'):
cout << "Please enter another student ID" << endl;
cin >> id;
ReadStudent(id,a);
break;
case ('d'):
{
cout << "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 )
{
cout << "Here is a list of courses that you have taken:" << endl;
for (int i = 0; i<a.size(); i++)
{
cout << a.at(i).firstname << " " << a.at(i).lastname << " " << a.at(i).id << endl;
for (int j = 0; j<a.size(); j++)
{

cout << 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();
}
}

cout << "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();
}
}

cout << "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

Back
Top