error C3861: identifier not found - c++

I encountered the following problem with this code.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iomanip>
//////////////////////////////////////////////////////////
//////////////////////////CORE CLASS//////////////////////
//////////////////////////////////////////////////////////
class Core {
public:
Core() : midterm(0), final(0) { }
Core(std::istream& is) { read(is); }
std::string name() const;
virtual std::istream& read(std::istream&);
virtual double grade() const;
protected:
std::istream& read_common(std::istream&);
std::istream& read_hw(std::istream&, std::vector<double>&);
double midterm, final;
std::vector<double> homework;
private:
std::string n;
};
std::string Core::name() const { return n; }
double Core::grade() const
{
return calc_grade(midterm, final, homework);
}
std::istream& Core::read_common(std::istream& in)
{
in >> n >> midterm >> final;
return in;
}
std::istream& Core::read(std::istream& in)
{
read_common(in);
read_hw(in, homework);
return in;
}
std::istream& Core::read_hw(std::istream& in, std::vector<double>& homework)
{
double input;
while (in >> input)
homework.push_back(input);
return in;
}
//////////////////////////////////////////////////////////
//////////////////////////GRAD CLASS//////////////////////
//////////////////////////////////////////////////////////
class Grad : public Core {
public:
Grad() : thesis(0) { }
Grad(std::istream& is) { read(is); }
double grade() const;
std::istream& read(std::istream&);
private:
double thesis;
};
std::istream& Grad::read(std::istream& in)
{
read_common(in);
in >> thesis;
read_hw(in, homework);
return in;
}
double Grad::grade() const
{
return std::min(Core::grade(), thesis);
}
//////////////////////////////////////////////////////////
//////////////////////MISCELLANEOUS///////////////////////
//////////////////////////////////////////////////////////
bool compare_grades(const Core& c1, const Core& c2)
{
return c1.grade() < c2.grade();
}
bool compare_Core_ptrs(const Core* cp1, const Core* cp2)
{
return compare_grades(*cp1, *cp2);
}
double calc_grade(double midterm, double final, std::vector<double>& homework)
{
double result = 0.0;
for (std::vector<double>::const_iterator i = homework.begin(); i != homework.end(); ++i)
result += *i;
return midterm*0.4 + final*0.4 + (result / homework.size())*0.2;
}
using namespace std;
int main()
{
vector<Core*> students;
Core* record;
char ch;
string::size_type maxlen = 0;
while (cin >> ch)
{
if (ch == 'U')
record = new Core;
else
record = new Grad;
record->read(cin);
maxlen = max(maxlen, record->name().size());
students.push_back(record);
}
sort(students.begin(), students.end(), compare_Core_ptrs);
for (vector<Core*>::size_type i = 0; i != students.size(); ++i)
{
cout << students[i]->name() << string(maxlen + 1 - students[i]->name().size(), ' ');
try
{
double final_grade = students[i]->grade();
streamsize prec = cout.precision();
cout << setprecision(3) << final_grade << setprecision(prec) << endl;
}
catch (domain_error e)
{
cout << e.what() << endl;
}
delete students[i];
}
return 0;
}
error C3861: 'calc_grade': identifier not found. I tried to move the function before the classes but nothing changed. I don't understand what is wrong. Help.

