Creating a list pointer that points to other objects - c++

list<Book*> books;
list<Book>::iterator pos, last;
Book Administrator::addBook()
{
Book *newBook = new Book();
cout << "Would you like to enter a book?" << endl;
cin >> userInput;
cout << endl;
if (userInput == "yes")
{
cout << "What is the title of the book you want to enter?" << endl;
cin >> title;
cout << "What is the author of the book you want to enter?" << endl;
cin >> author;
cout << "What is the ISBN of the book you want to enter?" << endl;
cin >> ISBN;
cout << endl;
newBook->setTitle(title);
newBook->setAuthor(author);
newBook->setISBN(ISBN);
newBook->setAvailability(true);
books.push_back(newBook);
}
return *newBook;
}
void Administrator::printBookDetails()
{
books.begin()->setPrevBook(NULL);
for (pos = books.begin(); pos != books.end(); ++pos)
{
cout << pos->getTitle() << "\n"
<< pos->getAuthor() << "\n"
<< pos->getISBN() << "\n"
<< pos->getAvailability() << "\n"
<< "******************************" << endl;
if (pos != books.begin())
{
last->setNextBook(&*pos);
pos->setPrevBook(&*last);
}
last = pos;
}
books.back().setNextBook(NULL);
}
Can someone help me finish off this project please, these are my two functions addBook and printbookDetails . These are in my Admin class.
I would like the books i create on the heap to be stored in list< book*> books as i want to reference them in another class.
I've gotten a bit of help on here so far in regards to pointers and i know its something to do with me not linking the pointers to the correct objects.
My printBookDetails is giving me trouble, the first line books.begin()->setPrevBook(NULL); is saying i need a pointer-to-class type but when i put the -> i still have an error.
Book Guest::searchBook(Book* search)
{
string searchBook;
cout << "What book would you like to search for?" << endl;
cin >> searchBook;
printBookDetails();
}
What id like to do is use the searchBook function above in my Guest class to reference the books in the list at a later time but when i cannot seem to get my pointers right.
Can someone please put me on the right track.

for (pos = books.begin(); pos != books.end(); ++pos)
Here, pos is an iterator, over your list. Iterators are like pointers to list entries.
But each of your list entries is also a pointer to a book, not a book itself.
So, you need code like: (*pos)->getTitle() when trying to access member functions for those elements.

Related

An error, im trying to make a function that process a person's symptoms and then store it inside a vector string as "Y" or "N" and i get this

#include <iostream>
#include <vector>
using namespace std;
string disease(vector<string> symptom, vector<string> name, int patientnum){
string holder;
cout << "is " << name[patientnum] << " experiencing " << symptom[patientnum] << " Y/N";
cin >> holder;
if(holder == "Y" || holder == "y"){
return symptom.push_back("Y");
}
else if(holder == "N" || holder == "n"){
return symptom.push_back("N");
}
else{
cout <<"Please input Y/N" << endl;
cout <<"Program exiting...";
}
}
int main()
{
vector<string> dry, sneeze, namex;
int patientn = 0;
string input;
while(patientn < 2){
cout << "Name: ";
cin >> input;
namex.push_back(input);
disease(dry[patientn], namex[patientn], patientn);
patientn++;
}
for(patientn=0; patientn<namex.size(); patientn++){
cout << namex[patientn] << " is experiencing dry cough = " << dry[patientn] << endl;
cout << namex[patientn] << " is experiencing sneezing = " << sneeze[patientn] << endl;
}
return 0;
}
This is the error im getting
error: could not convert ‘symptom.std::vector<_Tp, _Alloc>::push_back, std::allocator > >(std::basic_string(((const char*)"Y"), std::allocator()))’ from ‘void’ to ‘std::string {aka std::basic_string}’
Im a freshmen in IT, so im sorry if my logic for making this program is stupid, and my variables naming are confusing.
So in the while loop im asking for a name and then storing it inside a name vector and then i call the function to ask for an input. "
cout <<"Is " << name << " experiecing " << symptom; //something like this but i also use an int patientnum to get the name[patientnum]
and then get y/n as the answer.
Then i make an if that accepts uppercase or lowercase answer and return symptom.push_back "Y" or "N"
and the for loop on the bottom is to print the name and then Y/N
Or can you guys suggest me a better way of doing this, im willing to learn anything.
Change the function to void, since you don't want to return anything from it.
void disease(vector<string> symptom, vector<string> name, int patientnum){
string holder;
cout << "is " << name[patientnum] << " experiencing " << symptom[patientnum] << " Y/N";
cin >> holder;
if(holder == "Y" || holder == "y"){
symptom.push_back("Y");
}
else if(holder == "N" || holder == "n"){
symptom.push_back("N");
}
else{
cout <<"Please input Y/N" << endl;
cout <<"Program exiting...";
}
}
Unfortunately that's only one of many issues with your code.
Incidentally if you spend some time choosing logical and meaningful names for your functions and variables you will find the programming easier. Funny that. Half the battle with programming is thinking clearly about what you are doing, and meaningless or arbitrary names show that you aren't thinking clearly.

