Function definition not found (even if they exist) - c++

Here's my main:
#include "terremoto.h"
int main(){
std::string filename, zona;
std::ifstream in_stream;
std::ofstream out_stream;
nodo *elenco, *filtroZona;
std::list<Terremoto> elencoDoppio;
float K;
// caricamento dati tramite file
std::cout << "Inserire nome file da caricare\n";
getline(std::cin, filename);
in_stream.open(filename);
// elenco è la linked list con tutti i terremoti
elenco = carica_elenco(in_stream);
// filtro per zone tramite input da tastiera
std::cout << "Inserire zona da filtrare\n";
std::cin >> zona;
filtroZona = filtro_zona(elenco, zona);
std::cout << filtroZona;
// copia di elenco in una double linked list (elencoDoppio)
elenco_to_list(elenco, elencoDoppio);
stampa_dlist(std::cout, elencoDoppio);
// filtro per soglia di magnitudo tramite input da tastiera
std::cout << "Inserire soglia magnitudo (filtra per >=K)\n";
std::cin >> K;
filtra_magnitudo(elencoDoppio, K);
stampa_dlist(std::cout, elencoDoppio);
return 0;
}
here's my terremoto.h:
#ifndef TERREMOTO_H
#define TERREMOTO_H
#include <iostream>
#include <string>
#include <cstring>
#include <fstream>
#include <list>
const int MAX_TERREMOTI = 100;
const int DIM_DATAORA = 20;
class Terremoto{
public:
Terremoto();
Terremoto(const Terremoto &t);
~Terremoto();
Terremoto& operator=(const Terremoto &t);
bool operator<(const Terremoto &other) const;
void getDataOra(char *str) const {std::strcpy(str, dataOra);}
int getProfondita() const {return profondita;}
float getMagnitudo() const {return magnitudo;}
std::string getZona() const {return zona;}
std::string getAnno() const;
private:
std::string zona;
char* dataOra; // 19 lettere "aaaa-mm-gg hh:mm:ss"
int profondita;
float magnitudo; // intervallo (0.0, 10.0)
friend std::istream& operator>>(std::istream &in, Terremoto &t);
friend std::ostream& operator<<(std::ostream &out, const Terremoto &t);
};
struct nodo{
Terremoto value;
nodo *next;
};
nodo* carica_elenco(std::ifstream &in);
void stampa_slist(std::ofstream &out, nodo* n);
float media_magnitudo(nodo *n, std::string anno);
nodo* filtro_zona(nodo* n, std::string zona);
void elenco_to_list(nodo *n, std::list<Terremoto> &l);
void stampa_dlist(std::ostream &out, std::list<Terremoto> &l);
void stampa_recenti(std::ostream &out, std::list<Terremoto> &l, int n);
void filtra_magnitudo(std::list<Terremoto> &l, float K);
#endif
and here's my terremoto.cpp:
#include "terremoto.h"
Terremoto::Terremoto(){
dataOra = new char[DIM_DATAORA];
}
Terremoto::Terremoto(const Terremoto &t){
dataOra = new char[DIM_DATAORA];
zona = t.zona;
strcpy(dataOra, t.dataOra);
profondita = t.profondita;
magnitudo = t.magnitudo;
}
Terremoto::~Terremoto(){
delete dataOra;
}
Terremoto& Terremoto::operator=(const Terremoto &t){
if (&t != this){
zona = t.zona;
strcpy(dataOra, t.dataOra);
profondita = t.profondita;
magnitudo = t.magnitudo;
}
return *this;
}
std::string Terremoto::getAnno() const{
std::string dataOraString(dataOra);
std::string anno = dataOraString.substr(0,4);
return anno;
}
std::istream& operator>>(std::istream &in, Terremoto &t){
std::getline(in, t.zona, ',');
in.getline(t.dataOra, DIM_DATAORA, ',');
in >> t.profondita;
in >> t.magnitudo;
in.ignore();
return in;
}
std::ostream& operator<<(std::ostream &out, const Terremoto &t)
{
out << t.zona << ","
<< t.dataOra << ","
<< t.profondita << ","
<< t.magnitudo << std::endl;
return out;
}
bool Terremoto::operator<(const Terremoto &other) const{
int year = std::stoi(getAnno());
int otherYear = std::stoi(other.getAnno());
return year < otherYear;
}
nodo* push_front(nodo *n, Terremoto t){
nodo *temp;
temp = new nodo;
temp->value = t;
temp->next = n;
return temp;
}
nodo* carica_elenco(std::ifstream &in){
nodo *n;
Terremoto t;
n = 0;
while (in >> t){
n = push_front(n, t);
}
return n;
}
void stampa_slist(std::ofstream &out, nodo* n){
while (n && out){
out << n->value;
n = n->next;
}
return;
}
float media_magnitudo(nodo *n, std::string anno){
float media = 0.0;
int count = 0;
while (n){
if((n->value).getAnno() == anno){
media += (n->value).getMagnitudo();
count++;
}
n = n->next;
}
media /= count;
return media;
}
nodo* filtro_zona(nodo* n, std::string zona){
nodo *n2 = 0;
while (n){
if ((n->value).getZona() == zona){
push_front(n2, (n->value));
}
n = n->next;
}
return n2;
}
void elenco_to_list(nodo *n, std::list<Terremoto> &l){
while (n){
l.push_back(n->value);
n = n->next;
}
return;
}
void stampa_dlist(std::ostream &out, const std::list<Terremoto> &l){
std::list<Terremoto> temp;
std::list<Terremoto>::iterator iter;
temp = l;
for (iter = temp.begin(); iter != temp.end(); iter++){
out << *iter;
}
out << std::endl;
return;
}
void stampa_recenti(std::ostream &out, const std::list<Terremoto> &l, int n){
std::list<Terremoto> temp;
std::list<Terremoto>::iterator iter;
int count;
temp = l;
temp.sort();
for (iter = temp.begin(), count = 0; iter != temp.end() && count < n; iter++){
out << *iter;
count++;
}
out << std::endl;
return;
}
void filtra_magnitudo(std::list<Terremoto> &l, float K)
{
std::list<Terremoto>::iterator iter;
iter = l.begin();
while (iter != l.end()){
if (iter->getMagnitudo() < K){
iter = l.erase(iter);
}
else
iter++;
}
return;
}
(Visual Studio Code)
Terremoto.h - from line 43 on:
stampa_slist(...) : VSCode suggests "function definition for 'stampa_elenco' not found" (that's not the name of the function, I also tried rebooting but the error stays there.
elenco_to_list(...) : Like above, but this time the function name is correct.
stampa_dlist(...) : Again, it states "stampa_elenco()" is missing a definition, and again that's not the name.
When compiling, I only get an error with stampa_dlist(...) and it's the following:
undefined reference to `stampa_dlist(std::ostream&, std::__cxx11::list<Terremoto, std::allocator >&)'
found in the main, obviously.

As Richard Critten suggested, there was obviously an issue with the "const" in the definition.
No matter how much you check, sometimes the combination of being completely new to CS and the need of a break really hit :D
Sorry for the stupid question, but thanks for opening my eyes ahah

Related

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

segmentation fault scrabble game

im working on a little scrabblegame which i read a txtfile and create a hashtable for all words inside. Word is a specific class which contains a vector of .
i want to create a hashmap by my own and define the length of my "Dictionary" is 50000. im using a nullpointer to reserve all index of my array. If i want to print to my hashtable, compiler tells me a segmentation fault. does any one seems the error?
the headerfile:
class Dictionary {
public:
Dictionary();
Dictionary(string filepath);
friend std::ostream& operator<<(std::ostream& os, const Dictionary& obj);
bool find(const Word& word);
vector<Word> allPossibleWords(const vector<Character>& tiles);
// struct compare {
//
// bool operator()(const Word& a, const Word& b) {
// return a.operator<(b);
// }
// } myCompare;
vector<Word> m_allWords;
vector<Word>::iterator itVecWords;
static const int table_size = 500000;
// std::array <Word*, table_size> arrWords = {nullptr};
Word* arrWords[table_size] = {nullptr};
int hash(Word new_word);
void addItem(Word word);
void printHashTable();
the cpp:
Dictionary::Dictionary(string filepath) {
ifstream datei(filepath.c_str());
while (datei.good() && !datei.eof()) {
string temp;
string temp1;
string::size_type pos;
getline(datei, temp);
pos = temp.find(" ");
temp1 = temp.substr(0, pos);
Word new_word(temp1);
addItem(new_word);
}
datei.close();
}
std::ostream& operator<<(std::ostream& os, const Dictionary& obj) {
for (int i = 0; i < obj.m_allWords.size(); i++) {
os << obj.m_allWords[i] << endl;
}
return os;
}
bool Dictionary::find(const Word& word) const {
if (std::binary_search(m_allWords.begin(), m_allWords.end(), word)) {
return true;
}
return false;
}
vector<Word> Dictionary::allPossibleWords(const vector<Character>& tiles) const {
vector<Word> ergebnis;
string tmp;
int cnt = 0;
for (int i = 0; i < tiles.size(); i++) {
tmp += tiles[i].GetC();
}
sort(tmp.begin(), tmp.end());
for (int i = 1; i <= tiles.size(); i++) {
do {
string piece = tmp.substr(0, i);
do {
Word search = Word(piece);
//Überschreibt immer der in Ergebnis existierte Wert
if (find(search) && std::find(ergebnis.begin(), ergebnis.end(), search) == ergebnis.end()) {
ergebnis.push_back(search);
}
} while (next_permutation(piece.begin(), piece.end()));
} while (next_permutation(tmp.begin(), tmp.end()));
}
return ergebnis;
}
int Dictionary::hash(Word new_word) {
int index = 0;
for (auto u : new_word.new_Character) {
index += (int) u.GetC();
}
index = index * (int) new_word.new_Character.at(0).GetC();
index = index * (int) new_word.new_Character.at(new_word.new_Character.size() - 1).GetC();
return index % table_size;
}
void Dictionary::addItem(Word word) {
int index = hash(word);
if (arrWords[index] == nullptr) {
arrWords[index] = new Word(word);
} else {
Word* ptr = arrWords[index];
Word* neu = new Word(word);
while (ptr->getNextWord() != nullptr) {
ptr = ptr->getNextWord();
}
ptr->setNextWord(neu);
}
}
void Dictionary::printHashTable() {
Word* tmp;
for (int i = 0; i < table_size; i++) {
tmp = arrWords[i];
if (tmp != nullptr) {
tmp->printWord();
cout << "Index : " << i;
}
tmp = tmp->getNextWord();
}
}
class Word {
public:
Word();
Word(string m_wort);
int length() const;
int points() const;
friend std::ostream& operator<<(std::ostream& os, const Word& obj);
bool operator==(const Word& right) const; /
bool operator!=(const Word& right) const;
bool contains(const Character& c) const;
Word substr(int start, int end) const;
bool operator<(const Word& right) const;
vector <Character> new_Character;
Word* Next = nullptr;
void setNextWord(Word*);
Word* getNextWord();
void printWord();
string getWordAsString();
CPP File:
void Word::setNextWord(Word* w) {
Next = w;
}
Word* Word::getNextWord() {
return Next;
}
void Word::printWord() {
string s = "";
for (int i = 0; i < new_Character.size(); i++) {
s += new_Character.at(i).GetC();
}
cout << s << endl;
}
string Word::getWordAsString() {
string s;
for (int i = 0; i < new_Character.size(); i++) {
s += new_Character.at(i).GetC();
}
return s;
}

error C3861: identifier not found

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

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