i have a program that asks for a number of gifts, and then has you input the description, price, and units for it.
i have a function used to display the details here inside it's own cpp file:
void display(const Gift&) {
cout << "Gift Details:" << endl;
cout << "Description: " << gifts.g_description << endl;
cout << "Price: " << gifts.g_price << endl;
cout << "Units: " << gifts.g_units << endl;
}
and here's where i try to call it through another cpp file:
for (int i = 1; i <= numberOfGifts; i++) {
cout << "Gift #" << i << endl;
display(gifts[i]);
cout << endl;
}
i can't seem to figure out how to have it display the first, second, third, and fourth values? it only displays the fourth values 4 times. would greatly appreciate some help
void display(const Gift&) accepts a reference to a Gift as a parameter, but without an identifier (a name) for the parameter the function cannot interact with the parameter.
Instead use void display(const Gift& gift) and then use gift in place of gifts in the function.
Future bug:
Arrays normally are valid between 0 and the array's dimension -1. In
for (int i = 1; i <= numberOfGifts; i++)
i ranges from 1 to numberOfGifts. At the very least this ignores the first, 0th, element of gifts and quite possibly will allow the program to access one past the end of the array. Skipping the first value is a waste of memory, but might be OK. Trying to access a value outside of the array is bad and the results very unpredictable.
Related
I have a vector of objects with quite a few variables (name, type, length etc) which I am trying to write to file.
vector <Boat> berths;
void Boat::write_boats()
{
ofstream file("records_file.txt");
for (Boat b : berths)
{
file << owner_name << "; " << boat_name << "; " << type << "; " << length << "; " << draft << '\n';
}
file.close();
}
void save_records()
{
for (unsigned int i = 1; i < berths.size(); i++)
{
berths[i].write_boats();
}
}
I call the save_records() function with a menu option that ends the application.
The output i get is:
1) If i register a boat object, close the app and go in the text file, I can see the object written twice.
2) If i register 2 objects and I go in the text file, only the last (second) object has been written to file, and it shows 3 times.
Now my questions are:
What causes the double output?
Why is only the last object written to file? I thought the loop would fix that but it didn't
One problem I can spot: "i = 1" in the loop should be "i = 0", because array indexes start from 0. The second: you iterate 'berths' array, so you will get N * N boats saved, if you have N boats in 'berths'.
The simple solution would be
void save_all()
{
ofstream file("records_file.txt");
for (Boat b : berths)
{
file << b.owner_name << "; " << b.boat_name << "; " << b.type << "; " << b.length << "; " << b.draft << '\n';
}
}
If you have to make 'owner_name', 'type' and the rest of the fields as private, then you would have to declare
void Boat::save(std::ofstream& f) const
{
file << owner_name << "; " << boat_name << "; " << type << "; " << length << "; " << draft << '\n';
}
and modify 'save_all' to
void save_all()
{
ofstream file("records_file.txt");
for (const Boat& b: berths)
b.save(f);
}
Every time ofstream file("records_file.txt"); is called, it created a new file and overwrite it, if you want to append in the file you have to open it by this way:
ofstream file("records_file.txt", ios::app);
See: http://www.cplusplus.com/doc/tutorial/files/
I guess you are using something like while(!bla.eof()), if so then it reaches the end of the buffer but it needs to go past it to raise the flag, so you have the same output twice at the end.
I have an vector array in my class which is made to hold pointers to a specific object pointers.
The class should contain methods allowing for adding, removing and finding the objects inside.
The class right now looks like this:
class VectorKontener: public Kontener <VectorKontener> {
protected:
int find(Obiekt &n) {
cout << endl << "---------------------" << endl << "Running find method loop!" << endl;
for (int i = 0; i < stos.size(); i++) {
cout << "Now running for id: " << stos[i]->getId() << endl;
if (stos[i] == &n) return i;
}
return -1;
}
public:
VectorKontener::VectorKontener(Obiekt &n) {
add(n);
}
VectorKontener add(Obiekt &n) {
cout << "Adding: " << n.getId() << endl;
stos.push_back(&n);
return *this;
}
int checkPresent(Obiekt &n) {
return this->find(n) != -1;
}
VectorKontener remove(Obiekt &n) {
if (this->checkPresent(n)) {
stos.erase(stos.begin() + this->find(n));
}
else
cout << endl <<"ELEMENT NOT IN CONTAINER" << endl;
return *this;
}
VectorKontener display() {
cout << endl << "===DISPLAY===" << endl;
for (int i = 0; i < stos.size(); i++) {
stos[i]->display();
}
return *this;
}
};
However when running for test data of:
void Zad3()
{
Obiekt
obj1(5),
obj2(23),
obj3(234),
obj4(33);
cout << endl << "1. Class init" << endl;
VectorKontener k1(obj1);
cout << endl << "2. Adding other objects into array" << endl;
k1
.add(obj2)
.add(obj3)
.display();
cout << endl << "3. Element remove attempt" << endl;
k1
.remove(obj2)
.display();
getchar();
}
The output looks like so:
1. Class init
Adding: 5
2. Adding other objects into array
Adding: 23
Adding: 234
===DISPLAY===
This object has id: 5
This object has id: 23
This object has id: 234
3. Element remove attempt
---------------------
Running find method loop!
Now running for id: 5
Now running for id: 23
---------------------
Running find method loop!
Now running for id: 5
Now running for id: 23
===DISPLAY===
This object has id: 5
The output makes it seem like the third variable of the array becomes lost in the find method (hehe) since it is not calculated by it, despite stos.size() showing the proper value (2).
I am not a cpp expert, to be fair pretty far from it, and am aware this might be a pretty noobish issue, but I have really ran out of ways to make it work properly.
Any help would be really amazing
The issue is that the functions return copies of the object, meaning that in the chained add call the original object is not modified (on the second and any subsequent function call), instead a temporary one is created on each function call that gets destroyed right after.
The simple fix is to change the return value to a reference, e.g.: for the add function:
VectorKontener& add(Obiekt &n) {
instead of
VectorKontener add(Obiekt &n) {
And similar changes for the other functions.
Pretty new to C++ here and programming as a whole so please be patient and understanding that my explanations may not be on the mark. The assignment for my OOP class calls for the following:
Design an Inventory class that can hold information for an item in a retail store's inventory.
Required private member variables:
- item number
- quantity
- cost
Required public member functions
Default constructor - Sets all the member variables to 0
Constructor #2 - Accepts an item's number, quantity and cost as arguments. Calls other class functions to copy these values into the appropriate member variables.
They way I'm going about this is slightly different. Rather than 1 value I'm trying to initialize an array and store all the values enter by the user there. However it seems, once the user exits the member/class function the value is removed from the array.
Kind of at my wits end here so any info or recommendations would greatly help.
#include <iostream>
using namespace std;
class inventory
{
private:
int productNum[10];
int productCount[10];
double productPrice[10];
int inventoryFillLevel;
int userPNumber;
int userQuantity;
double userPrice;
public:
inventory()
{
int counter = 0;
userPNumber = 0;
userQuantity = 0;
userPrice = 0;
while (counter < 10)
{
productNum[counter] = 5;
productCount[counter] = 6;
productPrice[counter] = 7;
counter++;
}
}
inventory(int pNumber, int pCount, int pPrice)
{
cout << "Now we're in the 2nd constructor in the Class" << endl;
cout << "The 1st number entered by the user is: " << pNumber << endl;
cout << "The 2nd number entered by the user is: " << pCount << endl;
cout << "The 3rd number entered by the user is: " << pPrice << endl;
Input(pNumber);
}
void Input(int pNumber)
{
int counter = 0;
cout << "\nNow we're in the function as called by the Constructor." << endl;
cout << "The 1st number entered by the user is: " << pNumber << endl;
cout << "In the function the counter is: " << counter << endl;
cout << "The value in the array at " << counter << " is: " << productNum[counter] << endl;
cout << "Now we set that to the value entered by the user" << endl;
productNum[counter] = pNumber;
cout << "And now the value in the array is: " << productNum[counter] << endl;
}
void Show()
{
int counter = 0;
cout << "After entering the value, let's check what is stored in the array: ";
cout << productNum[counter] << endl;
}
};
int main()
{
int a=0;
int b=0;
int c=0;
inventory inv1;
cout << "1st User entered value" << endl;
cin >> a;
cout << "2nd User entered value" << endl;
cin >> b;
cout << "3rd User entered value" << endl;
cin >> c;
cout << "Now we call the 2nd constructor and pass the values to it" << endl;
inventory(a, b, c);
inv1.Show();
return 0;
}
Thanks again for any help with this.
You appear to be handling your class incorrectly. The line
inventory(a, b, c);
only creates a temporary instance of inventory that is gone essentially after the line finishes execution. So when you call inv1.Show() it's still using the values that are assigned in your default constructor when inv1 was declared. You should remove the current declaration of inv and change
inventory(a, b, c);
to
inventory inv1(a, b, c);
Value are not getting removed. There is small flaw in the code.
1)- You are making mistake while creating an object. You are calling Show method with object created by default constructor.
inventory inv1;
....
inv1.Show();
Change the declaration of inv1 to inventory inv1(a, b, c); and call then call show method.
Also inventory(a, b, c); will create new object and will not effect inv1.
2)- You are always storing values at index 0 of the member array.
As you are declaring int counter = 0 whenever you are calling any method/constructor.
Make int counter ; a class member.
class inventory
{
private:
int counter;
public:
inventory():counter(0){....}
....
};
It will count the items you already push in your inventory.
Though you will have to take care how many item you already pushed in.
Alternative approach can be you can use std::vector instead of int array .
I'm having trouble understanding passing references and pointers. I've gone over it so many times in my head but just can't seem to click with it, and I think it's what I need to use here, to actually modify the value in the Account object.
Are there any surefire simple ways to understand them? And how would they apply to this fairly simple scenario?
main code:
if (transactionMenuChoice == 2)
{
cout << "________________________________________________" << endl;
cout << "//TRANSACTION MENU - WITHDRAWAL" << endl;
cout << "//CURRENT CUSTOMER: " << allCustomers.at(customerIndex).getName() << endl;
cout << "//CURRENT ACCOUNT: " << allCustomers.at(customerIndex).getAccounts().at(accountIndex).getAccountNum() << " (" << allCustomers.at(customerIndex).getAccounts().at(accountIndex).getType() << ")" << endl;
cout << "||Withdraw how much?" << endl;
cout << "||£" << endl;
int d;
cin >> d;
allCustomers.at(customerIndex).getAccounts().at(accountIndex).removeFromBalance(d);
}
from my Account.cpp:
void Account::removeFromBalance(double d)
{
balance -= d;
}
Perhaps you are referring to the difference between value references and pointer references? A pointer is the address of a thing, not the thing itself. Your address is a 'pointer' to your mailbox, but not the mailbox itself. In your removeFromBalance function you are passing 'd' by value (not as a pointer). C++ object syntax can sometimes muddy the water since you will see '.' notation to call member function on actual (when you have an object) and '->' notation used to call a member function when you have a pointer to an object.
So I finished my project, but my only problem is that I can only search one author at a time. I seem to not be able to figure it out.
This is what I have..am I missing something thats not making me able to find more than one author's last name?
void BookRecordUI::FindBookLast() //allows us to search a book by the last name of the author from the book record...
{
string Last;
cout << "Enter Book by Last Name of Author: " << endl;
getline(cin, Last);
Collection.FindBookAuthorLast(Last);
}
Any help will be much appreciated!
EDIT: So basically I want to find multiple authors..for example, if I inputted John Hopkins and Wilson Greene, I want to pull both authors last name at the same time. Sorry for not clearly explaining it.
I also have this part as well..
void BookRecordList::FindBookAuthorLast(string Last)
{
int K;
for(K = 0; K < (int)List.size(); K++)
if(List[K].GetAuthorLast() == Last)
cout << List[K].GetTitle() << " " << List[K].GetAuthorFirst() << " " << List[K].GetAuthorLast() << " " << List[K].GetPublisher() << " " << List[K].GetPublisherAddress() << " " << List[K].GetPublisherPhone() << " "
<< List[K].GetPublisherContact() << " "<< List[K].GetCategory() << " " << List[K].GetDate() << endl;
};
My whole program is really long, so I dont want to overwhelm you guys by posting the whole thing up..
You may need to change your Book definition to enable searching for multiple authors:
struct Author
{
std::string& get_name() const;
};
struct Book
{
std::vector<Author> m_authors; // A book can have 1 or more authors
bool has_author(std::string author_name) const
{
std::vector<Author>::const_iterator iter;
for (iter = m_authors.begin();
iter != m_authors.end();
++iter)
{
if (iter.get_name() == author_name)
{
return true;
}
}
return false;
};
The objective now is to write a predicate or functor that will call Book::has_author.
This is one solution to your issue, there are probably others when you give it more thought.
You do not give us a lot of informations about what is a "book" and what is a Collection.
But, it seems that you already implement a function that returns you the expected result for one string (the last name of an author).
What you can do is use multiples times your function FindBookAuthorLast with a different last name each time.
Or, implement a function that takes a vector of string in parameters and that returns you a vector of Book (or whatever is your class containing the books).
EDIT :
With the new informations you posted, here is a way to do it :
(This is not the only solution to do it, there is a lot)
(Code not compiled, not tested)
void BookRecordList::FindBookAuthorLast(vector<string> Last)
{
int K;
vector<string>::iterator author_it = Last.begin();
for ( ; author_it != Last.end(); ++author_it)
{
for(K = 0; K < (int)List.size(); K++)
if(List[K].GetAuthorLast() == *author_it)
cout << List[K].GetTitle() << " " << List[K].GetAuthorFirst() << " " << List[K].GetAuthorLast() << " " << List[K].GetPublisher() << " " << List[K].GetPublisherAddress() << " " << List[K].GetPublisherPhone() << " "
<< List[K].GetPublisherContact() << " "<< List[K].GetCategory() << " " << List[K].GetDate() << endl;
}
};
To build the vector<string> to give to the function FindBookAuthorLast, iterate on getline().
Maybe all you want is to loop over your function:
void BookRecordUI::FindBookLast() //allows us to search a book by the last name of the author from the book record...
{
string Last;
do {
cout << "Enter Book by Last Name of Author: " << endl;
getline(cin, Last);
Collection.FindBookAuthorLast(Last);
}
while(!Last.empty());
}
(not tested).