C++ Debugging console app - c++

I'm working on a debugging console app for school, and I get an error when compiling the program.
//DEBUG9-4
//This program creates Student objects
//and overloads < to compare student year in school
#include<iostream>
#include<string>
using namespace std;
class Student
{
private: //MISSING :
int stuID;
int year;
double gpa;
public:
Student(const int i, const int y, const double g); // NO VARIABLES DECLARED HERE
void showYear(); //MISSING THE CURLY BRACES
bool operator < (const Student);
};
Student::Student(const int i, const int y, const double g) // VARIABLES WERE NOT MATCHING
{
stuID = i;
year = i;
gpa = g; // VARIABLE g WAS POST TO BE THE "gpa" VARIABLE
}
void Student::showYear()
{
cout << year;
}
int Student::operator < (const Student otherStu)
{
bool less = false;
if (year < otherStu.year)
less = true;
return less;
}
int main()
{
Student a(111, 2, 3.50), b(222, 1, 3.00);
if(a < b)
{
a.showYear();
cout << " is less than ";
b.showYear();
}
else
{
a.showYear();
cout << " is not less than ";
b.showYear();
}
cout << endl;
return 0;
}
Line: 28 Error: prototype for 'int Student::operator < (const Student& otherStu)' dose not match any in class Students.
Line: 16 Error: candidate is: bool Student::operator<(Student).

You wanted to implement it like this:
bool Student::operator < (const Student otherStu)
{
bool less = false;
if (year < otherStu.year)
less = true;
return less;
}
Because now your definition and declaration doesnt match, thay have different return value.
or you can doi just:
bool Student::operator < (const Student b)
{
return year < b.year ? true : false;
}

Related

Compilation error in C++ when using an assignment operator =?

I have written a program which was given to me as a homework assignment (it's a bit longer). The issue is that it compiles in CodeBlocks but it does not compile in Visual Studio 2017 it says - binary '=': no operator found which takes a right-hand operand of type 'CAutomobile' (or there is no acceptable conversion.
I would like to ask why is that because I could not myself find the error? I tried commenting the operator =function but still the error remained.
#include <iostream>
#include <algorithm>
#include <string>
#include <stdlib.h>
using namespace std;
class CVehicle {
string name;
int year;
public:
CVehicle() {
name = "Car";
year = 1990;
}
CVehicle(string n, int y) {
name = n;
year = y;
}
CVehicle(const CVehicle& vc) {
name = vc.name;
year = vc.year;
}
void setName(string n) {
name = n;
}
void setYear(int y) {
year = y;
}
string getName() {
return name;
}
int& getYear() {
return year;
}
virtual void Print(ostream& os) = 0;
};
class CAutomobile :public CVehicle {
double litres;
public:
CAutomobile() :CVehicle() {
litres = 7.2;
}
CAutomobile(string nm, int yr, double l) :CVehicle(nm, yr) {
litres = l;
}
void setLitres(double l) {
l = litres;
}
double& getLitres() {
return litres;
}
void Print(ostream& os) override {
os << getName() << endl;
os << getYear() << endl;
os << litres << endl;
}
friend bool operator< (CAutomobile a1, CAutomobile a2) {
if (a1.litres < a2.litres) {
return true;
}
return false;
}
CAutomobile operator= (CAutomobile& at) {
CAutomobile au;
au.getName() = at.getName();
au.getYear() = at.getYear();
au.getLitres() = at.getLitres();
return au;
}
CAutomobile operator+(CAutomobile aut) {
CAutomobile a;
a.getLitres() = getLitres() + aut.getLitres();
return a;
}
friend ostream& operator<< (ostream& o, CAutomobile a) {
o << a.getName() << endl;
o << a.getYear() << endl;
o << a.getLitres() << endl;
return o;
}
};
int main()
{
CAutomobile a[] = {
CAutomobile(),
CAutomobile("Wolkswagen",1970,80.5),
CAutomobile("Fiat",1979,21.9),
CAutomobile("Opel",1978,13.7)
};
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) {
cout << "Name" << ' ' << a[i].getName() << endl;
cout << "Year" << ' ' << a[i].getYear() << endl;
cout << "Litres" << ' ' << a[i].getLitres() << endl;
}
int range = 2016 - 1990 + 1;
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) {
a[i].setLitres(rand() % 100 + 1);
a[i].setYear(rand() % range + 1996);
}
//сортираме масива по литри и извеждаме
//най малкия (първия) му елемент
for (int i = 0; i < sizeof(a-1); i++) {
for (int j = 0; j < sizeof(a-1); j++) {
if (a[j].getLitres() > a[j + 1].getLitres()) {
swap(a[j], a[j + 1]);
}
}
}
cout << a[0] << endl;
CAutomobile k = a[0] + a[3];
cout << k.getLitres() << endl;
}
CAutomobile::operator = is completely wrong. It takes a non-const reference and assignes its field to a new object. Instead it should take a const reference and modify current object.
CAutomobile & operator =(CAutomobile const & other)
{
assert(this != ::std::addressof(other)); // check for self-assignment
SetName(other.getName());
SetYear(other.getYear());
SetLitres(other.getLitres());
return *this;
}
This will bring up another problem: getters are not const-qualified, so they should be fixes as well:
string const & getName(void) const {
return name;
}
int const & getYear(void) const {
return year;
}