You need to move calc_grade above grade so that it knows it exists. Or declare it above like this.
double calc_grade(double midterm, double final, std::vector<double>& homework);
Your grade method is marked const, so it may not change your class. But you are calling calc_grade which does not take a const vector therefor it could change the class member you are handing it. You can make it take a const vector to solve this. I would make that method const as well to keep things consistent.
One possible fix:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iomanip>
//////////////////////////////////////////////////////////
//////////////////////////CORE CLASS//////////////////////
//////////////////////////////////////////////////////////
class Core {
public:
Core() : midterm(0), final(0) { }
Core(std::istream& is) { read(is); }
std::string name() const;
virtual std::istream& read(std::istream&);
virtual double grade() const;
protected:
std::istream& read_common(std::istream&);
std::istream& read_hw(std::istream&, std::vector<double>&);
double midterm, final;
std::vector<double> homework;
private:
std::string n;
};
std::string Core::name() const { return n; }
double calc_grade(double midterm, double final, const std::vector<double>& homework)
{
double result = 0.0;
for (std::vector<double>::const_iterator i = homework.begin(); i != homework.end(); ++i)
result += *i;
return midterm*0.4 + final*0.4 + (result / homework.size())*0.2;
}
double Core::grade() const
{
return calc_grade(midterm, final, homework);
}
std::istream& Core::read_common(std::istream& in)
{
in >> n >> midterm >> final;
return in;
}
std::istream& Core::read(std::istream& in)
{
read_common(in);
read_hw(in, homework);
return in;
}
std::istream& Core::read_hw(std::istream& in, std::vector<double>& homework)
{
double input;
while (in >> input)
homework.push_back(input);
return in;
}
//////////////////////////////////////////////////////////
//////////////////////////GRAD CLASS//////////////////////
//////////////////////////////////////////////////////////
class Grad : public Core {
public:
Grad() : thesis(0) { }
Grad(std::istream& is) { read(is); }
double grade() const;
std::istream& read(std::istream&);
private:
double thesis;
};
std::istream& Grad::read(std::istream& in)
{
read_common(in);
in >> thesis;
read_hw(in, homework);
return in;
}
double Grad::grade() const
{
return std::min(Core::grade(), thesis);
}
//////////////////////////////////////////////////////////
//////////////////////MISCELLANEOUS///////////////////////
//////////////////////////////////////////////////////////
bool compare_grades(const Core& c1, const Core& c2)
{
return c1.grade() < c2.grade();
}
bool compare_Core_ptrs(const Core* cp1, const Core* cp2)
{
return compare_grades(*cp1, *cp2);
}
using namespace std;
int main()
{
vector<Core*> students;
Core* record;
char ch;
string::size_type maxlen = 0;
while (cin >> ch)
{
if (ch == 'U')
record = new Core;
else
record = new Grad;
record->read(cin);
maxlen = max(maxlen, record->name().size());
students.push_back(record);
}
sort(students.begin(), students.end(), compare_Core_ptrs);
for (vector<Core*>::size_type i = 0; i != students.size(); ++i)
{
cout << students[i]->name() << string(maxlen + 1 - students[i]->name().size(), ' ');
try
{
double final_grade = students[i]->grade();
streamsize prec = cout.precision();
cout << setprecision(3) << final_grade << setprecision(prec) << endl;
}
catch (domain_error e)
{
cout << e.what() << endl;
}
delete students[i];
}
return 0;
}

Related

Cant copy from a file to vector of pointers to objects

So I have a class called CStudentEmploy containing 3 variables.
I have another class class
CAnalizeData:CStudentEmploy
which contains a vector of pointers
vector<CStudentEmploy*>m_vData;
I also have istream operator :
friend istream& operator >> (istream& str,CStudentEmploy& obj)
{
str >> obj.m_strName >> obj.m_strFacNum >> obj.m_iMinutes;
return str;
}
I want to fill this vector from a file in a way like this:
CAnalizeData(const string &strFileName) {
ifstream ifile(strFileName.data());
copy(istream_iterator<CStudentEmploy*>(ifile), istream_iterator<CStudentEmploy*>(), back_inserter(m_vData));
}
This way works if I am trying to fill a vector of objects.
The error I get is :
Error C2679 binary '>>': no operator found which takes a right-hand operand of type '_Ty' (or there is no acceptable conversion)
I understand there is a problem with the iterator,but can't really fix it.Thanks.
Here is the full code:
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <fstream>
#include <algorithm>
#include <istream>
using namespace std;
class CStudentEmploy {
private:
string m_strName;
string m_strFacNum;
int m_iMinutes;
public:
CStudentEmploy() {
m_strName = "Empty";
m_strFacNum = "Empty";
m_iMinutes = 0;
}
CStudentEmploy(string strname,string strfacnum,int minutes) {
m_strName = strname;
m_strFacNum = strfacnum;
m_iMinutes = minutes;
}
CStudentEmploy(const CStudentEmploy &obj) {
m_strName = obj.m_strName;
m_strFacNum =obj.m_strFacNum;
m_iMinutes =obj.m_iMinutes;
}
int get_m_iMinutes() {
return m_iMinutes;
}
CStudentEmploy operator =(const CStudentEmploy &obj) {
this->m_strName = obj.m_strName;
this->m_strFacNum = obj.m_strFacNum;
this->m_iMinutes = obj.m_iMinutes;
return *this;
}
bool operator <(const CStudentEmploy &obj)const {
return m_iMinutes<obj.m_iMinutes;
}
CStudentEmploy operator +(const CStudentEmploy &obj) {
this->m_iMinutes += obj.m_iMinutes;
return *this;
}
friend ostream& operator << (ostream& str, const CStudentEmploy &obj)
{
str << "\nIme: " << obj.m_strName<< "\nF Nomer: " << obj.m_strFacNum << "\nMinuti:" << obj.m_iMinutes << endl;
return str;
}
friend istream& operator >> (istream& str,CStudentEmploy& obj)
{
str >> obj.m_strName >> obj.m_strFacNum >> obj.m_iMinutes;
return str;
}
};
class CAnalizeData:CStudentEmploy {
private:
vector<CStudentEmploy*>m_vData;
public:
CAnalizeData(const string &strFileName) {
ifstream ifile(strFileName.data());
copy(istream_iterator<CStudentEmploy*>(ifile), istream_iterator<CStudentEmploy*>(), back_inserter(m_vData));
}
void Write() {
vector<CStudentEmploy*>::iterator it = m_vData.begin();
while (it != m_vData.end())
{
cout << *it++;
}
}
void Sort() {
sort(m_vData.begin(), m_vData.end());
}
double calcMean() {
double avg = 0;
vector<CStudentEmploy*>::iterator it = m_vData.begin();
for (it = m_vData.begin(); it != m_vData.end(); it++) {
avg += (*it)->get_m_iMinutes();
}
cout << "Average minutes is:";
return avg / m_vData.size();
}
};
int main() {
CAnalizeData AB("Test.txt");
AB.Sort();
AB.Write();
cout << AB.calcMean();
cout << endl; system("pause");
return 0;
}
Perhaps something with std::transform:
CAnalizeData(const string &strFileName) {
ifstream ifile(strFileName.data());
transform(istream_iterator<CStudentEmploy>(ifile),
istream_iterator<CStudentEmploy>(), back_inserter(m_vData),
[](const CStudentEmploy &e) { return new CStudentEmploy(e); });
}
Using new there, since I assume the object would have been created on the stack.

