C++ Expression must be a modifiable lvalue - c++

writing this program for my c++ class and im running into an issue. My program reads the inputtted name and stores it into name it then wants to check for correct parameters under _name.. here are my class and its header file.
My error is specifically under ::setName where i want to check or set my inputted name with _name for correct output under ::display()
PhoneNumber.cpp
using namespace oop244;
void PhoneNumber::display() const{
cout << "name: " << _name << ", Phone number: (" << _areacode << ") " << _localNumber / 10000 << "-" << _localNumber % 10000 << endl;
}
bool PhoneNumber::isValid() const
{
if (correctNum == false && correctArea == false){
cout << _name << " does not have a valid phone number." << endl;
return false;
}
else{
return true;
}
}
void PhoneNumber::setName(const char name[])
{
cout << name << endl;
_name = name;
}
PhoneNumber.h
#define MAX_NAME_LENGTH 40
#define PHNO_MAX 999999
#define PHNO_MIN 100000
#define AREACODE_MIN 100
#define AREACODE_MAX 999
namespace oop244{
class PhoneNumber{
private:
char _name[MAX_NAME_LENGTH + 1];
int _areacode;
int _localNumber;
bool _validPhoneNumber;
public:
void setName(const char name[]);
void setPhoneNumber(int areaCode, int number);
void display() const;
bool isValid() const;
};
};

use standard string
#include <string>
and use
std::string _name;
in your class declarations instead of
char _name[MAX_NAME_LENGTH + 1];
alternatively use c-style str-functions, as suggested in another answer

You can't assign raw arrays. You need to copy the contents.
Assuming your class teacher forces you to use char arrays, you can for example use strncpy to copy the characters:
strncpy(_name, name, MAX_NAME_LENGTH);
You need to #include <cstring> for this.
If your class teacher allows it, better use std::array<char,MAX_NAME_LENGTH> or even std::string. Both can be copied by assigning.

Related

.Can there be a easier function defining - (to.string()) below

// The function which i was required to make was to.string() in the class,Which i had no idea how to make.This is an odd function(not comparing with the math one.)which returns value in two different types of data types i.e(string,integer).The only thing stuck me was assigning a variable after making (string to.string()) function//The return value of function is something like
[age,first_name,last_name,standard](without the square brackets with the commmasin the output)
p.s=need a simpler function without using vector header.
#include <iostream>
#include <sstream>
using namespace std;
class Student{
public :
void set_age(int no){
age_no=no;
}
void set_standard(int no){
std_no=no;
}
void set_first_name(string identity){
name_letter=identity;
}
void set_last_name(string identity2){
last_name_letter = identity2;
}
int get_age(){
return age_num;
}
int get_standard(){
return std_no;
}
string get_first_name(){
return name_letter;
}
string get_last_name(){
return last_name_letter;
}
private :
int age_no;
int std_no;
string name_letter;
string last_name_letter;
};
int main() {
int age, standard;
string first_name, last_name;
cin >> age >> first_name >> last_name >> standard;
Student st;
st.set_age(age);
st.set_standard(standard);
st.set_first_name(first_name);
st.set_last_name(last_name);
cout << st.get_age() << "\n";
cout << st.get_last_name() << ", " << st.get_first_name() << "\n";
cout << st.get_standard() << "\n";
cout << "\n";
cout << st.to_string();
return 0;
}
If you want to create a string with the format age, first_name, last_name, standard then you could do something like
class Student
{
public:
...
std::string to_string() const;
...
};
std::string Student::to_string() const
{
return std::to_string(get_age()) + ", " +
get_first_name() + ", "
get_last_name() + ", "
std::to_string(get_standard());
}
As an aside, I would suggest making all of your getter functions const for example
int get_age() const;
This denotes that the method will not mutate or modify any of the values of the class's member variables.

C++ How to call a void function without errors?

