C++ help setting up pointers in classes - c++

I'm currently having some problems with my class and the member functions, particularly with taking the users input from the setter functions and then displaying that info from the print info function. I have a separate functions that allow the user to enter information about the character and then a getter function to then use in printing out the info that the user entered. When I first ran it I had an error about needing to use a pointer to a member function and I added the &Character::GetCharacterName and the others in my print info function. Now when I run the program through my main function (I didn't include it because it simply calls all the functions) my program will run but all the values are set at 1 no matter what the user entered. I know it has something to do with pointers so any help with correctly setting this up so that it returns the values that the user entered would be appreciated. Thanks
Character.h file
class Character
{
public:
Character();
void SetCharacterName();
void SetCharacterType();
void SetCharacterLevel();
string GetCharacterName();
string GetCharacterType();
double GetCharacterLevel();
void PrintInfo();
private:
string CharacterName;
string CharacterType;
double CharacterLevel;
};
Character.cpp file
Character::Character()
{
CharacterLevel = 1.0;
}
void Character::SetCharacterName()
{
cout << "\nWhat is the character's name? ";
cin >> CharacterName;
}
void Character::SetCharacterType()
{
cout << "\nWhat is the character's type? ";
cin >> CharacterType;
}
void Character::SetCharacterLevel()
{
cout << "\nWhat is the character's level? ";
cin >> CharacterLevel;
}
string Character::GetCharacterName()
{
return CharacterName;
}
string Character::GetCharacterType()
{
return CharacterType;
}
double Character::GetCharacterLevel()
{
return CharacterLevel;
}
void Character::PrintInfo()
{
system("pause");
system("cls");
cout << "\nCharacter name is " << &Character::GetCharacterName << ".\n";
cout << "\nCharacter type is " << &Character::GetCharacterType << ".\n";
cout << "\nCharacter level is " << &Character::GetCharacterLevel << ".\n";
}

Use (), to do a method call in PrintInfo:
cout << "\nCharacter name is " << GetCharacterName() << ".\n";
etc.

I sugest :
this->GetCharacterName();
In the print method.

Related

How do I go about printing a vector of objects?