How to use std::sort to sort particular objects from an array?

I have those classes and I want to sort an array of objects, considering x coordinate, and sort just those with a particular value to an attribute.
Class.h
#include <iostream>
#include <algorithm>
class Punct2D
{
protected:
int x, y;
public:
Punct2D() {};
~Punct2D() {};
int get_x() const;
int get_y() const;
void set_x(const int x);
void set_y(const int y);
friend std::ostream &operator << (std::ostream &flux, Punct2D dot);
friend std::istream &operator >> (std::istream &flux, Punct2D &dot);
};
class Punct2DColorat :public Punct2D
{
private:
char *color;
public:
Punct2DColorat() { this->color = NULL; };
~Punct2DColorat() {};
char *get_color();
void set_color(char *color);
bool operator<(Punct2DColorat dot);
};
Here I have the implementation.
#include "Class.h"
int Punct2D::get_x() const
{
return this->x;
}
int Punct2D::get_y() const
{
return this->y;
}
void Punct2D::set_x(const int x)
{
this->x = x;
}
void Punct2D::set_y(const int y)
{
this->y = y;
}
char *Punct2DColorat::get_color()
{
return this->color;
}
void Punct2DColorat::set_color(char *color)
{
this->color = new char[strlen(color) + 1];
for (int i = 0; i < strlen(color) + 1; i++) this->color[i] = color[i];
}
bool Punct2DColorat::operator<(Punct2DColorat dot)
{
return this->x < dot.get_x();
}
std::ostream &operator << (std::ostream &flux, Punct2D dot)
{
flux << "Punct(" << dot.get_x() << "," << dot.get_y() << ")\n";
return flux;
}
std::istream &operator >> (std::istream &flux, Punct2D &dot)
{
std::cout << "Introduceti x :";
flux >> dot.x;
std::cout << "Introduceti y :";
flux >> dot.y;
return flux;
}
And here is the Main.
#include "Class.h"
void main()
{
int n, it = 0; char *aux = new char[15]; bool value;
Punct2DColorat *dots;
std::cout << "Cate puncte introduceti :"; std::cin >> n;
dots = new Punct2DColorat[n];
for (int i = 0; i < n; i++)
{
std::cout << "Introduceti 0 pentru Punct2D, respectiv 1 pentru Punct2D colorat :";
std::cin >> value;
if (value)
{
std::cin >> dots[i];
std::cout << "Introduceti culoarea punctului :";
std::cin >> aux;
dots[i].set_color(aux);
}
else
{
std::cin >> dots[i];
}
}
std::sort(dots, dots + n, [](Punct2DColorat dot) { return dot.get_color() != NULL; });
for (int i = 0; i < n; i++)
{
std::cout << dots[i];
if (dots[i].get_color() != NULL)
{
std::cout << "Culoare :" << dots[i].get_color() << "\n";
}
std::cout << "\n";
}
}
I want to sort the dots with color !=NULL, I tried this, it works but I have a runtime error.
bool Punct2DColorat::operator<(Punct2DColorat dot)
{
if ((this->color != NULL) && (dot.get_color() != NULL))return this->x < dot.get_x();
return true;
}
How can I sort just the objects with color !=NULL and the other objects with color==NULL remain in the same position?
Here is an example:
//If have 3 objects in the following order stored in the dots array.
dots[0].get_x()=3;
dots[0].get_y()=3;
dots[0].get_color()="Red";
dots[1].get_x()=0;
dots[1].get_y()=0;
dots[1].get_color()=NULL;
dots[2].get_x()=1;
dots[2].get_y()=1;
dots[2].get_color()="Blue";
//After sort i want to have them like this:
dots[0].get_x()=1;
dots[0].get_y()=1;
dots[0].get_color()="Blue";
dots[1].get_x()=0;
dots[1].get_y()=0;
dots[1].get_color()=NULL;
dots[2].get_x()=3;
dots[2].get_y()=3;
dots[2].get_color()="Red";
Thanks.
The problem is, your comparison operator evaluates to true for any couple of non-colored points.
A possible solution is to construct a second vector, sort it and re-insert
std::vector<Punct2DColorat> tmp;
for (int i = 0; i < n; i++)
{
if (dots[i].get_color() != NULL)
{
tmp.push_back(dots[i]);
}
}
std::sort(tmp.begin(), tmp.end());
int j = 0;
for (int i = 0; i < n; i++)
{
if (dots[i].get_color() != NULL)
{
dots[i] = tmp[j];
++j;
}
}