This is an assignment of mine that I picked to do but I am not sure how to fix the error message I am getting at cout << contact.getInformation() << endl;without changing the Void function to a different type or changing the main function (which I am trying to avoid). I think my lack of understanding is in how cout and void functions work together. I tried to remove the cout from the function but that did not work and the only way I could make the code run was when I replaced cout << contact.getInformation() << endl; with contact.getInformation() which I am trying to avoid. I just want the inside of the void function to print when I call cout << contact.getInformation() << endl;
Any help is welcome! Thank you!
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class Contact{
public:
Contact(int id, string name, string telephone, int age)
: _id{ id }, _name{ name }, _telephone{ telephone }, _age{ age } {}
int id() { return _id; }
string name() { return _name; }
string telephone() { return _telephone; }
int age() { return _age; }
void getInformation() {
cout << "ID: " + to_string(_id) + "\n" +
"NAME: " + _name + "\n" +
"TEL: " + _telephone + "\n" +
"AGE: " + to_string(_age) + "\n";
}
private:
int _id;
string _name;
string _telephone;
int _age;
};
int main() {
Contact contact{1, "Michael", "555-555-5555", 15};
cout << contact.getInformation() << endl;
}.
EDIT: Thanks all! I see now that it is impossible to do with those restrictions.
The code you've provided have many issues. You can avoid them if you read some good C++ book, my advice is Scott Meyers Effective C++: 55 Specific Ways to Improve Your Programs and Designs.
don't use using directive unless really necessary. In most cases for std namespace - it is not.
Pass function arguments of non primitive type by reference/const reference rather by value or pointer
Understand const keyword and it usage
Understand constructor static initialization bocks
Understand c++ streams
This is how you code should looks like:
#include <iostream>
#include <string>
class Contact {
public:
Contact(int id,const std::string& name,const std::string& telephone, int age):
_id( id ),
_name( name ),
_telephone( telephone ),
_age( age )
{}
int id() const {
return _id;
}
std::string name() const {
return _name;
}
std::string telephone() const {
return _telephone;
}
int age() const {
return _age;
}
private:
int _id;
std::string _name;
std::string _telephone;
int _age;
};
std::ostream& operator<<(std::ostream& to,const Contact& c)
{
to << "ID: " << c.id() << '\n';
to << "NAME: " << c.name() << '\n';
to << "TEL: " << c.telephone() << '\n';
to << "AGE: " << c.age() << '\n';
to.flush();
return to;
}
int main(int argc, const char** argv)
{
Contact contact = {1, "Michael", "555-555-5555", 15};
std::cout << contact << std::endl;
return 0;
}
What you are asking is not possible. The two conditions you have set (i.e. 1. Do not change the void function to another type, and 2. Do not alter the main method) make it impossible to change your code in some other way so as for the main function to produce the intended outcome.
You can either alter your void function to one that returns something 'printable', e.g. a string, or you can keep your void function printing to cout directly, but then change the main function to call this on its own, outside the context of a cout << construct.
(Or, preferably, as has also been pointed in the comments, instead of void, overload the << operator to make cout work with your specific object type)
The name getInformation suggests it should, well, get the information and not print it.
Therefore you probably want this:
string getInformation() {
return "ID: " + to_string(_id) + "\n" +
"NAME: " + _name + "\n" +
"TEL: " + _telephone + "\n" +
"AGE: " + to_string(_age) + "\n";
}
Instead of this:
void getInformation() {
cout << "ID: " + to_string(_id) + "\n" +
"NAME: " + _name + "\n" +
"TEL: " + _telephone + "\n" +
"AGE: " + to_string(_age) + "\n";
}
Not changing main nor getInformation is not possible.

C++: No matching function to call to const char

