C++ Update Object attributes using set function [duplicate] - c++

This question already has answers here:
What's the difference between passing by reference vs. passing by value?
(18 answers)
Closed 7 years ago.
I'm writing a bookshop program. The program stores a number of books with their associated values (title, price, isbn, author) in a vector. One of the functions I'm trying to write is to search the vector by isbn and update the values of whichever book matches. Here is my code
void UpdateOnIsbn(vector <CBooks> booklist)
{
string searchisbn;
char response;
string booktitle;
string author;
double price;
string ISBN;
cout << "Please enter an ISBN to be searched: ";
cin >> searchisbn;
for (int i = 0; i < booklist.size(); i++)
{
if (booklist[i].HasISBN(searchisbn))
{
booklist[i].Display();
cout << "Would you like to update the details of this book? (Y/N): ";
cin >> response;
if (response != 'n' && response != 'N')
{
cout << endl << "Please Enter New Title for book: ";
cin >> booktitle;
booklist[i].SetTitle(booktitle);
cout << endl << "Please Enter New Author ";
cin >> author;
booklist[i].SetAuthor(author);
cout << endl << "Please Enter New Price ";
cin >> price;
booklist[i].SetPrice(price);
cout << endl << "Please Enter New ISBN ";
cin >> ISBN;
booklist[i].SetISBN(ISBN);
}
}
}
}
The function seems to work as it looks for new values to be entered but after it runs the old values are not replaced when I display the books again. Please help
Here is an example of one of the set functions:
void CBooks::SetPrice(double NewPrice)
{
m_Price = NewPrice;
}

You are passing a copy of booklist so you are modifying the copy not the original object.
Try passing a reference to the function void UpdateOnIsbn(vector <CBooks>& booklist)

You need to pass booklist by reference:
void UpdateOnIsbn(vector <CBooks>& booklist)
Otherwise the vector is copied and only this copy is modified.

Related

Dealing with multiple functions and parameters

Good day everyone
I am new to programming and C++.
I have been having some trouble with my program. I want the function culcAverageYearMark to use the variables from the function getMarks but no matter what I have tried it always throw any error like "expected primary expression before 'int' " I have tried everything that I possibly can but no lucky.
#include <iostream>
using namespace std;
void studentDetails()
{
string name, surName, schoolName;
cout << "Enter your name: \n";
cin >> name;
cout << "Enter your surname: \n";
cin >> surName;
cout << "Enter your school name: \n";
cin >> schoolName;
}
void getMarks()
{
int english, mathematics, lifeOrientation, history, computerLiteracy, geography;
cout << "Enter your mark for English: \n";
cin >> english;
while (!(english >0 && english <= 100))
{
cout << "Invalid mark \n";
cout << "Please enter your mark for English: \n";
cin >> english;
}
cout << "Enter your mark for Mathematics: \n";
cin >> mathematics;
while (!(mathematics >0 && mathematics <= 100))
{
cout << "Invalid mark \n";
cout << "Please enter your mark for Mathematics: \n";
cin >> mathematics;
}
cout << "Enter your mark for Life Orientation: \n";
cin >> lifeOrientation;
while (!(lifeOrientation >0 && lifeOrientation <= 100))
{
cout << "Invalid mark \n";
cout << "Please enter your mark for lifeOrientation: \n";
cin >> lifeOrientation;
}
cout << "Enter your mark for History: \n";
cin >> history;
while (!(history >0 && history <= 100))
{
cout << "Invalid mark \n";
cout << "Please enter your mark for History: \n";
cin >> history;
}
cout << "Enter your mark for Computer Literacy: \n";
cin >> computerLiteracy;
while (!(computerLiteracy >0 && computerLiteracy <= 100))
{
cout << "Invalid mark \n";
cout << "Please enter your mark for Computer Literacy: \n";
cin >> computerLiteracy;
}
cout << "Enter your mark for Geography: \n";
cin >> geography;
while (!(geography >0 && geography <= 100))
{
cout << "Invalid mark \n";
cout << "Please enter your mark for Geography: \n";
cin >> geography;
}
}
void calcAverageYearMark();
int main()
{
studentDetails();
getMarks();
calcAverageYearMark();
return 0;
}
void calcAverageYearMark()
{
getMarks(int english, int mathematics, int lifeOrientation, int history, int computerLiteracy, int geography)
float average = (english + mathematics + lifeOrientation + history + computerLiteracy + geography)/6;
}
Yes this is a scope issue.
If you want to calculate something in one function then get that value and send it to another function you want to use this code example...
int calculationA()
{
int a;
//do calulation to a
return a;
}
int calculateB(int b)
{
//b was sent from the main method
//we can use it here
return b;
}
int main()
{
int x = calculationA();
int output = calculationB(x);
//output variable now contains the caclulations after going through both methods
return 0;
}
you cannot access the variable without either making it global or sending it as a parameter. You are experiencing what is called a scope error
The problem you are having really has a couple different causes.
First of all, your function get_marks() has a void return type. That means that it does not return any value when it is run. If you want to get a value out of it you will need to give it a return type. For you needs it would need to return either a reference to an array or a pointer. If you don't know what those are then you should rethink how you are structuring your code so that you aren't getting multiple values out of a single function.
Another big issue is that you are calling get_marks incorrectly. The way you have defined it does not take any argument, so you will run into compilation issues because you are trying to pass it arguments when it does not expect any. You are also not properly passing arguments in the first place. You should not put a datatype before arguments.
Here is a simple rewrite of your program that should get the results you want:
#include <iostream>
using namespace std;
void studentDetails()
{
string name, surName, schoolName;
cout << "Enter your name: \n";
cin >> name;
cout << "Enter your surname: \n";
cin >> surName;
cout << "Enter your school name: \n";
cin >> schoolName;
}
int getMark(const string &class)
{
int english, mathematics, lifeOrientation, history, computerLiteracy, geography;
cout << "Enter your mark for " << class << " \n";
cin >> val;
while (!(val >0 && val <= 100))
{
cout << "Invalid mark \n";
cout << "Please enter your mark for English: \n";
cin >> val;
}
return val
}
float calcAverageYearMark()
{
int english, mathematics, lifeOrientation, history, computerLiteracy, geography;
english = getMark("english");
mathematics = getMark("mathematics");
lifeOrientation = getMark("lifeOrientation");
history = getMark("history");
computerLiteracy = getMark("computerLiteracy");
geography = getMark("geography");
float average = (english + mathematics + lifeOrientation + history + computerLiteracy + geography)/6.0;
return average;
}
int main()
{
studentDetails();
getMarks();
calcAverageYearMark();
return 0;
}
Please note that I have not tested this code and it is more meant to demonstrate a better structure to accomplish what you are trying to do.