Errors in Linking Files in Eclipse

I am having so much trouble with linking files in eclipse. I keep getting undefined reference errors, even though I added each file path to the Paths and Symbols setting in Project. I also included the header files. I have 1 Application file along with 3 implementation files and 2 header files.
Here is 1 implementation file:
#include <iostream>
#include <fstream>
#include "complex2.h"
#include "complexType.h"
using namespace std;
complexDB::complexDB(int lineCount)
{
length = lineCount;
c = new complexType[lineCount];
num_complex = 0;
}
void complexDB::set_Index(int i, const complexType& cT)
{
c[i] = cT;
}
void complexDB::set_numComplex(int n)
{
num_complex = n;
}
void complexDB::insert(const complexType& insertItem)
{
if (num_complex < length)
{
int oldi = num_complex;
c[oldi] = insertItem; // inserts item at the last index of array
num_complex++;
}
}
void complexDB::deletee(const complexType& deleteItem)
{
}
void complexDB::list()
{
cout << "in list:" << endl;
cout << length << "\t" << num_complex << endl;
for (int i = 0; i < num_complex; i++)
{
cout << c[i];
}
}
void complexDB::save()
{
ofstream fout;
fout.open("126complex.txt");
if (fout.is_open())
{
cout << "is open" << endl;
}
for (int i = 0; i < num_complex; i++)
{
fout << c[i];
}
}
complexDB::~complexDB()
{
delete[] c;
}
Here is another implementation file:
#include <fstream>
#include <sstream>
#include "complexType.h"
//#include "complex2.cpp"
using namespace std;
#define CA_MAX_SIZE 10
#define ComplexFileName "126.txt"
void CreateComplexFile()
{
complexType ca[CA_MAX_SIZE];
ofstream fout;
fout.open(ComplexFileName);
for (int i = 0; i < CA_MAX_SIZE; i++)
{
ca[i].setComplex(i, i + 1);
fout << ca[i];
}
fout.close();
}
void ReadComplexFile()
{
complexType ca[CA_MAX_SIZE];
ifstream fin;
fin.open(ComplexFileName);
for (int i = CA_MAX_SIZE - 1; i >= 0; i--)
{
fin >> ca[i];
}
fin.close();
}
void ReadComplexFileEOF()
{
complexType ca[CA_MAX_SIZE];
ifstream fin;
fin.open(ComplexFileName);
int i = 0;
while (!fin.eof())
{
fin >> ca[i++];
}
fin.close();
}
void ReadComplexFileTwice()
{
complexType ca[CA_MAX_SIZE];
ifstream fin;
fin.open(ComplexFileName);
for (int i = CA_MAX_SIZE - 1; i >= 0; i--)
{
fin >> ca[i];
}
fin.clear();
fin.seekg(0, ios::beg);
int i = 0;
while (!fin.eof())
{
fin >> ca[i++];
}
fin.close();
}
void ImportComplexFile(string fname)
{
ifstream fin;
double real, im;
char plusorminus, ichar;
string oneline;
fin.open(fname.c_str());
while (!fin.eof())
{
getline(fin, oneline);
stringstream(oneline) >> real >> plusorminus >> im >> ichar;
}
fin.close();
}
void ImportComplexFile2(string fname)
{
ifstream fin;
fin.open(fname.c_str());
double real, im;
char plusorminus, ichar;
complexType c;
string oneline;
while (!fin.eof())
{
getline(fin, oneline);
real = 0;
im = 0;
plusorminus = '\0';
ichar = '\0';
stringstream(oneline) >> real >> plusorminus >> im >> ichar;
switch (plusorminus)
{
case '-':
im = -im;
break;
case 'i':
im = real;
real = 0;
break;
case '\0':
im = 0;
break;
}
c.setComplex(real, im);
cout << c << endl;
}
fin.close();
}
For both files, anything with complexType gives the error:
undefined reference to `complexType::complexType(double, double)'
Also for the main file I get this error:
cannot find -lC:\Users\Altemush\Documents\SJSU_Dev\projects_mingw\complex2\src
I suppose I'm not linking the files together correctly, een though I thought I did. Please, can anyone help me?
Here is complexType.h:
#ifndef H_complexNumber
#define H_complexNumber
#include <iostream>
using namespace std;
class complexType
{
friend ostream& operator<< (ostream&, const complexType&);
friend istream& operator>> (istream&, complexType&);
friend complexType operator+(const complexType& one,
const complexType& two);
public:
void setComplex(const double& real, const double& imag);
complexType(double real = 0, double imag = 0);
complexType& operator=(const complexType &rhs);
complexType operator-(const complexType& two);
complexType operator-(int x);
int realPart;
int imaginaryPart;
};
#endif
Here is complexType.cpp:
#include <iostream>
#include "complexType.h"
using namespace std;
ostream& operator<< (ostream& os, const complexType& complex)
{
os << "(" << complex.realPart << ", "
<< complex.imaginaryPart << ")" << endl;
return os;
}
istream& operator>> (istream& is, complexType& complex)
{
char ch;
// is >> ch;
is >> complex.realPart;
is >> ch;
is >> complex.imaginaryPart;
is >> ch;
return is;
}
complexType::complexType(double real, double imag)
{
setComplex(real, imag);
}
void complexType::setComplex(const double& real, const double& imag)
{
realPart = real;
imaginaryPart = imag;
}
complexType operator+(const complexType& one, const complexType& two)
{
complexType temp;
temp.realPart = one.realPart + two.realPart;
temp.imaginaryPart = one.imaginaryPart + two.imaginaryPart;
return temp;
}
complexType complexType::operator-( const complexType &operand2 )
{
return complexType( realPart - operand2.realPart,
imaginaryPart - operand2.imaginaryPart );
}
complexType complexType::operator-( int operand2 )
{
return complexType( realPart - operand2,
imaginaryPart - operand2 );
}
complexType& complexType::operator=(const complexType &rhs){
realPart = rhs.realPart;
imaginaryPart = rhs.imaginaryPart;
return *this;
}

C++ Operand types are incompatible("Movie" and "nullptr")

const Movie* Movies::getMovie(string mc, int& mn) const {
if(mc.length()==0)
return nullptr; // not found
else {
mc = myToLower(mc);
int ndx=0;
for(;ndx<movieCnt &&
(myToLower(movies[ndx].getTitle()).find(mc)==
string::npos);ndx++);
mn = ndx<movieCnt?ndx+1:0;
return ndx<movieCnt?&movies[ndx]:nullptr;
}
}
//const Movie* Movies::getMovie(int mc) const {
const Movie* Movies::operator[](int mc) const{
return (mc > 0 && mc <= movieCnt)?movies[mc-1]:nullptr;
}
I got this error message error: Operand types are incompatible("Movie" and "nullptr")
In Movies.h
public:
Movies(string);
int getMovieCount() const;
const Movie* getMovie(string, int&) const;
const Movie* getMovie(int) const;
const Movie* Movies::operator[](int mc) const;
~Movies();
Any help? Thank you!
// Movie.cpp
#include "Movie.h" // include Movie class definition
#include <sstream>
using namespace std;
Movie::Movie() {
title = studio = "";
boxOffice[WORLD] = boxOffice[US] = boxOffice[NON_US] =
rank[WORLD] = rank[US] = rank[NON_US] = releaseYear = 0;
}
Movie::Movie(string temp) {
istringstream iS(temp);
getline(iS, title, '\t');
getline(iS, studio, '\t');
iS >> releaseYear >> rank[US] >> boxOffice[US] >> rank[NON_US]
>> boxOffice[NON_US] >> rank[WORLD] >> boxOffice[WORLD];
}
string Movie::getTitle() const {return title;}
string Movie::getStudio() const {return studio;}
int Movie::getReleaseYear() const {return releaseYear;}
int Movie::getUSRank() const {return rank[US];}
int Movie::getNonUSRank() const {return rank[NON_US];}
int Movie::getWorldRank() const {return rank[WORLD];}
long long Movie::getUSBoxOffice() const {return boxOffice[US];}
long long Movie::getNonUSBoxOffice() const {return boxOffice[NON_US];}
long long Movie::getWorldBoxOffice() const {return boxOffice[WORLD];}
std::ostream& operator << (std::ostream& os, const Movie &movie)
{
os << "\n\n====================== Movie Information\n"
<< "\n Movie Title:\t" << movie.getTitle()
<< " (" << movie.getReleaseYear() << ") " << movie.getStudio()
<< "\n US Rank & Box Office:\t" << movie.getUSRank() << "\t$" << movie.getUSBoxOffice()
<< "\nNon-US Rank & Box Office:\t" << movie.getNonUSRank() << "\t$" << movie.getNonUSBoxOffice()
<< "\n World Rank & Box Office:\t" << movie.getWorldRank()<< "\t$" << movie.getWorldBoxOffice()
<< "\n";
return os;
}
Movie::Movie(const Movie &mP) { // copy constructor
this->title = mP.title;
this->studio = mP.studio;
this->releaseYear = mP.releaseYear;
this->rank[US] = mP.rank[US];
this->rank[NON_US] = mP.rank[NON_US];
this->rank[WORLD] = mP.rank[WORLD];
this->boxOffice[US] = mP.boxOffice[US];
this->boxOffice[NON_US] = mP.boxOffice[NON_US];
this->boxOffice[WORLD] = mP.boxOffice[WORLD];
}
this is Movie.cpp,below is Movies.cpp.
// Movies.cpp
#include "Movie.h" // include Movie class definition
#include "Movies.h" // include Movies class definition
#include <fstream>
using namespace std;
Movies::Movies(string fn){loadMovies(fn);}
int Movies::getMovieCount() const {return movieCnt;}
const Movie* Movies::getMovie(string mc, int& mn) const {
if(mc.length()==0)
return nullptr; // not found
else {
mc = myToLower(mc);
int ndx=0;
for(;ndx<movieCnt &&
(myToLower(movies[ndx].getTitle()).find(mc)==
string::npos);ndx++);
mn = ndx<movieCnt?ndx+1:0;
return ndx<movieCnt?&movies[ndx]:nullptr;
}
}
//const Movie* Movies::getMovie(int mc) const {
const Movie* Movies::operator[](int mc) const{
return (mc > 0 && mc <= movieCnt)?&movies[mc-1]:nullptr;
}
Movies::~Movies() { // not needed - invoked at end
delete[] movies;
movies = nullptr;
}
void Movies::loadMovies(string fn) {
ifstream iS(fn);
string s;
getline(iS, s); // skip heading
getline(iS, s);
movieCnt=0;
movies = new Movie[MAX_MOVIES];
while(!iS.eof()) {
movies[movieCnt++] = Movie(s);
getline(iS, s);
}
iS.close();
reSize();
}
void Movies::reSize() {
Movie * m = movies;
movies = new Movie[movieCnt];
for(int i=0;i<movieCnt;i++)
movies[i] = m[i];
delete[] m; // null assignment not needed; end of method
}
string Movies::myToLower(string s) const {
string t; // initialized as ""
for(char c : s)
t += tolower(c);
return t;
}
a part of Movies.h:
public:
Movies(string);
int getMovieCount() const;
const Movie* getMovie(string, int&) const;
const Movie* getMovie(int) const;
const Movie* Movies::operator[](int) const;
~Movies();
#WhozCraig Thank you for answering me! I upload the Movie.cpp,Movies.cpp and part of Movies.cpp I really conused..

Printing out information from a file by looping through another function designed to search the file - C++

I have this function that can scan my file and print out a predesignated record according to which one you choose to look at:
void addressBook::showRecord(int pickNum) {
PEOPLE2 p;
ifstream indata("vectortest.dat", ios::binary);
if(!indata) {
cout << "Error opening file for reading " << endl;
exit(0);
}
indata.seekg(pickNum * sizeof(PEOPLE2));
indata.read(reinterpret_cast <char*> (&p), sizeof(PEOPLE2));
cout << p.fName2 << " " << p.lName2 << " " << p.Address2 << " " << endl;
}
So all you have to do is pop showRecord into main, and then pick which name you want to print out. Say I want to look at the second name stored, I would put in
newBook->showRecord(1);
Thats all fine an dandy, and it works perfect, but what if I want to go a bit further. So I create another function that can use showRecord to print out all of the names in the address book that have been stored to my file. I tried this:
void addressBook::showAll() {
ifstream indata("vectortest.dat", ios::binary);
for(int i = 0; i < indata.end; i++) {
showRecord(i);
}
}
and it works, but it only prints out the stuff that's hard coded into my PERSON struct from a previous assignment:
addressBook *newBook = addressBook::newbookInst();
PERSON me[] = {{"First" , "Last", "ADDRESS"}, {"John", "Doe", "1234"}};
newBook->addPerson(me[1]);
newBook->addPerson(me[0]);
which is just odd beacuse when I go into the file itself, I can see all of the names that were added.
So how do I use this so that it actually prints out everything in the file, and not just the two entries that are permanently stored?
Here is my addressbook.h and addressbook.cpp code in case you need a better understanding of whats going on...
\\addressbook.h////////
#ifndef _ADDRESSBOOK
#define _ADDRESSBOOK
#include <fstream>
#include <vector>
#include<string>
using std::string;
#include <iostream>
using namespace std;
using std::istream;
using std::ostream;
namespace CJ
{
const int MAXADDRESS =25;
struct PERSON
{
string fName;
string lName;
string Address;
};
struct PEOPLE2
{
char fName2[25];
char lName2[25];
char Address2[25];
};
class addressBook
{
private:
vector<PERSON> people;
int head;
int tail;
public:
addressBook();
addressBook(const PERSON &p);
addressBook(const PERSON p[], int size);
addressBook(char *fName, char *lName, char *address);
bool addPerson(const PERSON &p);
bool sortcomp(const PERSON& p1, const PERSON& p2);
bool getPerson(PERSON &p);
bool findPerson(const string& lastName, PERSON& p);
bool findPerson(const string& lastName, const string& firstName, PERSON& p);
void bubbleSort(int *array,int length);
void printBook();
void sort();
void waitKey();
static addressBook *newbookInst();
static addressBook *tempNew;
static PERSON *p();
static PERSON *temPerson;
void showRecord(int pickNum);
void writeRecord();
void showAll();
friend ostream &operator << (ostream &, addressBook &);
addressBook operator =(const string& str);
addressBook &operator +=(const PERSON &p);
addressBook operator [](int x);
};
}
#endif
\\addressbook.cpp/////
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <conio.h>
#include <string>
using std::string;
#include "addressBook.h"
#include "menu.h"
namespace CJ
{
addressBook::addressBook()
: head(0), tail(-1)
{
}
addressBook::addressBook(const PERSON &p)
: head(0), tail(-1)
{
addPerson(p);
}
addressBook::addressBook(const PERSON p[], int size)
: head(0), tail(-1)
{
for(int i = 0; i < size; i++)
addPerson(p[i]);
}
addressBook::addressBook(char *fName, char *lName, char *Address)
: head(0), tail(-1)
{
PERSON tmp;
tmp.fName = fName;
tmp.lName = lName;
tmp.Address = Address;
addPerson(tmp);
}
bool addressBook::addPerson(const PERSON &p)
{
people.push_back(p);
if(tail == -1)
tail++;
return true;
}
bool addressBook::getPerson(PERSON &p)
{
if(tail >=0)
{
if(tail >= people.size())
tail = 0;
p = people[tail];
tail++;
return true;
}
return false;
}
bool addressBook::findPerson(const string &lastName, PERSON &p)
{
for(size_t i = 0; i < people.size(); i++)
{
if(people[i].lName == lastName)
{
PERSON *p = addressBook::p();
*p = people[i];
return true;
}
}
return false;
}
bool addressBook::findPerson(const string &lastName, const string &firstName, PERSON &p)
{
for(size_t i = 0; i < people.size(); i++)
{
if(people[i].lName == lastName && people[i].fName == firstName)
{
PERSON *p = addressBook::p();
*p = people[i];
return true;
}
}
return false;
}
void addressBook::printBook()
{
for(size_t i = 0; i < people.size(); i++)
{
std::cout << people[i].fName << "\t" << people[i].lName << "\t" << people[i].Address << std::endl;
}
}
bool addressBook::sortcomp(const PERSON& p1, const PERSON& p2)
{
int result = (p1.lName.compare(p2.lName)) ;
if ( result > 0 )
return true ;
if ( result < 0 )
return false ;
return (p1.fName.compare(p2.fName)) > 0 ;
}
void addressBook::sort()
{
bool didSwap ;
do
{
didSwap = false ;
for ( unsigned i=1; i<people.size(); ++i )
if ( sortcomp(people[i-1], people[i]) )
{
std::swap(people[i-1], people[i]) ;
didSwap = true ;
}
} while ( didSwap ) ;
}
addressBook &addressBook::operator +=(const PERSON &p)
{
addPerson(p);
return *this;
};
addressBook addressBook::operator [](int x)
{
return people[x];
};
ostream &operator << (ostream &output, addressBook &ab)
{
PERSON tmp;
ab.getPerson(tmp);
output << tmp.fName << " " << tmp.lName << " " << tmp.Address << endl;
return output;
}
addressBook * addressBook::tempNew = NULL;
addressBook *addressBook::newbookInst()
{
if(tempNew == NULL)
{
tempNew = new addressBook;
}
return tempNew;
}
PERSON * addressBook::temPerson = NULL;
PERSON *addressBook::p()
{
if(temPerson == NULL)
{
temPerson = new PERSON;
}
return temPerson;
}
bool status;
char lName[50];
char fName[50];
void addressBook::writeRecord()
{
PEOPLE2 temp;
ofstream outFile("vectortest.dat", ios::app);
if(!outFile)
{
cout << "Error opening file for writing " << endl;
return;
}
for (vector<PERSON>::iterator iter = people.begin(), end = people.end(); iter != end; ++iter)
{
strncpy(temp.fName2, iter->fName.c_str(), 25);
strncpy(temp.lName2, iter->lName.c_str(), 25);
strncpy(temp.Address2, iter->Address.c_str(), 25);
outFile.write(reinterpret_cast<const char *>(&temp), sizeof(PEOPLE2));
}
outFile.close();
}
void addressBook::showRecord(int pickNum)
{
PEOPLE2 p;
ifstream indata("vectortest.dat", ios::binary);
if(!indata)
{
cout << "Error opening file for reading " << endl;
exit(0);
}
indata.seekg(pickNum * sizeof(PEOPLE2));
indata.read(reinterpret_cast<char *>(&p), sizeof(PEOPLE2));
cout << p.fName2 << " " << p.lName2 << " " << p.Address2 << " " << endl;
indata.close();
}
void addressBook::showAll()
{
ifstream indata("vectortest.dat", ios::binary);
for(int i = 0; i < indata.end; i ++)
{
showRecord(i);
}
}
}
I don't really know that much about the context of how you're planning to use your address book class. But what I've done is re-work the basic structure of what you had into a little more idiomatic C++. This should hopefully help guide your future work on this class. The reading from file issue that you were having issues with is fixed.
#include <iostream>
#include <iterator>
#include <fstream>
#include <cstdlib>
#include <conio.h>
#include <string>
#include <vector>
#include <algorithm>
const int MAXADDRESS = 25;
struct PEOPLE2
{
char fName2[25];
char lName2[25];
char Address2[25];
};
struct PERSON
{
PERSON()
{}
PERSON(PEOPLE2 p)
: fName(p.fName2), lName(p.lName2), Address(p.Address2)
{}
PERSON(const std::string& first, const std::string& last, const std::string& add)
: fName(first), lName(last), Address(add)
{}
std::string fName;
std::string lName;
std::string Address;
};
// required for std::sort
bool operator< (const PERSON &lhs, const PERSON &rhs)
{
int result = (lhs.lName.compare(rhs.lName));
if(result == 0)
return lhs.fName < rhs.fName;
return result < 0;
}
// required for os << people
std::ostream& operator<< (std::ostream& os, const PERSON& rhs)
{
os << rhs.fName << " " << rhs.lName << " " << rhs.Address;
return os;
}
class addressBook
{
private:
std::vector<PERSON> people;
public:
addressBook()
{ }
addressBook(const PERSON &p)
{
addPerson(p);
}
template<typename IT>
addressBook(IT begin, IT end)
{
std::copy(begin, end, std::back_inserter(people));
}
addressBook(char *fName, char *lName, char *address)
{
PERSON tmp;
tmp.fName = fName;
tmp.lName = lName;
tmp.Address = address;
addPerson(tmp);
}
addressBook(const std::string& fileName)
{
std::ifstream indata(fileName, std::ios::binary);
PEOPLE2 p;
while(true)
{
indata.read(reinterpret_cast<char*>(&p), sizeof(PEOPLE2));
if(indata.fail())
break;
people.push_back(p);
}
}
void addPerson(const PERSON &p)
{
people.push_back(p);
}
bool findPerson(const std::string& lastName, PERSON& p)
{
std::find_if(std::begin(people), std::end(people), [&](const PERSON& in)->bool
{
if(lastName == in.lName)
{
p = in;
return true;
}
return false;
});
}
bool findPerson(const std::string& lastName, const std::string& firstName, PERSON& p)
{
std::find_if(std::begin(people), std::end(people), [&](const PERSON& in)->bool
{
if(lastName == in.lName && firstName == in.fName)
{
p = in;
return true;
}
return false;
});
}
void printBook()
{
std::for_each(std::begin(people), std::end(people), [](const PERSON& p)
{
std::cout << p.fName << "\t" << p.lName << "\t" << p.Address << std::endl;
});
}
void sort()
{
std::sort(std::begin(people),std::end(people));
}
void waitKey();
void showRecord(int pickNum)
{
std::cout << people[pickNum] << std::endl;
}
void writeRecord(const std::string& fileName)
{
PEOPLE2 temp;
std::ofstream outFile(fileName, std::ios::app);
if(!outFile)
{
std::cout << "Error opening file for writing " << std::endl;
return;
}
for(auto iter = people.begin(), end = people.end(); iter != end; ++iter)
{
strncpy(temp.fName2, iter->fName.c_str(), 25);
strncpy(temp.lName2, iter->lName.c_str(), 25);
strncpy(temp.Address2, iter->Address.c_str(), 25);
outFile.write(reinterpret_cast<const char *>(&temp), sizeof(PEOPLE2));
}
}
void showAll()
{
std::for_each(std::begin(people), std::end(people), [](const PERSON& in)
{
std::cout << in << std::endl;
});
}
friend std::ostream &operator << (std::ostream &output, addressBook &ab)
{
std::for_each(std::begin(ab.people), std::end(ab.people), [&](const PERSON& in)
{
output << in << "\n";
});
return output;
}
addressBook &operator +=(const PERSON &p)
{
addPerson(p);
return *this;
};
PERSON operator [](int x)
{
return people[x];
};
};
std::string fileName = "c:\\temp\\test.rec";
int main()
{
addressBook ab(fileName);
ab.sort();
ab.showAll();
//addressBook ab;
//ab.addPerson(PERSON("Mary", "Smith", "1 West Street"));
//ab.addPerson(PERSON("Joe", "Brown", "2 East Street"));
//ab.addPerson(PERSON("Harry", "Cooper", "3 South Street"));
//ab.writeRecord(fileName);
}