im trying to create a object called player in class player.
#include <string>
#ifndef PLAYER_HH
#define PLAYER_HH
using namespace std;
class Player
{
public:
Player(string name, int points);
const string get_name();
int get_points();
void add_points(int pts);
bool has_won();
private:
string _name;
};
#endif // PLAYER_HH
from player.cpp:
#include <string>
using namespace std;
Player::Player(string name):
_name(name), _points(0){
}
Now, the problem is, in the main function i get this error:
error: no matching function for call to ‘Player::Player(const char [6])’
Player player1 = Player("Matti");
^
Shouldn't the compiler be able to convert it to a string?
edit: Here is the full main.cpp that i'm not supposed to be changing:
#include <cstdlib>
#include <iostream>
#include <string>
#include "player.hh"
int main()
{
Player player1 = Player("Matti");
Player player2 = Player("Teppo");
Player* in_turn = 0;
int turn = 1;
while (true)
{
if (turn % 2 != 0)
{
in_turn = &player1;
}
else
{
in_turn = &player2;
}
std::cout << "Enter the score of player " << in_turn->get_name()
<< " of turn " << turn << ": ";
int pts = 0;
std::cin >> pts;
in_turn->add_points(pts);
if (in_turn->has_won())
{
std::cout << "Game over! The winner is " << in_turn->get_name() << "!" << std::endl;
return EXIT_SUCCESS;
}
std::cout << std::endl;
std::cout << "Scoreboard after turn " << turn << ":" << std::endl;
std::cout << player1.get_name() << ": " << player1.get_points() << "p" << std::endl;
std::cout << player2.get_name() << ": " << player2.get_points() << "p" << std::endl;
std::cout << std::endl;
turn += 1;
}
return EXIT_SUCCESS;
}
You guys are awesome with your fast answers :-)
You declared the constructor of player as Player(string name, int points);.
If you define a function with two parameters you have to use both.
Create your object with
Player player1 = Player("Matti", 0);
If you still want to call it with just one parameter you have to set a default value like this.
class Player
{
public:
...
Player(string name, int points = 0); // replace 0 with whatever you want to be default.
...
}
Then you can use both variants. The one above and the one you attempted
Player player1 = Player("Matti");
Of course the function header of your definition has to match the one in the declaration:
Player::Player(string name, int points):
_name(name), _points(points){
}
It's important not to write the default value inside dhe definition because this will most likely produce an compiler error.
The conversion from const char[6] to std::string will work and is not the issue here.
Your constructor has two parameters, you cannot simply omit the second one. If you like to create Player objects with a default score, declare your constructor as:
Player(string name, int points = 0);
First of all, you declare your constructor having two parameters:
Player(string name, int points);
but define it as having only one:
Player::Player(string name):
_name(name), _points(0){
}
That should give you compilation error. Either remove the second param from the declaration in class body and keep main.cpp as it is or add second param to the definition in player.cpp:
Player::Player(string name, int points):
_name(name), _points(points){
}
and then specify value for 'points' explicitly:
Player("Matti", 0);
You can also have both - just add default value for points:
class Player
{
...
Player(string name, int points = 0);
};
Then, both of these lines will work:
Player player1 ("Matti");
Player player2 ("Matti", 0);

not a class or namespace error