[C++]Sorting objects by class member's value

In the code shown below, in the function void printExpensiveThanT(..) i'm supposed to print out the destination, distance and the price for the offers which are more expensive than the offer T in the function, sorted in ascending order by the distance value.
I'm not sure what should i use to sort them, i experimented something with vectors but it didn't work out so i deleted it.
Any help would be appreciated.
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
class Transport {
protected:
char destination[100];
int basePrice;
int distance;
public:
Transport() {}
Transport(char *destination, int basePrice, int distance) {
strcpy(this->destination, destination);
this->basePrice = basePrice;
this->distance = distance;
}
virtual ~Transport() {}
virtual int priceTransport() = 0;
friend bool operator<(const Transport &t1, const Transport &t2) {
return t1.distance<t2.distance;
}
int getDistance(){ return distance; }
char *getDestination() { return destination; }
int getPrice() { return basePrice; }
};
class AutomobileTransport : public Transport {
private:
bool ifDriver;
public:
AutomobileTransport() {}
AutomobileTransport(char *destination, int basePrice,int distance, bool ifDriver) : Transport(destination,basePrice,distance) {
this->ifDriver = ifDriver;
}
void setIfDriver(bool ifDriver) {
this->ifDriver = ifDriver;
}
bool getIfDriver() {
return ifDriver;
}
int priceTransport() {
if(ifDriver) {
basePrice+=basePrice*20/100;
}
return basePrice;
}
friend bool operator<(const AutomobileTransport &a1, const AutomobileTransport &a2) {
return a1.distance<a2.distance;
}
};
class VanTransport: public Transport {
private:
int passengers;
public:
VanTransport() {}
VanTransport(char *destination, int basePrice, int distance, int passengers) : Transport(destination, basePrice, distance) {
this->passengers = passengers;
}
void setPassengers(int passengers) {
this->passengers = passengers;
}
int getPassengers() {
return passengers;
}
int priceTransport() {
for(int i = 0; i < passengers; i++) {
basePrice-=200;
}
return basePrice;
}
friend bool operator<(const VanTransport &k1, const VanTransport &k2) {
return k1.distance<k2.distance;
}
};
void printExpensiveThanT(Transport **offers,int n,AutomobileTransport &T) {
Transport *tmp;
for(int i = 0; i <= n; i++){
if(offers[i]->priceTransport() > T.priceTransport())
cout<<offers[i]->getDestination()<<" "<<offers[i]->getDistance()<<" "<<offers[i]->getPrice()<<endl;
}
}
int main() {
char destination[20];
int type,price,distance,passengers;
bool driver;
int n;
cin>>n;
Transport **offers;
offers=new Transport *[n];
for (int i=0; i<n; i++) {
cin>>type>>destination>>price>>distance;
if (type==1) {
cin>>driver;
offers[i]=new AutomobileTransport(destination,price,distance,driver);
} else {
cin>>passengers;
offers[i]=new VanTransport(destination,price,distance,passengers);
}
}
AutomobileTransport at("Ohrid",2000,600,false);
printExpensiveThanT(offers,n,at);
for (int i=0; i<n; i++) delete offers[i];
delete [] offers;
return 0;
}
Since you're dealing with pointers, the easiest thing to do is to use std::vector and std::sort:
#include <vector>
//...
void printExpensiveThanT(Transport **offers, int n, AutomobileTransport &T)
{
std::vector<Transport*> sortedVect;
for (int i = 0; i < n; i++)
{
if (offers[i]->priceTransport() > T.priceTransport())
sortedVect.push_back(offers[i]); // add this item to the vector
}
// sort the vector based on the dereferenced pointers and their respective
// operator <
std::sort(sortedVect.begin(), sortedVect.end(),
[](Transport* left, Transport* right) { return *left < *right; });
// print out the values
for (auto it : sortedVect)
cout << (*it).getDestination() << " " << (*it).getDistance() << " " << (*it).getPrice() << "\n";
}
Also, your original code looped one more than it should (i <= n was wrong).
Edit:
If your compiler doesn't support the C++ 11 syntax, here is an alternate solution:
#include <vector>
//...
bool Sorter(Transport* left, Transport* right)
{ return *left < *right; }
void printExpensiveThanT(Transport **offers, int n, AutomobileTransport &T)
{
std::vector<Transport*> sortedVect;
for (int i = 0; i < n; i++)
{
if (offers[i]->priceTransport() > T.priceTransport())
sortedVect.push_back(offers[i]); // add this item to the vector
}
// sort the vector based on the dereferenced pointers and their respective
// operator <
std::sort(sortedVect.begin(), sortedVect.end(), Sorter);
// print out the values
std::vector<Transport*>::iterator it = sortedVect.begin();
while (it != sortedVect.end())
{
cout << (*it).getDestination() << " " << (*it).getDistance() << " " << (*it).getPrice() << "\n";
++it;
}
}