I'm guessing I might have to use pointers, but haven't gone in depth too much on them in class yet to try and implement them in my program. I have this so far, the printing function is towards the middle of the program. I'm not quite sure on how to print out the elements from the vector as my approach didn't work.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class rolodex
{
string name;
string street, town, state;
string zip;
string phone;
vector <rolodex> entries;
public:
rolodex();
void getmenu();
void add_entry();
void set_name();
void set_address();
void set_phone();
void printinfo();
};
rolodex :: rolodex() : name(""), street(""), town(""), state(""), zip(""),
phone(""), entries()
{
}
void rolodex :: getmenu()
{
cout << "\n\n1)Add Entry";
cout << "\n5)Print All Entries";
cout << "\n6)Exit" << endl;
}
void rolodex :: add_entry()
{
rolodex temp;
cout << "\n\nEnter Name: ";
temp.set_name();
temp.set_address();
cout << "\n\nEnter Your Phone Number: ";
temp.set_phone();
entries.push_back(temp);
}
void rolodex :: set_name()
{
cin.ignore();
getline(cin, name);
}
void rolodex :: set_address()
{
cout << "\n\nNow we'll enter address information.";
cout << "\n\nStreet: ";
getline(cin, street);
cout << "\n\nTown: ";
getline(cin, town);
cout << "\n\nState: ";
getline(cin, state);
cout << "\n\nZip: ";
getline(cin, zip);
}
void rolodex :: set_phone()
{
getline(cin, phone);
}
void rolodex :: printinfo()
{
for(unsigned int i = 0; i < entries.size(); i++)
{
cout << entries[i] << endl; //This is where I'm stuck since I've only
//worked with vectors of non-object data
//type
}
}
int main()
{
rolodex person, menu;
short choice;
bool done = false;
do
{
menu.getmenu();
cout << "\n\nEnter a choice: ";
cin >> choice;
switch(choice)
{
case 1:
person.add_entry();
break;
case 5:
person.printinfo();
break;
case 6:
done = true;
break;
default:
cout << "\n\nInvalid Entry." << endl << endl;
}
} while(!done && isdigit(choice));
return 0;
}
πάντα ῥεῖ is right, but to add a little more detail...
You need to specify how you want the stream to handle your object. This is done by by adding a << operator. For example:
std::ostream& operator<<(std::ostream& s, const rolodex& r){
// Or however you want to format it.
s << "Name: " << r.name << " : ";
s << "Street: " << r.street << " : ";
s << "Town: " << r.town << " : ";
s << "State: " << r.state << " : ";
s << "Zip: " << r.zip << "\n";
}
Unfortunately, the function above tries to access the private fields of your class, which it can't because it is not part of the class definition.
An easy way to address that is to declare this function a "friend" inside of the class definition, like such:
friend std::ostream& operator<<(std::ostream&, const rolodex&);
...And since you might appreciate it, one big copy-pasteable chunk that you can use directly that should make your function work:
class rolodex
{
string name;
string street, town, state;
string zip;
string phone;
vector <rolodex> entries;
public:
rolodex();
void getmenu();
void add_entry();
void set_name();
void set_address();
void set_phone();
void printinfo();
friend std::ostream& operator<<(std::ostream&, const rolodex&);
};
std::ostream& operator<<(std::ostream& s, const rolodex& r){
// Or however you want to format it.
s << "Name: " << r.name << " : ";
s << "Street: " << r.street << " : ";
s << "Town: " << r.town << " : ";
s << "State: " << r.state << " : ";
s << "Zip: " << r.zip << "\n";
}
Following up on πάντα ῥεῖ's suggestion, here's one way of doing that, changing your design as little as possible:
1) Create a non-member overloaded operator<< for your rolodex class:
std::ostream& operator<< (std::ostream& os, const rolodex& rol)
{
os << rol.name << ":" << std::endl
<< "\t" << rol.street << std::endl
<< "\t" << rol.town << std::endl
<< "\t" << rol.state << std::endl
<< "\t" << rol.zip << std::endl
<< "\t" << rol.phone << std::endl;
return os;
}
.. but the compiler will chide you for attempting to access private members (by default, members are private) from outside the class, so you would have to relax the rules a bit:
class rolodex
{
...
public:
...
friend std::ostream& operator<< (std::ostream& os, const rolodex& rol);
};
You can't have the operator<< inside the class itself, see does-overloading-operator-works-inside-the-class.
However, it is almost always better design to add getter functions to your public interface anyway. You would have get_name() etc in the public: section of your class def, those functions would initially just return the values of the private member variables, and then your operator<< can use them instead of trying to access the private members. You then no longer require the friend declaration.
I upvoted Some programmer dude's remark about your design
The code for letting the use input the data really shouldn't be inside the rolodex class, because it makes the class hard to reuse. Image wanting to re-use the rolodex from a graphical interface, for example, and it's not such a good idea to have the rolodex contain instances of itself inside the vector.
I would suggest a
1) Person class containing all the person's attributes, with public getters get_name() and setters set_name() that don't use a specific entry method, just take the data as arguments e.g. set_name(std::string& name).
2) an non-member operator<< to output a person to an output stream
3) a Rolodex class with a private std::vector<Person> and methods to add a person, write all the persons to an output stream, etc..
Good luck & enjoy :-)
Edit: the menu structure on the terminal should IMHO be left inside the main() function or encapsulated into another class. But certainly don't leave it in Rolodex or worse, Person.

c++ using private class data in a program