c++ Program skips through lines while taking input [console application]

I am writing a sequential program on Library Management System which consists of two structs (books and student) and several functions.
Everything works accordingly except when I try to take console input in the function add_new_book() for the struct book , it skips line while taking input. I did research previously and then used the function cin.ignore() . That function works for the first two string inputs but after taking first two inputs, it skips the remaining input lines and terminates the function.
Here below is code from struct book and function add_new_book()
struct books{
int book_id;
string book_name;
string author_name;
string subject;
int fine;
};
void add_new_book(){
struct books b;
cout << "Enter the Book Name : ";
getline(cin, b.book_name);
cin.ignore();
//cin >> b.book_name;
cout << "Enter Author's Name : ";
getline(cin, b.author_name);
cin.ignore();
cout << "Enter Book id : ";
cin >> b.book_id;
cout << "Enter Book Cost : ";
cin >> b.fine;
cin.ignore();
cout << "Enter the Subject : ";
getline(cin, b.subject);
cout << "\n",b.book_name,b.author_name,b.book_id,b.fine,b.subject;
cout << "\n\n\t\t SUCCUSSFULLY ADDED \n";
// open a file in write mode.
ofstream outfile;
outfile.open("book1.txt");
outfile << b.book_name << endl;
outfile.close();
admin();
}
I suggest to get rid of cin.ignore's and use getline for numeric fields as well, using a std::string as a temporary buffer:
string s;
cout << "Enter Book id : ";
//cin >> b.book_id;
getline(cin, s);
Once you have the user input in a string, check its value and eventually assign it to the struct field, e.g. the book id has to be converted to int, this way:
b.book_id = std::atoi(s.c_str());
atoi will return zero if no conversion can be performed
if(b.book_id == 0)
{
cout << "Invalid book id";
}
Also, cout is not meant to be used the way you do. I would try something clean and tidy, like this:
cout << "Title : " << b.book_name << endl;
cout << "Author: " << b.author_name << endl;
//etc ...
You you shouldn't call std::cin.ignore() after std::getline(). getline will extract the '\n' from the input stream at the end of the line. Calling ignore will extract and discard another line.

C++ not able to type after cin >> answer;

I'm writing a basic program, similar to ELIZA(online therapist) simple questions and answers but I'm stuck at the end. after cin >> answer; I'm not able to write anything.
int main () {
short number;
string color;
string sport;
int answer;
string travel;
// Greets user
cout << "Hello, I'm Samantha" << endl;
// Asks user for their favorite sport
cout << "What's your favorite sport?";
cin >> sport;
cout << "I like " << sport << " too!" << endl;
cout << "How about your favorite color?";
cin >> color;
cout << "Not my favorite color but it's nice!" << endl;
cout << "Tell me something you've never told anyone before";
cin >> answer;
cout << "Don't worry, your secret is safe with me!" << endl;
cout << "Hows your life going?";
cin >> answer;
return 0;
}
your variable named "answer" has a data type integer. the first time you prompt the user to enter something from the console (apparently to be a string) the cin object attempts to initialize "answer" with a string (probably because the prompts does not ask for a number) which kills the cin object which will not allow the object to take instructions...so the next time you want to use it there is no cin object.
Just change the data type for "answer" to string.
Dr t

How to remove a struct element from a vector?

I'm a newbie programmer and I'm working on a program that holds a registry of pets in a hotel (some silly exercise we saw in class, doesn't matter). I'm using vectors for holding the struct elements (pets). The code for the struct is this:
struct Pets{
string Name;
string Race;
string Owner;
int Tel;
}p;
And the function to ask for user input is this:
AddPet(vector<Pets> &vtnew)
{
Pets newpet;
cout << "Enter the pet's name: " << endl;
cin >> newpet.Name;
cout << "Enter the pet's race: " << endl;
cin >> newpet.Race;
cout << "Enter the owner's name: " << endl;
cin >> newpet.Owner;
cout << "Enter the owner's telephone number: " << endl;
cin >> newpet.Tel;
vtnew.push_back(newpet);
}
Ok, now I need to create a function to remove the pet by entering the name or something. Is there any way to do that?
A vector is an unsorted container so the simple solutions are really your only choice.
void RemovePet(std::vector<Pet> & pets, std::string name) {
pets.erase(
std::remove_if(pets.begin(), pets.end(), [&](Pet const & pet) {
return pet.Name == name;
}),
pets.end());
}
This is known as the Erase-remove idiom.
Note that this will remove all pets matching that name, not just one.

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.