passing an array of character to function c++ - c++

Let's say I have the following:
char cipan[9];
then what should I pass to the function? how about the get and set method??
I'm currently doing like this
set method
void setCipan(char cipan[]){
this->cipan = cipan;
}
and the get method
char getCipan(){
return cipan;
}
and I get an error when compiling??
Im totally blur.. can someone explain what should i pass to the function??
class userData{
private:
string name;
char dateCreate[9];
void userDataInput(string name,char dateCreate[]){
this->name = name;
this->dateCreate = dateCreate;
}
public:
//constructor
userData(string name){
userDataInput(name,dateCreate);
}
userData(string name,char dateCreate[]){
userDataInput(name,dateCreate);
}
//mutator methods
void changeName(string name){this->name = name;}
void changeDateCreate(char *dateCreate){this->dateCreate = dateCreate;}
//accesor methods
string getName(){return name;}
char *getDateCreate(){return dateCreate;}
};

I'd do the following:
void setCipan(const char* new_cipan)
{
strcpy(cipan, new_cipan);
}
const char* getCipan() const
{
return cipan;
}
Of course, the better approach is to use std::string:
void setCipan(const string& new_cipan)
{
cipan = new_cipan;
}
string getCipan() const
{
return cipan;
}

Constructor's purpose is to initialize class variables. I think it's unnecessary to call another method in the constructor to do initialization.
void userDataInput(string name,char dateCreate[]){
this->name = name;
this->dateCreate = dateCreate; // Both the dateCreate are class variables.
}
userData(string name){
userDataInput(name,dateCreate); // dateCreate is already a class variable.
}
dateCreate is the class scope variable. You are just passing it to a method, and re-assigning the same to dateCreate. Assignment operation doesn't copy elements of one array to another and are invalid operations.
To copy array elements, use std::copy instead.

Related

Why do I get this error "expression must be an lvalue or a function designator" for some of my data members?

I am trying to create a function that prints whatever I feed it from the class I created. I can only get some of my class object data members to work with my print function.
I have tried using pointers and references in some source codes I found online but they didn't work. After working on this problem for about a week now I feel like I have tried everything.
void print(string* object);
enum Degree { SECURITY = 1, NETWORKING = 2, SOFTWARE = 3};
class Student {
public:
Student(string ID, string first, string last, string Email, int Age, int days1, int days2, int days3, Degree StudentDegree) {
studentID = ID;
firstName = first;
lastName = last;
email = Email;
age = Age;
daysTillComplete[0] = { days1 };
daysTillComplete[1] = { days2 };
daysTillComplete[2] = { days3 };
studentDegree = StudentDegree;
return;
}
string getID() const;
void setID(string ID);
string getFirst() const;
void setFirst(string ID);
string getLast() const;
void setLast(string ID);
string getEmail() const;
void setEmail(string ID);
int getAge() const;
void setAge( int Age);
int getdays1();
int getdays2();
int getdays3();
void setDaysTilComplete(int days, int days1, int days2);
Degree getDegree() const;
void setDegree(Degree degreeType);
private:
string studentID = "No name";
string firstName = "No name";
string lastName = "No name";
string email = "No name";
int age = 7;
int daysTillComplete[3];
Degree studentDegree = NETWORKING;
};
void print(string* object) {
cout << *object << endl;
}
string Student::getID() const {
return studentID;
}
string Student::getFirst() const {
return firstName;
}
string Student::getLast() const {
return lastName;
}
string Student::getEmail() const {
return email;
}
int Student::getAge() const {
return age;
}
int Student::getdays1() {
return daysTillComplete[0];
}
int Student::getdays2() {
return daysTillComplete[1];
}
int Student::getdays3() {
return daysTillComplete[2];
}
Degree Student::getDegree() const {
return studentDegree;
}
void Student::setID(string ID) {
studentID = ID;
}
void Student::setFirst(string first) {
firstName = first;
}
void Student::setLast(string last) {
lastName = last;
}
void Student::setEmail(string Email) {
email = Email;
}
void Student::setAge(int studentAge) {
age = studentAge;
}
void Student::setDaysTilComplete(int days1, int days2, int days3) {
daysTillComplete[0] = days1;
daysTillComplete[1] = days2;
daysTillComplete[2] = days3;
}
void Student::setDegree(Degree degreeType) {
studentDegree = degreeType;
}
int main() {
Student vallery("A1", "Vallery", "Williams", "vallery.a.williams1234#gmail.com",21,52,28,32,NETWORKING);
print(&vallery.getID());
print(&vallery.getFirst());
print(&vallery.getLast());
print(&vallery.getEmail());
//print(&vallery.getAge()); <--- will not compile if this statement is in the program
//print(&vallery.getdays1()); <--- will not compile if this statement is in the program
////print(&vallery.getdays2()); <--- will not compile if this statement is in the program
////print(&vallery.getdays3()); <--- will not compile if this statement is in the program
//print(&vallery.getDegree()); <--- will not compile if this statement is in the program
cin.get();
return 0;
}
My expected results for example print(vallery.getFirst); would be print vallery. That works, but when I do print(vallery.getAge); it should be 21 but I can't even compile it because I get the "expression must be an l-value or function designator" error. Also using int instead of string for the data type of the print function doesn't work either. I must be using something incorrectly. Can someone point me in the right direction? After a bunch of research I haven't found any solutions.
There are several things are are probably going wrong with this code.
The most obvious is that your print function expects a string*. The calls that fail are those where you try and give the function something that is not a string*. For example, getAge() returns a int, where you are taking the address of the returned int. So you are trying to call print(int*) which then is failing. To solve this you can either using templating or have overloads. Here is a recommended template function:
template <typename T>
print (const T& _object)
{
cout << _object << endl;
}
A second problem, which is what is masking this first error comes from the fact you are taking a ptr instead of a reference (or a const reference as in my template function). If you want to print something, you want it to definitely be there and not a nullptr. So use references. In saying this, I think the ones that you say will work, definitely shouldn't work (even though they are string*'s) under any sane compiler. Perhaps the current error is hiding those errors.
The error “expression must be an lvalue or a function designator” comes from the fact that you are trying to take the address of an r-value. That is a value that is temporary and/or has not been bound to a name. Your getters return a copy of the value stored in your student object and this value has no address. You are trying to get the address of an addressless value, hence the error that it must be lvalue.
To solve this: Firstly don't use pointers, use a const reference. Secondly, have your getters return a const reference for objects. For example,
const string& Student::getID() const;
If your print function takes a const reference, it is able to handle a temporary variables for the cases where you return an int or other primitive type. Since your other getters return a reference to an addressable value, the print function can also take this reference without having to needlessly copy the values.