I know that private class data is only accessible within the class; however, the examples that I have read show similar use of private members in their program code. I am attempting to use functions to access and manipulate the private class members, but it is not working. What am I doing incorrectly? I have tried substituting the Data.SelectionF() function for Data.selection after the first cin and for all instances of the use of the selection member variables without success. I also tried the same approach for all instances of the value member variable. Thanks
#include <iostream>
#include <iomanip>
using namespace std;
class allData {
private:
char selection;
double r;
double centimeter;
double value;
public:
double ConvertC (double value);
double ConvertR (double value);
double valueF (double value);
char selectionF (char selection);
allData Data ();
} Data;
int main() {
cout << "Enter C for converting your Feet to Centimeters.\n"
"Enter R for converting your Inches to Centimeters.\n";
cin >> Data.selection;
cout << "\nYou selected to convert to: " <<
Data.selectionF(Data.selection) << ".\n\n";
cout << "Enter your starting value to two decimal places, and press
ENTER.\n\n";
cin >> Data.value;
cout << "\nYou entered a starting value of: " <<
Data.valueF(Data.value) << ".\n\n";
//switch to decide which conversion function to use from the structure
switch (Data.selectionF(Data.selection)) {
case 'c': { Data.ConvertC(Data.value);
cout << "Your Feet converted to Centimeters is: " <<
Data.ConvertC(Data.value) << "\n\n";
break;
}
case 'C': { Data.ConvertC(Data.value);
cout << "Your Feet converted to Centimeters is: " <<
Data.ConvertC(Data.value) << "\n\n";
break;
}
case 'r': { Data.ConvertR(Data.value);
cout << "Your Inches converted to Centimeters is: " <<
Data.ConvertR(Data.value) << "\n\n";
break;
}
case 'R': { Data.ConvertR(Data.value);
cout << "Your Inches converted to Centimeters is: " <<
Data.ConvertR(Data.value) << "\n\n";
break;
}
default: {cout << "You entered an invalid selection for your conversion"
"choice.\n";
break;
}
}
return 0;
}
//Function definitions
double allData::ConvertC (double value) {
centimeter = value * 30.48;
return centimeter;
}
double allData::ConvertR (double value) {
r = value * 2.54;
return r;
}
double allData::valueF (double value) {
return value;
}
char allData::selectionF (char selection) {
return selection;
}
//End of program.
Whatever examples you've read, either they are wrong or you misunderstood them. You cannot access private class members outside of the class (barring friend declarations, of course). That's what a private class member means, by definition.
cin >> Data.selection;
selection is a private class member. It cannot be accessed from your main(). That's, pretty much, all that can be said about it.
If I did not misunderstand your question let me tell you something about your problem.
Firstly, with this line "cin >> Data.value;" you are trying to get the private value of the "DATA" class in fact this is wrong. You cannot access to the private variable from the outside of the "DATA" class. The object "DATA" is not inside the "DATA" class. On the other hand if you want to access the private variables inside the class indirectly, then you can write a function like that:
public:
void function_name(const DATA &dataObject) const
{
cout << "The selection value : " << dataObject.selection << endl;
}
This part of code will access to the private variables inside the class indirectly. Remember if a function is inside the class then it can access all the private variables and there is no something wrong with this code.

Segmentation Fault on Simple C++ Program

This is a follow up to my previous question. I have some code which should be running fine, and it does for the most part. When I run it, most of the main method runs but I get a segmentation fault when the getter methods are executed. Here is the code:
#include <iostream>
#include <string>
using namespace std;
class Person
{
protected:
string m_FirstName, m_LastName, m_email;
public:
Person(){}
Person(const string& firstName, const string& lastName) :
m_FirstName(firstName), m_LastName(lastName)
{}
string get_name() const
{
return m_FirstName;
}
string get_surname() const
{
return m_LastName;
}
bool has_email_p()
{
}
};
class Person_with_telephone: public Person
{
protected:
string m_telephone;
public:
Person_with_telephone(){}
Person_with_telephone(const string& telephone) : m_telephone(telephone)
{}
bool has_telephone_p()
{
if (m_telephone == "")
{
cout << "You have no phone number registered" << endl;
return false;
}
else
{
cout << "Your number is: " << m_telephone << endl;
return true;
}
}
string get_telephone() const
{
return m_telephone;
}
string set_telephone()
{
}
string get_telephone()
{
}
};
int main()
{
string f, l, ph;
cout << "Enter fist name: ";
cin >> f;
cout << "Enter Last name: ";
cin >> l;
cout << "Enter telephone number: ";
cin >> ph;
Person p(f, l);
Person_with_telephone pwt(ph);
cout << "Your name is: " << p.get_name() << " " << p.get_surname() << endl;
cout << "Has telephone? " << endl << " Your number is: " << pwt.get_telephone() << endl;
return 0;
}
When I compile it compiles fine and when I run I get asked for the three inputs of Name, Surname and Telephone, but when I input the last value I get this:Odd segfault
You are not returning anything in Person_with_telephone::get_telephone(). This will cause a segfault.
If you compile with proper warnings turned on Then you should at least get
main.cpp:32:9: warning: control reaches end of non-void function [-Wreturn-type]
}
^
main.cpp:69:3: warning: control reaches end of non-void function [-Wreturn-type]
}
^
main.cpp:74:3: warning: control reaches end of non-void function [-Wreturn-type]
}
^
3 warnings generated.
Which would let you know that you need return statements in those functions.
Your bool has_email_p(), string get_telephone() and string set_telephone() functions don't do or, more importantly, return anything.

function does not take 1 arguments error