Array of derived class stored in parent class

I don't think I quite understand how to store an array of a derived class in its parent class.
I keep getting errors
Error C3646 'list': unknown override specifier
Error C2065 'list': undeclared identifier
Here is the code I have
#include <iostream>
#include <string>
using namespace std;
class GameScores
{
public:
GameEntry list[9];
void inputList(GameEntry x);
void sortList();
void removeList(int r);
void printList();
GameScores();
};
class GameEntry :public GameScores
{
public:
GameEntry(const string& n = "", int s = 0, const string d = "1/1/99");
string getName() const;
int getScore() const;
string getDate() const;
string setName(string n);
int setScore(int s);
string setDate(string d);
private:
string name;
int score;
string date;
};
GameScores::GameScores()
{
GameEntry list[9];
}
void GameScores::inputList(GameEntry x)
{
for (int i = 0; i < 10; i++)
if (x.getScore() >= list[i].getScore())
{
list[i + 1] = list[i];
list[i] = x;
}
}
void GameScores::sortList()
{
GameEntry swap;
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10 - 1; j++)
{
if (list[j].getScore() > list[j].getScore() + 1)
{
swap = list[j];
list[j] = list[j + 1];
list[j + 1] = swap;
}
}
}
}
void GameScores::removeList(int r)
{
for (int i = r; i < 10; i++)
list[i - 1] = list[i];
list[9].setScore(0);
list[9].setName(" ");
list[9].setDate(" ");
}
void GameScores::printList()
{
cout << "Top Scores" << endl;
for (int i = 0; i < 10; i++)
cout << list[i].getScore() << " " << list[i].getName() << " " << list[i].getDate() << endl;
}
GameEntry::GameEntry(const string& n, int s, const string d) // constructor
: name(n), score(s), date(d) { }
// accessors
string GameEntry::getName() const { return name; }
int GameEntry::getScore() const { return score; }
string GameEntry::getDate() const { return date; }
string GameEntry::setName(string n)
{
name = n;
}
int GameEntry::setScore(int s)
{
score = s;
}
;
string GameEntry::setDate(string d)
{
date = d;
}
int main()
{
GameEntry p1("John", 90, "9/9/98"), p2("Jane", 95, 8/21/98), p3("Bob", 60, "7/11/99"), p4("Jo", 92, "6/4/97");
GameScores topScores;
topScores.inputList(p1);
topScores.inputList(p2);
topScores.inputList(p3);
topScores.inputList(p4);
topScores.printList();
return 0;
}
This design is very questionable. What purpose is being served by making the second class inherit the first? It looks like you'd end up with each member of the array containing an additional array with all its siblings. Don't you want only one array? You need to rethink this from an earlier point.
If you really have a reason for a parent class to contain an array of the child class, maybe you should define an interface (abstract base class) that both classes implement.
To use GameEntry as a type in your GameScores class , you must forward-declare the class like so :
class GameEntry;
class GameScores
{
public:
GameEntry list[9];
void inputList(GameEntry x);
void sortList();
void removeList(int r);
void printList();
GameScores();
};