Am I right about this copy constructor, or they are lying to me?

Say you got a class Student:
class Student{
char *_name;
Student(char *name){
_name = new char[strlen(name)+1];
strcpy(_name, name);
}
void setName(char *name){
_name = new char[strlen(name)+1];
strcpy(_name, name);
}
char* getName(){return _name;}
}
Now, it is just a basic class.
When I do this :
Student s("Mike");
Student s1 = s; // calls default copy constructor
s1.setName("Bruce");
cout << s.getName();
cout << s1.getName();
Shouldn't they now both be called Bruce because copy constructor is copying address to the source char and both pointers point to the same thing?
Initially, after the copy, both objects' _name pointers point to the same string in memory. But when you call setName, it allocates a new string, with different contents, and sets s1's _name to point to that instead. So in the end, the two objects refer to different strings.
I think this is the code you are looking for:
class Student{
private:
char *_name;
public:
Student(const char *const name) : _name(nullptr) {
setName(name);
}
~Student() { delete[] _name; }
void setName(const char *const name) {
delete[] _name;
_name = new char[strlen(name)+1];
strcpy(_name, name);
}
const char* getName() const {return _name;}
};
As they are two different student objects they can have different names. So in your code s1 is given the name bruce and s will have the name mike as expected
strcpy function copies the content of char array (that is all characters including the terminating null character with code 0). Both would be called "Bruce" if you had _name = name in your copying constructor.

Use singleton classes in c++