I'm struggling with an error that I haven't been able to find the solution for. I can't seem to understand why "Location" is not found as a class. here is me header file:
#ifndef CLASS2_HPP
#define CLASS2_HPP
class Passenger
{
public:
enum class Location
{
Business,
Economy,
Vip
};
Passenger(Location clas_s, char* firstName, char* secondName, int seat, int terminal, float time_of_departure);
const char* get_location() const;
int get_seat() const;
int get_terminal() const;
float get_time() const;
char* get_firstName() const;
char* get_secondName() const;
void print() const;
private:
Location _clas_s;
char _firstName;
char _secondName;
int _seat;
int _terminal;
float _time_of_departure;
};
#endif // CLASS2
And here is my cpp file:
#include <iostream>
#include "Class2.hpp"
using namespace std;
Passenger::Passenger(Location clas_s, char* firstName, char* secondName, int seat, int terminal, float time_of_departure)
: _clas_s(clas_s), _firstName(firstName), _secondName(secondName), _seat(seat), _terminal(terminal), _time_of_departure(time_of_departure) {};
void Passenger::print() const
{
cout << "Your name is " << _firstName
<< " " << _secondName << endl
<< "Your class is " << get_location() << endl
<< "Your seat is " << _seat << endl
<< "Your terminal is " << _terminal << endl
<< "Your time of departure is " << _time_of_departure << endl;
}
const char* Passenger::get_location() const
{
switch (_clas_s)
{
case Location::Business : return "Business";
case Location::Economy : return "Economy";
case Location::Vip : return "Vip";
}
}
int main() {
Passenger p((Passenger::Location::Vip), 'John', 'Johnson', 25, 2, 13.53);
p.print();
return 0;
}
Thanks in advance.
It seems you are on C++03, so make
enum Location
{
Business,
Economy,
Vip
};
And
case Business : return "Business";
case Economy : return "Economy";
case Vip : return "Vip";
Edit: I was wrong about
You forgot to set Passenger::Passenger(Passenger:: Location
clas_s,...
When you create your Passenger you have to pass strings using the double quotes, not single quotes (which are for single characters only):
Passenger p((Passenger::Location::Vip), "John", "Johnson", 25, 2, 13.53);
Then, you have declared _firstName and _secondName as char. But this would only let you store a single character! A simple solution is to use an array (but it would be much better to use the appropriate structure, which is a std::string, so that you don't need to worry about the size):
char _firstName[50];
char _secondName[50];
Then, to initialize them you need to #include <cstring> and, in the constrcutor's body (not in the initializer list!)
strcpy(_firstName, firstName);
strcpy(_secondName, secondName);
(Again, a std::string would be better, you could set it in the initializer list)
With these changes it compiles and the output, as expected, is:
Your name is John Johnson
Your class is Vip
Your seat is 25
Your terminal is 2
Your time of departure is 13.53
Tested on ideone.
Are you getting this error:
Class.cpp:24:14: warning: use of enumeration in a nested name specifier is a C++11 extension [-Wc++11-extensions]
case Location::Business : return "Business";
As it states, its a C++11 feature, so try compiling your code with "-std=c++11" option. Or change the switch case with integer values:
switch (_clas_s)
{
case 0: return "Business";
case 1: return "Economy";
case 2: return "Vip";
}
Hope that helps.

Storing a objects derived from an abstract base class with maps in a vector array of base class pointers

I'm writing a program that uses OOP to store student records. At the moment I only have two classes, one for each individual course module called 'Courses', and one ( well two if you count the abstract base class) for the type of degree programme called 'Physics' derived from the 'Records' base class.
I'm using two maps in the program. One to store the individual courses for each individual record and sort them by course code, and one to store all the records and sort them by ID numbers.
I planned on having the user input all student information, including codes, storing this in a vector (named 'prec' in the code), then pushing the vector elements into the map used to store all the records. The code is far from finished, I was just attempting to run it to see if I was on the right track.
The code builds without any errors, but when I attempt to run it, it comes up with the error message: " Debug assertion failed: expression vector subscript out of range". I feel this may have something to do with the way I am using individual vector elements to call my functions to store courses in the maps but I cant quite get it, any help would be much appreciated!
Here are my files:
header file:
#ifndef MY_CLASS_H // Pre-processor directives to prevent multiple definition
#define MY_CLASS_h
#include <iostream>
#include <string>
#include <utility>
#include <map>
#include <fstream>
using std::string;
using std::ostream;
using std::map;
using std::cout;
using std::endl;
using std::cin;
namespace student_record // Defines the namespace student_record in which the classes are defined
{
class Course { /* Create class Course for individual courses, is this better than incorporating
all the data separately into the Record class below? Class contains course name, mark achieved and mark weight and course ID */
protected:
string course_name;
double course_mark;
int course_Id;
public:
Course() {course_name= "Null"; // Default constructor for null course
course_mark=0;
}
Course(string course_namein, double course_markin, int course_Idin) {course_name=course_namein; // Parametrized constructor to create course with set name, mark, weight and course ID
course_mark=course_markin;
course_Id=course_Idin;}
~Course() {course_name.erase(0,course_name.size());} // Destructor to delete the course name
// Access functions to get name, mark and weight //
double getmark() const {return course_mark;}
string getname() const {return course_name;}
int getid() const {return course_Id;}
friend ostream & operator << (ostream &os, const Course &c); // Friend function to overload the insertion operator for courses
};
class Record
{ // Create class Record as abstract base class for all inherited degree classes
protected:
string student_name;
int studentid;
int years;
public:
Record() {student_name="Casper";
studentid=0;
years=0;} // Default constructor for class Record, produces empty record
Record(string name, int number, int time) {student_name=name;
studentid=number;
years=time;} // Parametrized constructor for class Record
~Record() {student_name.erase(0, student_name.size());} // Destructor to delete the student name
virtual int getid()const=0;
virtual int getyears()const=0;
virtual void show_record()const=0;
virtual void print_record(string *filename)const=0;
virtual void degree_class()const=0;
virtual void insert_class()=0;
/* Virtual functions defined to be used in the derived classes (subjects ie, Physics, stamp collecting, etc...)
Thus the base class Record is abstract*/
};
class Physics: public Record
{
private:
string degree_name;
typedef map <int, Course> course_map;
course_map modules;
void searchdatabase (course_map &courses, int coursecode)const; // Uses iterator to search map for corresponding course to inputted key ( remember to move to function definitions)
string get_name (const int i, course_map &temp) const{ return temp[i].getname();}
double get_mark(const int i, course_map &temp)const{ return temp[i].getmark();} // Functions to return the mark, weight and name of a given course corresponding to inputed course code
int getid()const{return studentid;}
int getyears()const{return years;}
void show_record()const;
void print_record( string *filename) const;
void degree_class()const;
void insert_class();
// Function to insert record into map
public:
Physics():Record(){degree_name= "Physics ";}
Physics(string name,int Id, int time):Record( name, Id, time){degree_name= "Physics";}
~Physics() {degree_name.erase(0, degree_name.size());}
};
}
#endif
function definitions:
#include <iostream>
#include <string>
#include <utility>
#include <map>
#include <fstream>
#include <vector>
#include "Database_header.h"
using namespace std;
using namespace student_record;
ostream & student_record::operator<< (ostream &os, const Course &c)
{
os<< "Course code" << c.course_Id << " \n Course name: " <<c.course_name << " \n Mark " << c.course_mark <<endl;
return os;
}
// Function to insert classes //
void Physics::insert_class()
{
int courseid;
string coursename;
double mark;
cout << " Enter course code " << endl;
cin >> courseid;
cout << " \n Enter course name " << endl;
cin >> coursename;
cout << " \n Enter mark achieved " << endl;
cin >> mark;
Course temp (coursename, mark, courseid);
modules.insert(pair<int, Course>(courseid, temp));
}
void Physics::searchdatabase(course_map &courses, int coursecode) const // Function to search for specific course mark based on course code, need to modify this!!!!
//takes in a map as its argument, although i suppose can use student.modules?
{
course_map::iterator coursesIter;
coursesIter=courses.find(coursecode);
if(coursesIter != courses.end())
{
cout << " Course Code " <<
coursecode << " corresponds to " <<
coursesIter ->second << endl;
}
else { cout << " Sorry, course not found " << endl; }
}
void Physics::print_record( string *filename) const // Function for printing record to the file
{
ofstream myoutputfile;
myoutputfile.open(*filename,ios::app);
if(!myoutputfile.good())
{
// Print error message and exit
cerr<<"Error: file could not be opened"<<endl;
}
if(myoutputfile.good())
{
myoutputfile << "Student name: " << student_name << endl
<< "\n Student ID: " << studentid << endl
<< "\n Year: " << years << endl;
course_map::iterator modulesiter; // Iterator to print out courses using overloaded << function (I think?)
for(modulesiter==modules.begin();modulesiter!=modules.end();modulesiter++)
{
myoutputfile<<modulesiter->second << endl;
}
}
}
void Physics::show_record() const // Function for showing specific student record on screen ( with iterator for map of courses)
{
cout << "Student name: " << student_name;
cout << "\n Student ID: " << studentid;
cout << "\n Years on course: " << years;
cout << "\n Courses and grades: ";
course_map::iterator modulesiter; // Iterator to print out courses using overloaded << function (I think?)
for(modulesiter==modules.begin();modulesiter!=modules.end();modulesiter++)
{
cout<<modulesiter->second << endl;
}
}
void Physics::degree_class()const
{
double temp;
vector<double> dynarr; // Create a vector array to store the grades extracted from the course map for each student
course_map::iterator modulesiter;
for(modulesiter==modules.begin();modulesiter!=modules.end();modulesiter++) // Iterate through map and push values into each vector
{
Course ghost;
ghost=modulesiter->second;
dynarr.push_back(ghost.getmark());
}
double sum(0);
for(int i(0);i<=dynarr.size();i++)
{
sum+=dynarr[i];
}
temp=sum/dynarr.size();
if( temp>=40 && temp <=49.9)
{
cout << "The student has achieved a 3rd class degree with an average of: \n "
<< temp;
}
else if( temp>=50 && temp <=59.9)
{
cout << "The student has achieved a 2:2 degree with an average of: \n "
<< temp;
}
else if( temp>=60 && temp <=69.9)
{
cout << "The student has achieved a 2:1 degree with an average of: \n "
<< temp;
}
else if( temp>=70)
{
cout << "The student has achieved a 1st class degree with an average of: \n "
<< temp;
}
else { cout << "The student has failed the degree " << endl;}
}
and main cpp file:
#include <iostream>
#include <utility>
#include <map>
#include <iomanip>
#include <vector>
#include "Database_header.h"
#include <fstream>
using namespace std;
using namespace student_record;
void main()
{
// Create map to store students with ID keys //
string full_name;
int id;
int time;
string degree_name;
vector<Record*> prec;
// Vector of base class pointers to store all the different records first. No need to specify length as it is a vector! (Advantage over dynamic array?)
char student_test('y'); // Condition for adding students to the record //
int q(0);
while (student_test=='y' || student_test=='Y')
{
// Counter for while loop
cout<< " \n Please enter the student name " << endl;
getline(cin, full_name);
// Enter student name, check it is a string? //
cout<< "\n Please enter student ID " << endl;
cin >> id;
// Check if not integer or number, if not need error message //
cout << "\n Please enter the number of years on the course " << endl;
cin >> time;
// Check if not integer or number, if not need error message //
cout<< "\n Please enter degree type " << endl;
cin>>degree_name;
if(degree_name=="Physics" || degree_name=="physics") // create object of appropriate derived class ( Physics, Chem, Maths, Bio)
{
prec.push_back(new Physics(full_name, id, time));
}
char class_test('y'); // test condition for class insertion loop
while(class_test=='y') // Add courses+marks into course map
{
cout << " \n Add classes to student record " << endl;
prec[q]->insert_class();
cout << " \n Add another class? Y/N" << endl;
cin>>class_test;
}
cout << "Enter another student? Y/N " << endl;
cin >> student_test;
if(student_test=='N' && student_test=='n')
{
cout << "\n Thank you for using the student database, Goodbye !" << endl;
}
q++; // increment counter, to keep track of of vectors of base class pointers, and also be able to output number of students
}
// Next insert all records into map //
typedef map<int, Record*> studentlist;
studentlist studentmap;
for(int i(0); i<=prec.size(); i++)
{
studentmap.insert(pair<int, Record*> (prec[i]->getid(), prec[i]));
}
}
Thanks so much!
for(int i(0); i<=prec.size(); i++)
{
studentmap.insert(pair<int, Record*> (prec[i]->getid(), prec[i]));
}
Should be i < prec.size() instead of <=