Creating new "dynamic" objects?

What is the best way of creating dynamic (not sure if this is the correct word) objects? For example, if I run the following:
Person man[10];
cout << "MENU" << endl;
cout << "1. Add a person to the list" << endl;
cout << "2. Delete a person from the list" << endl;
cout << "3. Change a person's information'" << endl;
cout << "4. Locate a person by ID number" << endl;
cout << "5. Locate a person by last name" << endl;
cout << "6. Print the list on the screen" << endl;
cout << "7. Load the list from a file" << endl;
cout << "8. Save the list to a file" << endl;
cout << "9. Exit the program" << endl;
cin >> a;
if (a == 1) {
if (i <= 10) {
Person man[i];
cout << "Please enter your last name: " ;
cin >> last;
man[i].setLastName(last);
i++;
cout << man[i].getLastName();
}
}
When I run this, I am allowed to enter my last name, but when I press ENTER the program stops running. What is the reason for this and is there a better way to create these objects "profiles"?
Thank you and I'm sorry if this is a stupid question.
The reason is your entire program only take one input cin >> a; and then check if its equal to 1. After the block the program has nothing left to do. So your program terminated.
If you want to edit all first name and last name of your 10 Person obj, you'd better create a loop to do that. For loop, you can google for / while.
Heres a example:
int i;
while(cin >> i)
{
if(i == 9)
return;
else if[....]
}
When you say dynamic, object allocation is via new operator. In your code, the array is already declared with 10 elements(static allocation). Hence in you code you are not performing dynamic allocation.
For dynamic allocation,add a function which can return you a new Person object. In this function create a object using new operator and return this object.
This way you add new objects dynamically.
Refer to new operator for more details on dynamic allocation.

Im creating a text based adventure game and need an alternative to using GOTO

How can I properly use a do, while, or for loop of some kind to prevent the user from entering anything else other than the answer "1" or "2"?
If they don't, the program should tell them they cannot do that and then return them to the previous question.
#include <iostream>
#include "Options.h"
#include <string>
using namespace std;
int main(int argc, char *argv[]) {
cout << "\tWelcome to my text adventure game\n" << endl;
cout << "Please enter your characters Name: ";
string name;
cin >> name;
cout << "\nWelcome " << name << endl;
cout << "\nPlease choose the side you would like to play in - ";
Options OptionsObject;
OptionsObject.optionsSide();
string answer;
while(answer != "quit") {
cin >> answer;
cout << answer << endl;
}
if ( answer == "1" ) {
cout << "You chose the good side. Let the game begin\n " << endl;
cout << "You are located in a city named after the warrior who saved it from the evil\nmany years ago. The city of Redshore. " << endl;
cout << "You are no ordinary man in the City of Redshore. You are the king who rules it\nYou are seen as King of Justice, a good king.\nOne who only want what is best for his people" << endl;
cout << "but also a troubled man. You experienced something traumatizing when you\nwere a just a little boy, but no one knows about it,\nno one but yourself that is " << endl;
} else if( answer == "2" ) {
cout << "hey there" << endl;
}
}
Seen that this problem would be in all the choose the user will do during the game I will make an external function, to let the user choose. Maybe a static class working in this way.
int ans = Answer.getUserAnswer(2,"[1/2]>");
and this should work in this way:
public static int getUserAnswer(int max =1,string message="[1/1]>")
{
int ans = 0;
while(ans==0){
cout<<message<<" ";
cin >> answer;
if(answer>0 and answer<=max) return ans;
cout<<"\tnot a valid choose\n";
ans=0;
}
}
and you will have in your ans one of the value you expect, and it will print "not a valid choose" if the answer is not between the one you expect, and you can do this even with 10 answers, calling it by default expect you to give him just the number one.
I used it in a console game I made ;)
Hope is useful
EDIT
int getUserAnswer(int max =1,string message="[1/1]>")
{
int ans = 0;
while(ans==0){
cout<<message<<" ";
cin >> answer;
if(answer>0 and answer<=max) return ans;
cout<<"\tnot a valid choose\n";
ans=0;
}
}
and to request this code in your code:
cout << "\nWelcome " << name << endl;
cout << "\nPlease choose the side you would like to play in - ";
Options OptionsObject;
OptionsObject.optionsSide();
int answer =getUserAnswer(2,"[1/2]>");
if (answer == 1){
cout << "You chose the good side. Let the game begin\n " << endl; cout << "You are located in a city named after the warrior who saved it from the evil\nmany years ago. The city of Redshore. " << endl; cout << "You are no ordinary man in the City of Redshore. You are the king who rules it\nYou are seen as King of Justice, a good king.\nOne who only want what is best for his people" << endl; cout << "but also a troubled man. You experienced something traumatizing when you\nwere a just a little boy, but no one knows about it,\nno one but yourself that is " << endl;
}
else if(answer == 2){
cout << "hey there" << endl;
}
You should put the line where you read the input in a do loop that loops while the answer given by the user is invalid.
So, your do loop should be:
string answer;
cin >> answer;
// loop while answer is neither "1" nor "2"
while( answer != "1" && answer != "2" ) {
cout << "Please enter a 1 or a 2. You entered " << answer << endl;
cin >> answer;
}