I created a singleton class
class AreaDataRepository {
private:
AreaDataRepository();
AreaDataRepository(const AreaDataRepository& orig);
virtual ~AreaDataRepository();
Way onGoingWay;
public:
static AreaDataRepository& Instance()
{
static AreaDataRepository singleton;
return singleton;
}
void SetOnGoingWay(Way onGoingWay);
Way const & GetOnGoingWay() const;
};
void AreaDataRepository::SetOnGoingWay(Way onGoingWay) {
this->onGoingWay = onGoingWay;
}
Way const & AreaDataRepository::GetOnGoingWay() const {
return onGoingWay;
}
header file of Way
class Way {
private:
std::string id;
std::string name;
public:
Way();
Way(const Way& orig);
virtual ~Way();
void SetName(std::string name);
std::string const & GetName() const;
void SetId(std::string id);
std::string const & GetId() const;
};
Then i'm created a Way object and set vales of id and name.
Way wayNode;
wayNode.SetId("123");
wayNode.SetName("jan")
AreaDataRepository::Instance().SetOnGoingWay(wayNode);
After assign OngoingWay accessing it from another class.
std::cout << AreaDataRepository::Instance().GetOnGoingWay().GetId();
the vale is not printing.
I'm going psychic here.... and I divine that your implementation of SetId is like this:
void SetId(std::string id) { id = id; }
that does not set the member variable, that sets the parameter to itself. And since your constructor most likely set the member variable id to "" you're printing empty strings. Either change the name of the parameter (to newId for example) to avoid the conflict or change the implementation to:
void SetId(std::string id) { this->id = id; }
As proof of this claim here's the result for the first version, as you see it prints nothing. And here is the result for the second, as you can see it prints the number.
The problem boils down to this: you have function parameter names that are the same as the name of your member variables and the function parameters are shadowing/hiding the member variables.
The only place this cannot happen is in a constructor's initialization list:
class Foo {
int x;
public:
Foo(int x): x(x) {} // <-- this works
void SetX(int x) { x = x; } // <-- this won't the parameter is hiding the member variable
};
Demo for the above snippet
std::cout is buffered in most implementations, if not in all. That means, the stream will wait for you to end a line before writing out any data. So, you can easily fix this by changing your output statement to
std::cout << AreaDataRepository::Instance().GetOnGoingWay().GetId() << std::endl;

How to make a function pointer constant

A typical getter/setter looks like this:
void setName(const std::string& _name) { name = _name; }
std::string getName() const { return name; }
How can I do the same if the member is a function pointer like this:
void setBotFunc(int(*botFunc)()) { botFunction = botFunc; }
int (*getBotFunc() const)() { return botFunction; }
Particularly I don't know how to declare the setter in a way that says 'I will only read and not modify the pointer (value)'. Does this even make sense? const int (*botFunct)() is obviously treated like a function which returns a const int.
void setBotFunc( int(* const botFunc)() )
{
botFunction = botFunc;
}

Question about assigning default constructor to *this in C++?

I am reading some C++ text. In an example, the text written:
class Student {
int no;
char grade[M+1];
public:
Student();
Student(int, const char*);
const Student& set(int, const char*);
void display() const;
};
Student::Student() {
no = 0;
grade[0] = '\0';
}
Student::Student(int n, const char* g) {
*this = Student(); // initialize to empty
set(n, g); // validate, reset if ok
}
I don't understand this line: *this = Student();
Why do we have to do that, while just calling Student(); also makes the default constructor invoked?
Thanks
It's not possible to call the default constructor directly (C++ FAQ). ie.
Student::Student(int n, const char* g){
Student();
set(n, g); // validate, reset if ok
}
doesn't work. However I'm not sure about the solution you have, either.
*this = Student()
will call Student::operator=(const Student&). In this particular class it's OK (that function is the default member copy) but it might not be in general, because the Student object is only 'partly constructed' when that method is called.
Better to have a private init function
void Student::init() {
no = 0;
grade[0] = '\0';
}
and call it from both constructors.
Although, imho, it would be better to use common initialization function, something like this:
class Student {
(...)
private:
void initMe();
};
Student::Student() {
initMe();
}
Student::Student(int n, const char* g) {
initMe(); // initialize to empty
set(n, g); // validate, reset if ok
}
void Student::initMe() {
no = 0;
grade[0] = '\0';
}
That would avoid unnecessary creation of objects.
It constructs a temporary Student object, and then copies it to *this. I would just initialize the member variables to empty in the second constructor though. The idea is that you don't have to write the same code that initializes the member variables as empty twice though, but it is quite trivial problem here.
*this = Student(); is just to initialize the member variables with respect to default constructor called. Such design should be avoided, as it creates temporary and copies it contents.
Use something like below:
void reset() { // introduce this method inlined in the class
grade[no = 0] = '\0';
}
Student::Student() {
reset(); // call it when needed
}
Student::Student(int n, const char* g) {
reset(); // initialize to empty
set(n, g); // validate, reset if ok
}