Class with Pointer and Dynamic Arrays

I'm currently writing a program that will help a college keep track of which students are in what clubs. This code will be pasted into existing code that works, as provided by my professor.
Could someone please look my code over, and help me work through my mistakes? I included comments to explain what everything should do.
Also, please note this is an assignment and I cannot change anything about the class. I'm also a beginner, so keep it simple, please. Your help will be extremely appreciated beyond all measure.
class Club
{
public:
Club();
Club(Club &c);
Club(string cname);
void addMember(string name);
void removeMember(string name);
string getClubName() const;
string setClubName(const string& nameOfClub);
void loadClub();
bool isMember(string& name) const;
string getAllMembers() const;
friend Club mergeClubs(Club& c1, Club& c2);
~Club();
private:
string *members;
int numMembers;
string clubName;
};
Club::Club()
{
clubName = "";
numMembers = 0;
}
Club::Club(Club &c)
{
numMembers = c.numMembers;
members = new string [numMembers];
for (int i = 0; i < numMembers; i++)
{
members[i] = c.members[i];
}
//copy constructor
//watch out for memory leaks
}
Club::Club(string cname)
{
clubName = cname;
//cname should be saved as the club's name in the clubName variable
}
void Club::addMember(string name)
{
string *m;
m = new string [numMembers];
string *members = m;
for (int i = 0; i < numMembers; i++)
{
for (int j = 0; j < name.length(); i++)
{
m[i] = name[j];
}
}
delete [] m;
//adds new member to the club
//records their name in the members variable
//may need a dynamic array to make this work, watch for memory leaks!
}
void Club::removeMember(string name)
{
string *m;
m = new string [numMembers];
string *members = m;
for (int i = 0; i < numMembers; i++)
{
if ( m[i] == name)
{
m[i] = "";
}
}
delete [] m;
//deletes the person from the array in members
//will do nothing if the person is not in the array to begin with
//may require dynamic array to make this work- watch for memory leaks!
//if the person's name appears more than once, just delete the first instance
}
string Club::getClubName() const
{
return clubName;
//getter of clubName
}
string Club::setClubName(const string& nameOfClub)
{
return clubName = nameOfClub;
//setter of clubName
}
void Club::loadClub()
{
//should print "tell me the name of the next member of the club"
//reads into the variable name
//uses addMember() to add that person to the club
//the input should include up to the line break as the name, so it should take in "jane doe" as an entry
//keeps asking for more names until the user enters a blank entry
string name;
do
{
cout << "Tell me the name of the next member of the club, ";
cout << "or submit a blank entry to stopent ering names." << endl;
getline(cin, name, '\n');
addMember(name);
} while (name != "");
}
bool Club::isMember(string& name) const
{
/*for (int i = 0; i < numMembers; i++)
{
for (int j = 0; j < name.length(); j++)
{
if (members[i] == name)
{
return true;
}
else
{
return false;
}
}
}*/
for (int i = 0; i < numMembers; i++)
{
if (members[i] == name)
{
return true;
}
return false;
}
//returns true if the person is a member of the club, false otherwise
}
string Club::getAllMembers() const
{
for (int i = 0; i < numMembers; i++)
{
return members[i];
cout << ", ";
}
cout << endl;
//returns a string of all the names of the members of the club
//commas and spaces separating every entry of the list
//should not be a comma following the last name in the list
}
Club mergeClubs(Club& c1, Club& c2)
{
//creates a new club from 2 existing clubs
//combined club name should be Club 1/Club 2
Club temp;
temp.clubName = c1.clubName + "/" + c2.clubName;
return temp;
}
Club::~Club()
{
delete [] members;
//destructor
//watch out for memory leaks
}
For some reason I cannot fathom I have (mostly) corrected this program for you. There are still some nasty things like passing copies of strings into const functions but fixing these would be mere optimisations. At least this program is logically correct.
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <sstream>
using namespace std;
class Club
{
public:
Club();
Club(const Club &c);
Club(string cname);
void addMember(string name);
void removeMember(string name);
string getClubName() const;
string setClubName(const string& nameOfClub);
void loadClub();
bool isMember(const string& name) const;
string getAllMembers() const;
friend Club mergeClubs(Club& c1, Club& c2);
~Club();
private:
vector<string> members;
string clubName;
};
Club::Club()
: members()
, clubName()
{
}
Club::Club(const Club &c)
: members(c.members)
, clubName(c.clubName)
{
}
Club::Club(string cname)
: members()
, clubName(cname)
{
}
void Club::addMember(string name)
{
members.push_back(name);
}
void Club::removeMember(string name)
{
members.erase(remove(members.begin(), members.end(), name), members.end());
}
string Club::getClubName() const
{
return clubName;
//getter of clubName
}
string Club::setClubName(const string& nameOfClub)
{
return clubName = nameOfClub;
//setter of clubName
}
void Club::loadClub()
{
//should print "tell me the name of the next member of the club"
//reads into the variable name
//uses addMember() to add that person to the club
//the input should include up to the line break as the name, so it should take in "jane doe" as an entry
//keeps asking for more names until the user enters a blank entry
string name;
do
{
cout << "Tell me the name of the next member of the club, ";
cout << "or submit a blank entry to stopent ering names." << endl;
getline(cin, name, '\n');
addMember(name);
} while (name != "");
}
bool Club::isMember(const string& name) const
{
return find(members.begin(), members.end(), name) != members.end();
}
string Club::getAllMembers() const
{
stringstream result;
vector<string>::const_iterator b = members.begin(), e = members.end();
for (bool comma = false ; b != e; ++b, comma = true)
{
if (comma) {
result << ", ";
}
result << *b;
}
return result.str();
}
Club mergeClubs(Club& c1, Club& c2)
{
Club temp(c1.clubName + "/" + c2.clubName);
struct memberAdd {
Club& _club;
memberAdd(Club& club) : _club(club) {}
void operator()(const string& member) {
_club.addMember(member);
}
};
for_each(c1.members.begin(), c1.members.end(), memberAdd(temp));
for_each(c2.members.begin(), c2.members.end(), memberAdd(temp));
return temp;
}
Club::~Club()
{
//destructor
//watch out for memory leaks
}
int main()
{
Club boys("red");
boys.addMember("Ben");
boys.addMember("Paul");
Club girls("blue");
girls.addMember("Lucy");
girls.addMember("Hermione");
Club unisex = mergeClubs(boys, girls);
cout << unisex.getClubName() << " has the following members: " << unisex.getAllMembers() << endl;
}
Some initial comments:
The copy constructor should take a const Club& like this:
Club(const Club& club)
members and numMembers are anachronistic. Use a std::vector for members and drop the numMembers altogether (std::vector has a size() method).
Club::Club does not initialise members or numMembers. This will result in a possible crash in the destrutor. This would be solved if you replaced them with a vector.
the logic in addMember does not make sense.
nor in removeMember
isMember should take a const string& and you would be well advised to write it in terms of std::find() (#include <algorithm>)
I could go on...

Sort string array by alphabet and display values

I am trying to sort an array with is filled with string values by alphabet. It already works with integers. I think the problem isn’t about the sorting, it is about displaying it.
But here is the code:
#include <iostream>
#include <algorithm>
using namespace std;
class Ticket {
int ticketnr;
string name;
public:
Ticket() {
ticketnr = 0;
name = "NN";
};
Ticket(int _tickernr, string _name) {
ticketnr = _tickernr;
name = _name;
}
friend bool upSort(Ticket a, Ticket b);
};
bool upSort(Ticket a, Ticket b) {
return (a.name > b.name);
}
int main() {
Ticket vip(1435, "Beckenbauer");
Ticket frei;
Ticket array[10] = {vip, Ticket(2100, "Maier")};
sort(array, array + 10, upSort);
for (int i = 0; i < 10; i++) cout << array[i] << endl;
}
Xcode says: invalid operands to binary expression
Thank you and best regards
Flo
There is probably nothing wrong with the sort. What is clearly wrong is that you don't have an ostream& operator<< for Ticket, so you cannot do this:
for (int i = 0; i < 10; i++) cout << array[i] << endl;
// ^^^^^^^^^^^^^^^^
So,
friend
std::ostream& operator<<(std::ostream& o, const Ticket& t)
{
return o << t.ticketnr << " " << t.name;
}