I've tried many times to fix this error but I'm not sure what to do. For both the addBooks and displayBooks functions I am getting a "function does not take 1 arguments" error, though the vector should just be one argument.
struct bookStruct
{
char title[40];
char author[40];
int pages;
int year;
};
enum menu { display=1, add, end} ;
void displayOptions();
void displayBooks();
void addBooks();
int main(){
vector<bookStruct> book(1);
string option = "display";
displayOptions();
cin >> option;
//std::strcpy(book[0].title, "a");
//std::strcpy(book[0].author, "a");
//book[0].pages = 0;
//book[0].year = 0;
while (option != "end"){
addBooks(book);
displayBooks(book);
}
return 0;
}
void displayOptions(){
cout << "1. Display list of books" << endl;
cout << "2. Add books" << endl;
cout << "3. Exit" << endl;
}
void displayBooks(vector<bookStruct> book){
for (int n = 0; n<book.size(); n++){
cout << book[n].title << " ; " << book[n].author << " ; "
<< book[n].pages << " ; " << book[n].year <<endl;
}
cout << endl;
}
void addBooks(vector<bookStruct> book){
int n = book.size()+1;
book.resize(book.size()+1);
cout << "Enter the book title: " << endl;
cin >> book[n].title;
cout << "Enter the author name: " << endl;
cin >> book[n].author;
cout << "Enter the number of pages: " << endl;
cin >> book[n].pages;
cout << "Enter the publication year: " << endl;
cin >> book[n].year;
}
Both addBooks and displayBooks take no arguments:
void displayBooks();
void addBooks();
yet you are calling them with arguments:
addBooks(book);
displayBooks(book);
The compiler is telling you this in its own words.
It looks like you need
void displayBooks(vector<bookStruct> book);
void addBooks(vector<bookStruct> book);
although it is more likely that you don't need to copy the vectors into the functions:
void displayBooks(const vector<bookStruct>& book);
void addBooks(const vector<bookStruct>& book);
Note you have definitions of one-parameter functions after main(). The main() function only considers the declarations that come before it.
void displayBooks();
void addBooks();
take no parameter, however you passed book into them, the compile cannot find both functions. therefore, error.
void displayBooks();
should be
void displayBooks(vector<bookStruct> book);
but as a better approach you can use:
void displayBooks(const vector<bookStruct> &book);
So that book vector is not copied while being passed into the method DisplayBooks
Your function is declared as
void addBooks();
but you are calling it with
addBooks(book);
Compiler obviously thinks it strange that you have no argument in the declaration, and then try to call it with an argument.
It is hard for me to advice exactly what you should do, since it's not clear from the code you have posted what the "right" thing is.

c++ setting string attribute value in class is throwing "Access violation reading location"

I am having some trouble getting this simple code to work:
#pragma once
#include <iostream>
#include <string>
using std::string;
class UserController;
#include "UserController.h"
class CreateUserView
{
public:
CreateUserView(void);
~CreateUserView(void);
UserController* controller;
void showView();
string name;
string lastname;
string address;
string email;
string dateOfBirth;
};
All i need is to set these attributes in the implementation with getline().
CreateUserView::CreateUserView(void)
{
}
void CreateUserView::showView()
{
cout << endl << " New User" << endl;
cout << "--------------------------" << endl;
cout << " Name\t\t: ";
getline(cin, name);
cout << " Lastname\t: ";
getline(cin, lastname);
cout << " Email\t\t: ";
getline(cin, email);
cout << " ===============================" << endl;
cout << " 1. SAVE 2.CHANGE 3.CANCEL" << endl;
cout << " ===============================" << endl;
cout << " choice: ";
int choice;
cin >> choice;
cin.ignore();
controller->createUser_choice(choice);
}
I keep getting this "Access violation reading location" error at this line:
getline(cin, name);
what's the best way of assigning a value to an std::string attribute of a class?
even name = "whatever" is throwing that error!!
thanks
EDIT:
a UserController is instantiating the CreateUserView:
CreateUserView *_createUserView;
This how the CreateUserView is being instantiated:
void UserController::createUser()
{
//Init the Create User View
if(_createUserView == NULL)
{
_createUserView = new CreateUserView();
_createUserView->controller = this;
}
_createUserView->showView();
}
You don't seem the initialize your variable properly:
CreateUserView *_createUserView;
Therefore it is a dangling pointer, not NULL (in C++, with a few exceptions, variables are not initialized automatically to 0). So here
if(_createUserView == NULL)
{
_createUserView = new CreateUserView();
_createUserView->controller = this;
}
the if block is not executed, and here
_createUserView->showView();
you get access violation. Initialize your pointer properly to NULL:
CreateUserView *_createUserView = NULL;
Try changing your declaration of the global:
CreateUserView *_createUserView = NULL;