My list objects are being destroyed

list<Book> *books = new list<Book>;
list<Book>::iterator pos;
void Administrator::addBook()
{
Book *newBook = new Book();
cout << "Would you like to enter a book?" << endl;
cin >> userInput;
cout << endl;
if (userInput == "yes")
{
cout << "What is the title of the book you want to enter?" << endl;
cin >> title;
cout << "What is the author of the book you want to enter?" << endl;
cin >> author;
cout << "What is the ISBN of the book you want to enter?" << endl;
cin >> ISBN;
cout << endl;
newBook->setTitle(title);
newBook->setAuthor(author);
newBook->setISBN(ISBN);
newBook->setAvailability(true);
books->push_back(*newBook);
}
}
*****************
I really need help with this, i have received a few answers today but none have helped me with this problem. This is my admin class. It creates books on the heap and stores them in an stl::list
void Guest::searchBook(Book* search)
{
string searchBook;
cout << "What book would you like to search for?" << endl;
cin >> searchBook;
printBookDetails();
}
This is my Guest class, what i would like to do here is to search through the list of books i created in my Administrator class but when it goes into the function printBookDetails, my list contains no elements, im assuming they've been destroyed.
Administrator* admin1 = new Administrator("jayfitz91", 24681357);
Guest* guest1 = new Guest("guest", 0000);
void main()
{
//Everything here works fine
admin1->addBook();
admin1->addBook();
admin1->makeAvailable();
admin1->printBookDetails();
//My list is destroyed at this point and it returns nothing
guest1->printBookDetails();
My Guest class inherits the printBookDetails from my Administrator class
All of the admin functions work but as soon as it gets to guest, the elements disappear.
Is there anyway i can get around this? The help would greatly be appreciated
Thanks to #OldProgrammer, i realised i had to return the list of books from my Admin class and pass it through as a parameter to my printBookDetails method in my guest class:
//Admin class
//Now returning a list
list<Book> Administrator::addBook()
{
Book *newBook = new Book();
cout << "Would you like to enter a book?" << endl;
cin >> userInput;
cout << endl;
if (userInput == "yes")
{
cout << "What is the title of the book you want to enter?" << endl;
cin >> title;
cout << "What is the author of the book you want to enter?" << endl;
cin >> author;
cout << "What is the ISBN of the book you want to enter?" << endl;
cin >> ISBN;
cout << endl;
newBook->setTitle(title);
newBook->setAuthor(author);
newBook->setISBN(ISBN);
newBook->setAvailability(true);
books->push_back(*newBook);
}
return *books;
}
//Guest class function
void Guest::printBookList(list<Book> *tempList)
{
pos = tempList->begin();
for (pos = tempList->begin(); pos != tempList->end(); ++pos)
{
cout << pos->getTitle() << "\n"
<< pos->getAuthor() << "\n"
<< pos->getISBN() << "\n"
<< pos->getAvailability() << "\n"
<< "******************************" << endl;
}
}
//Main class function
//Create a temporary variable for the list
list<Book> tempList;
//pass it through to the method
guest1->printBookList(&tempList);
First off, you don't have to dynamically create your list object.
list<Book> books = new list<Book>();
You do this because
you have less responsibility: you don't have to release the resources contained by books. It will automatically be released.
list is a stl container, which means it automatically handles dynamic allocations.
This is different if you use an dynamically allocated array...
I think your list is "gone" is because Guest and Administrator has two entirely different list.
To solve this issue, you should grant access to the book list that Administrator has to your Guest.
Or extract out the book list and store it in another class that allow access to the list to both Administrator and Guest.

Printing out elements in a list

Book Administrator::bookDetails()
{
Book book;
list<Book> books;
string title;
string author;
int ISBN;
string userInput;
while (userInput != "q")
{
cout << "Would you like to enter a book?" << endl;
cin >> userInput;
if (userInput == "yes")
{
cout << "What is the title of the book you want to enter?" << endl;
cin >> title;
cout << "What is the author of the book you want to enter?" << endl;
cin >> author;
cout << "What is the ISBN of the book you want to enter?" << endl;
cin >> ISBN;
book.setTitle(title);
book.setAuthor(author);
book.setISBN(ISBN);
books.push_back(book);
}
list<Book>::iterator pos;
pos = books.begin();
for (pos = books.begin(); pos != books.end(); pos++)
{
//There error is produced here
cout << *pos << "\n";
}
}
return book;
}
This is the bookDetails function of my Administration class. It loops through and asks for a books title, author and ISBN number and when its finished it pushes the book onto a list.
This seems to work fine when i debug it but i get an error when i try to print out the details of each book using the iterator.
Can anyone help me out here?
Thanks
You need to implement operator<< for Book
std::ostream operator<<(std::ostream& os, const Book& book)
{
os << book.title << " " << book.author; // print out other information
return os;
}